Version
dev (built from source at 7719563)
Platform
Linux (x64)
Install channel
Built from source
Binary variant
standard
What happened, and what did you expect?
CONTRIBUTING.md lists the prerequisites as "C compiler (gcc or clang), make,
zlib, Git" (plus optional Node for the graph UI). README.md says the same.
In a container with exactly those, scripts/build.sh succeeds — it
produces build/c/codebase-memory-mcp — but scripts/test.sh and
scripts/lint.sh cannot run. So the documented set is precisely enough to
build and not enough to do anything else CONTRIBUTING.md then asks for.
Six more tools are required and are not mentioned anywhere in the contributor
docs:
| Tool |
Required by |
zip |
test.sh Step 0o → scripts/package-release.sh (MCPB bundles) |
python3 |
Makefile.cbm:978, CBM_DAEMON_SMOKE_REQUIRE_RUN=1 python3 tests/test_daemon_smoke.py (and :1238 for the lint-mem gate) |
cppcheck |
lint.sh, both modes |
clang-format |
lint.sh, both modes |
clang-tidy |
lint.sh full mode |
curl |
src/cli/cli.c cbm_download_to_file(); exercised by tests/test_cli.c:1683 |
I expected the documented prerequisites to be sufficient to run the test and
lint scripts that CONTRIBUTING.md goes on to describe.
The reason this is worth a report rather than a shrug is the failure shape.
None of them fails in a way that says "missing tool":
-
The build-time ones die inside test.sh's numbered preflight contracts
after printing thirteen PASS lines, exiting 2 — and lint.sh exits 2 via
make ... Error 127. That is the same exit shape as a genuinely red tree. I
recorded it as "the baseline has failures" and only caught the mistake
because both scripts had finished in 66 seconds.
-
curl is worse. The suite builds and runs normally, then fails exactly one
test roughly 300 lines in:
FAIL tests/test_cli.c:1683: rc == 1, expected 0 == 0
The only clue is error: download failed (exit 127) earlier in the log. 127
is execvp failing to find the binary — cbm_download_to_file() builds
{"curl", "-fSL", ...} and hands it to cbm_exec_no_shell(). Note this test
needs curl even with networking fully disabled, because it drives the update
flow against a file:// CBM_DOWNLOAD_URL.
Installing curl and changing nothing else: 276 passed, 0 failed.
This is invisible from inside CI because GitHub's runners preinstall all of
them, so nothing in the workflows has to name them. There is some precedent for
the curl half specifically: #901, #904, #905 and #1285 all deal with curl
availability in constrained environments (Windows smoke, Alpine), each resolved
by installing it there rather than by recording it as a dependency.
Reproduction
A container with exactly the documented prerequisites and nothing else:
FROM ubuntu:26.04
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
build-essential zlib1g-dev git ca-certificates
WORKDIR /src
docker build -t cbm-prereq-repro .
docker run --rm -v "$PWD:/src" -w /src cbm-prereq-repro scripts/build.sh; echo "BUILD_EXIT=$?"
docker run --rm -v "$PWD:/src" -w /src cbm-prereq-repro scripts/test.sh; echo "TEST_EXIT=$?"
docker run --rm -v "$PWD:/src" -w /src cbm-prereq-repro scripts/lint.sh; echo "LINT_EXIT=$?"
BUILD_EXIT=0 — the binary is produced.
Both exit 2 in about a minute — fast enough that the speed is the only hint the
failure is environmental rather than a red tree. Adding zip, python3,
clang-tidy, cppcheck and clang-format gets the suite running; adding
curl as well gets it green.
Logs
The curl case, since it is the least obvious.
Without curl — scripts/test.sh --suites "daemon_runtime cli":
error: download failed (exit 127)
FAIL tests/test_cli.c:1683: rc == 1, expected 0 == 0
319 passed, 1 failed
With curl installed and nothing else changed — --suites cli, i.e. just the
suite containing that test:
(The two runs cover different suite selections, so the totals are not directly
comparable; the point is that the single failure disappears and the cli suite
is clean.)
Suggested fix
A docs-only change — no logic, no behaviour:
- extend the prerequisites line in
CONTRIBUTING.md (and the matching
README.md text) to cover them;
- optionally split them by purpose, since not every contributor runs
everything: test.sh needs zip, python3 and curl; lint.sh needs
cppcheck and clang-format, plus clang-tidy for full mode.
Happy to open that PR if you'd like it.
Confirmations
Investigated with Claude Code; reproductions and logs are from real runs, not
generated.
Version
dev (built from source at 7719563)
Platform
Linux (x64)
Install channel
Built from source
Binary variant
standard
What happened, and what did you expect?
CONTRIBUTING.mdlists the prerequisites as "C compiler (gcc or clang), make,zlib, Git" (plus optional Node for the graph UI).
README.mdsays the same.In a container with exactly those,
scripts/build.shsucceeds — itproduces
build/c/codebase-memory-mcp— butscripts/test.shandscripts/lint.shcannot run. So the documented set is precisely enough tobuild and not enough to do anything else
CONTRIBUTING.mdthen asks for.Six more tools are required and are not mentioned anywhere in the contributor
docs:
ziptest.shStep 0o →scripts/package-release.sh(MCPB bundles)python3Makefile.cbm:978,CBM_DAEMON_SMOKE_REQUIRE_RUN=1 python3 tests/test_daemon_smoke.py(and:1238for the lint-mem gate)cppchecklint.sh, both modesclang-formatlint.sh, both modesclang-tidylint.shfull modecurlsrc/cli/cli.ccbm_download_to_file(); exercised bytests/test_cli.c:1683I expected the documented prerequisites to be sufficient to run the test and
lint scripts that
CONTRIBUTING.mdgoes on to describe.The reason this is worth a report rather than a shrug is the failure shape.
None of them fails in a way that says "missing tool":
The build-time ones die inside
test.sh's numbered preflight contractsafter printing thirteen
PASSlines, exiting 2 — andlint.shexits 2 viamake ... Error 127. That is the same exit shape as a genuinely red tree. Irecorded it as "the baseline has failures" and only caught the mistake
because both scripts had finished in 66 seconds.
curlis worse. The suite builds and runs normally, then fails exactly onetest roughly 300 lines in:
The only clue is
error: download failed (exit 127)earlier in the log. 127is
execvpfailing to find the binary —cbm_download_to_file()builds{"curl", "-fSL", ...}and hands it tocbm_exec_no_shell(). Note this testneeds
curleven with networking fully disabled, because it drives the updateflow against a
file://CBM_DOWNLOAD_URL.Installing
curland changing nothing else: 276 passed, 0 failed.This is invisible from inside CI because GitHub's runners preinstall all of
them, so nothing in the workflows has to name them. There is some precedent for
the
curlhalf specifically: #901, #904, #905 and #1285 all deal withcurlavailability in constrained environments (Windows smoke, Alpine), each resolved
by installing it there rather than by recording it as a dependency.
Reproduction
A container with exactly the documented prerequisites and nothing else:
BUILD_EXIT=0— the binary is produced.Both exit 2 in about a minute — fast enough that the speed is the only hint the
failure is environmental rather than a red tree. Adding
zip,python3,clang-tidy,cppcheckandclang-formatgets the suite running; addingcurlas well gets it green.Logs
The
curlcase, since it is the least obvious.Without
curl—scripts/test.sh --suites "daemon_runtime cli":With
curlinstalled and nothing else changed —--suites cli, i.e. just thesuite containing that test:
(The two runs cover different suite selections, so the totals are not directly
comparable; the point is that the single failure disappears and the
clisuiteis clean.)
Suggested fix
A docs-only change — no logic, no behaviour:
CONTRIBUTING.md(and the matchingREADME.mdtext) to cover them;everything:
test.shneedszip,python3andcurl;lint.shneedscppcheckandclang-format, plusclang-tidyfor full mode.Happy to open that PR if you'd like it.
Confirmations
Investigated with Claude Code; reproductions and logs are from real runs, not
generated.