Orchestrata Ultimate › Plans › briefs › qwen › Q1-toolchain-declaration
Q1 — One C/C++ toolchain declaration: finish, test and verify
Source: plans/briefs/qwen/Q1-toolchain-declaration.md at 8a2cb42ad · last changed 2026-10-11 · first committed 2026-10-11 · 187 lines.
Prose pending.
Plan text
Q1 — One C/C++ toolchain declaration: finish, test and verify
| Field | Value |
|---|---|
| Executor | Qwen3.8-max (openrouter/qwen/qwen3.8-max-0902) via opencode run |
| Worktree | /home/mohamed/workspace/wt-BARE-PYTHON — work ONLY inside this directory |
| Branch | fix/bare-interpreter-gate (1 commit c1eebd019 ahead of origin/master 762935ab6) |
| Spec author | orchestrator, 2026-10-11 |
| Your deliverable | the uncommitted change completed, tested and STAGED (not committed) + plans/briefs/qwen/Q1-report.md |
1. Directive and why
Mohamed (verbatim): "make the gcc path a configuration and set it".
On this host ~/.guix-profile/bin leads PATH, so a bare gcc resolves to Guix GCC 16.2.0, and it fails the
vendored janus-swi native build against the system swipl headers (two worktree provisions failed this way,
2026-10-11). Before this change, four places each picked a compiler of their own: .envrc exported the bare
CC=gcc CXX=g++; deploy/install-orchestrata.sh defaulted to bare gcc and re-derived /usr/bin/gcc with a
PATH-shadow probe; deploy/install-tools.sh hardcoded /usr/bin/gcc; scripts/worktree_toolchain.py pinned a
hardcoded /usr/bin/gcc only when shadowed. The change makes one tracked file, env/toolchain.env, the only
place a compiler is named. Every consumer reads it, and every consumer refuses a missing, bare-named or
non-executable compiler rather than fall back to PATH.
Most of the change is already written (by the orchestrator, before this executor model was adopted) and is uncommitted in the worktree. The new tests were written but never run. Your job: complete it, run everything, fix what fails, and stage it.
2. Rules (project law — violations are rejected)
- Never run bare
python,python3,pytestorpip. Alwaysenv -u PYTHONPATH .venv/bin/python ...from the worktree root. (A barepythonon this host resolves to a stale checkout ~530 commits behind.) - uv only; no new dependencies; do not edit
pyproject.toml/uv.lock. - Tests: no
unittest.mock/Mock/MagicMock/patch/monkeypatch, no Fake/Stub/Dummy classes, noskip/skipif/xfail, no xdist. Function-scope fixtures;tmp_pathfor files. The installer tests run the REALbash deploy/install-orchestrata.shwith anenv=dict (that is the injection seam; never mutateos.environ). The existing tests use a recordinguvscript on a fakePATHdirectory: that is an existing real-subprocess seam the project already uses, keep it as is. - Absolute imports only. Never write the word "should" in code, comments or docstrings.
- Never delete a function, test or helper. If one becomes unused, leave it and list it in the report as a removal candidate (only Mohamed authorises removals).
- Git: do NOT commit, push, merge, rebase, reset, stash or switch branches.
git addthe files in §4 at §7 step 4. - Stay inside
/home/mohamed/workspace/wt-BARE-PYTHON. Never touch10.53.1.x(production). Never run the full suite; never runscripts/run_tests.pywithout explicit paths. - If the code contradicts this spec, or a test proves the shipped code wrong, fix the CODE per §3 (never weaken a test). If a design choice here looks wrong, STOP and say why in the report.
3. The design (already implemented — verify it, do not redesign)
env/toolchain.env(NEW, untracked):CC=/usr/bin/gcc,CXX=/usr/bin/g++plus a header comment.deploy/toolchain.sh(NEW, untracked, SOURCED):load_toolchain <declaration-file>readsCC/CXX, refuses (return 1, oneFAIL:line on stderr) when the file is missing (FAIL: no toolchain declaration at <file>), a key is missing (FAIL: <file> declares no CXX), a value is not absolute (... a bare name is resolved from PATH; declare an absolute path) or not executable (..., which is not an executable); on success exportsCC/CXX, unsetsC_INCLUDE_PATHCPLUS_INCLUDE_PATH, printstoolchain: CC=<cc> CXX=<cxx> (from <file>).deploy/install-orchestrata.sh: the old block (baregccdefault + PATH-shadow probe +toolchain override:line) is replaced bysource "$INSTALLER_ROOT/deploy/toolchain.sh"andload_toolchain "${ORCHESTRATA_TOOLCHAIN_ENV:-$INSTALLER_ROOT/env/toolchain.env}" || exit 1, whereINSTALLER_ROOTis the checkout the installer script lives in (NOT$SOURCE_REPO).deploy/install-tools.sh: same loader; the native build passesCC="$CC" CXX="$CXX"through$SUDO env..envrc: theexport CC=gcc/export CXX=g++lines are gone;dotenv "env/toolchain.env"is the LAST line of the file, so neither.envnor a profile overlay can override it.scripts/worktree_toolchain.py:declared_toolchain(path)(raisesToolchainDeclarationError) andpin_system_toolchain(env)(applies the declaration UNCONDITIONALLY, drops the two Guix include vars, printstoolchain: CC=<cc> CXX=<cxx> (from <decl>)plus, dropped C_INCLUDE_PATH[, CPLUS_INCLUDE_PATH]when it dropped any). Declaration =env["ORCHESTRATA_TOOLCHAIN_ENV"]when set, elseDEFAULT_TOOLCHAIN_DECLARATION.scripts/worktrees.py: provisioning calls the above.scripts/build_janus_ft.pyandscripts/build_ft_tree_sitter.py: their_pin_system_toolchainalready delegates toworktree_toolchain.pin_system_toolchain(loaded by file path), so they ALREADY follow the declaration. Their docstrings/comments still describe the old behaviour — fix those words (§4).scripts/hooks/pre-push: banner text only — it describes the already-committedc1eebd019change (anenv/*.envedit resolves to the files naming its keys, never escalates). It is uncommitted: do not edit it, stage it with the rest.
4. What you change
| File | Change |
|---|---|
tests/deploy/test_install_orchestrata_cc.py |
Rewrite the 2 tests below (§5.1). Keep every helper. |
tests/deploy/test_install_orchestrata_toolchain.py |
Rewrite the 2 tests below (§5.2). Keep every helper. Leave test_sync_stage_fails_closed_when_a_locked_path_package_does_not_import unchanged. |
tests/deploy/test_envrc_toolchain.py |
NEW (§5.3). |
scripts/build_janus_ft.py |
Docstring of _pin_system_toolchain and the comment in _build_env ("Pin the system compiler exactly as scripts/worktrees.py does") now state: the compiler comes from the env/toolchain.env declaration via worktree_toolchain.pin_system_toolchain, unconditionally, and a missing/bare/non-executable declaration raises ToolchainDeclarationError (the build is refused). No logic change. |
scripts/build_ft_tree_sitter.py |
Same for its _pin_system_toolchain docstring and _build_env docstring. No logic change. |
| any file in §3 | ONLY if a test in §6 proves it wrong; say so in the report. |
plans/briefs/qwen/Q1-report.md |
NEW — your report. |
Stage at the end: everything in §3 and §4 that is modified or new (git status --porcelain lists them), EXCEPT
plans/briefs/qwen/ and any generated file you did not edit by hand (docs/CODEBASE_MAP*.md, plans/ast-*.json,
context.json, reports/* — if they appear modified, leave them unstaged and list them in the report).
5. Tests
Read first: the two test modules in full, and tests/deploy/_install_orchestrata_support.py. The installer test
harness already exists: run_install(tmp_path, source_repo, ...args, env_overrides={...}) runs the real installer
with --bootstrap-only; _write_recording_uv(fakebin, record_file) puts a uv first on PATH that records the
CC, CXX and C_INCLUDE_PATH it was called with (<unset> when unset) instead of syncing. INSTALLER_ROOT in
these runs is THIS worktree, so the declaration read by default is THIS worktree's env/toolchain.env
(CC=/usr/bin/gcc, CXX=/usr/bin/g++).
5.1 tests/deploy/test_install_orchestrata_cc.py
- Replace
test_sync_stage_exports_cc_and_cxx_with_gcc_defaultwithtest_sync_stage_uses_the_declared_compilers: noCC/CXXin the installer environment, PATH from_path_with_only_system_gcc(fakebin). Assert: rc 0 for the bootstrap stage reached (record_fileexists), recordedCC=/usr/bin/gccandCXX=/usr/bin/g++, and stdout containstoolchain: CC=/usr/bin/gcc CXX=/usr/bin/g++ (fromfollowed by the path of this worktree'senv/toolchain.env(compute it from the test file's location:Path(__file__).resolve().parents[2] / "env" / "toolchain.env"). Docstring: WHY (a systemd user unit has no direnv; the compiler comes from the declaration, never from PATH). - Replace
test_sync_stage_fails_closed_without_a_compiler_on_pathwithtest_sync_stage_refuses_an_unusable_declaration, parametrized over 3 cases, each pointingORCHESTRATA_TOOLCHAIN_ENV(viaenv_overrides) at a file you write undertmp_path:missing: the path does not exist → stderr/stdout containsFAIL: no toolchain declaration at;bare-name:CC=gcc\nCXX=g++\n→ containsa bare name is resolved from PATH;not-executable:CC=<tmp_path>/no-such-cc\nCXX=/usr/bin/g++\n→ containswhich is not an executable. For every case assertreturncode != 0andnot record_file.exists()(provesuv syncnever ran). Use the real PATH plusfakebinfirst (the declaration, not PATH, decides).
5.2 tests/deploy/test_install_orchestrata_toolchain.py
- Replace
test_sync_stage_pins_system_gcc_when_shadowedwithtest_a_shadowing_gcc_on_path_does_not_change_the_compiler:_fakebin_with_shadow_gcc(fakebin)first on PATH andC_INCLUDE_PATH=/tmp/leakinenv_overrides. Assert recordedCC=/usr/bin/gcc,CXX=/usr/bin/g++,C_INCLUDE_PATH=<unset>, stdout containstoolchain: CC=/usr/bin/gcc, andtoolchain override:appears NOWHERE in the output (the PATH probe no longer exists). - Replace
test_sync_stage_no_override_when_gcc_already_systemwithtest_an_inherited_bare_cc_is_overridden_by_the_declaration:env_overrides={"PATH": _path_with_only_system_gcc(fakebin), "CC": "gcc", "CXX": "g++"}. Assert recordedCC=/usr/bin/gccandCXX=/usr/bin/g++(an inherited bareCC=gccis exactly what.envrcused to export, and it is the failure this change removes)._path_with_only_system_gccis defined intest_install_orchestrata_cc.py; reuse the existing import pattern of this module (read its import block — it already imports from that module or from_install_orchestrata_support; do not duplicate the helper).
5.3 tests/deploy/test_envrc_toolchain.py (NEW)
Text-level contract tests over the repo's real .envrc (it is a shell file, not Python; reading it is correct):
test_envrc_exports_no_compiler: no line matching^\s*export\s+(CC|CXX)=exists.test_envrc_loads_the_toolchain_declaration_last: the LAST line that callsdotenv(ignore comments/blank lines) is exactlydotenv "env/toolchain.env".test_the_declaration_names_absolute_executables: parseenv/toolchain.envwithworktree_toolchain.declared_toolchain(import it the waytests/scripts/test_worktrees_provision.pydoes) and assert both values are absolute and executable on this host. Header docstring with WHY and the Test Standards Compliance block (copy the shape fromtests/deploy/test_toolchain_sh.py).
6. Run — exact commands, in order, from the worktree root
- Every directly affected module, fast and infrastructure-free:
All pass, 0 skipped.env -u PYTHONPATH .venv/bin/python -m pytest -q -p no:cacheprovider \ tests/deploy/test_toolchain_sh.py tests/deploy/test_envrc_toolchain.py \ tests/deploy/test_install_orchestrata_cc.py tests/deploy/test_install_orchestrata_toolchain.py \ tests/scripts/test_worktrees_provision.py tests/scripts/test_build_janus_ft.py \ tests/scripts/test_build_ft_tree_sitter.pytest_toolchain_sh.pyandtest_worktrees_provision.pywere written but NEVER run: expect failures there and fix them (a test asserting the §3 behaviour is right; a test asserting something §3 does not say is wrong — report which and why). - Real behaviour, outside pytest (paste outputs into the report):
bash -c 'source deploy/toolchain.sh && load_toolchain env/toolchain.env && echo "CC=$CC CXX=$CXX CIP=${C_INCLUDE_PATH-unset}"'env C_INCLUDE_PATH=/tmp/leak CC=gcc .venv/bin/python -c 'import os, sys; sys.path.insert(0, "scripts"); import worktree_toolchain as t; e = t.pin_system_toolchain(dict(os.environ)); print(e["CC"], e["CXX"], "C_INCLUDE_PATH" in e)'→ expect atoolchain: ... dropped C_INCLUDE_PATHline, then/usr/bin/gcc /usr/bin/g++ False.
- Lint/format the Python files you changed:
env -u PYTHONPATH .venv/bin/python -m ruff check --fix <files>thenenv -u PYTHONPATH .venv/bin/python -m black <files>;bash -n deploy/toolchain.sh deploy/install-orchestrata.sh deploy/install-tools.sh. - Stage (§4 rule), then
git status --porcelainand paste it. - Review gate exactly as the pre-commit hook runs it:
env -u PYTHONPATH .venv/bin/python scripts/gate.py review-staged; echo "review rc=$?"→ must be 0. rc 1: fix the findings and repeat. rc 2: report the reasons, stop. - Bounded run over the blast radius. Another executor works in a sibling worktree and runs its own bounded
run; two at once overload the shared test fleet. So FIRST wait until no other run is in progress (bounded,
60 min):
timeout 3600 bash -c 'while pgrep -f "scripts/run_tests.py" >/dev/null; do sleep 15; done'; echo "wait rc=$?"(rc 124 = still busy after 60 min: STOP and report). Then resolve, then run exactly those paths:
Required before running:env -u PYTHONPATH .venv/bin/python scripts/affected_tests.py --json --files $(git diff --cached --name-only | tr '\n' ' ') > .q1-affected.json env -u PYTHONPATH .venv/bin/python scripts/run_tests.py $(env -u PYTHONPATH .venv/bin/python -c 'import json; print(" ".join(json.load(open(".q1-affected.json"))["tests"]))'); echo "run rc=$?" rm .q1-affected.json"escalate": false,"untested": [](anenv/*.envfile resolves to the files that name its keys —CC/CXX— per commitc1eebd019; if it escalates anyway, STOP and paste the reasons). The run must end 0 failed, 0 errors, rc 0. ONE run; do not start a second while one is in progress.
7. Done when — then write plans/briefs/qwen/Q1-report.md
- [ ] §6.1 passes, 0 skipped; §6.2 outputs as expected.
- [ ] ruff/black clean;
bash -nclean on the three shell files. - [ ] only §4-allowed files staged;
gate.py review-stagedrc 0. - [ ] §6.6 resolver did not escalate; the run is rc 0, 0 failed, 0 errors.
Report (plain facts, no "should"): each file changed and why; every test you had to fix in the pre-written modules and whether the code or the test was wrong; §6 outputs; any helper that became unused; anything in this spec you found wrong.