Orchestrata Ultimate › Gates › codetools-gates
Gate: codetools-gates
At a glance
| Purpose | Prove a codetools master commit once per batch (install, verify, promote) inside a provisioned container, under a 300 s target, with the scope chosen by selection rather than the full suite. |
| Where it runs | The codetools repo (/home/mohamed/workspace/orchestrata.codetools, src/codetools/gate/), deployed at /opt/codetools/bin/codetools. Designed to run from a systemd user timer codetools-gate.timer (src/codetools/gate/units.py). |
| Trigger | The timer ticks OnBootSec=1min / OnUnitActiveSec=30s and runs codetools gate run --once; MasterWatch compares git rev-parse master with the sha of the last DONE batch record (master_watch.py docstring). |
| Exact commands | codetools gate provision [--units] [--repo R] [--state S] · codetools gate readiness [--repo R] · codetools gate run --once [--repo R] [--state S] [--records D] [--ref REF] [--workers N] [--scope affected|full] [--reason TEXT] · codetools gate cpuset [--apply] [--repo R] · codetools gate status [--repo R] [--state S] [--records D] (all from --help, 2026-10-23). |
| Blocks | A red probe is refusal class infra and nothing runs (readiness.py); a red batch is bisected over the merge list since the last green (batch_runner.py); an affected batch with no full verify record refuses naming the missing baseline (schedule.py). |
| Ruling / ADR | codetools register (repo paths, not orchestrata's decisions page): docs/adr/0004, 0023, 0024, 0025, 0033, 0036, 0039, 0040, 0042, 0043 (Proposed), 0044. Orchestrata side: RUL-040, RUL-032. |
These gates are separate from orchestrata-ultimate's own commit and push gates. They
verify codetools, the deployed toolkit orchestrata consumes (codetools ast map
for the codebase maps, codetools deploy select-affected for RUL-040's oracle seam).
See codetools for the project itself.
Current state on this host (measured 2026-10-23, listing only)
systemctl --user list-unit-fileslists nocodetools-gate.timerorcodetools-gate.service, so the timer path is not installed here./opt/codetools-gatedoes not exist.incus list --all-projectsshows the installer containerct-installer-testas STOPPED./var/tmp/ct-3b(the batch-record directory the 2026-10-13/14 ADRs cite) does not exist any more.- What does run is the ct-install launcher (below), whose last two logs end
SMOKE-OK … WALL 26s INSTALL-EXIT 0(install 73,e1ffbc36) andSMOKE-OK … WALL 43s INSTALL-EXIT 0(install 75,a5c419f5), inorchestrata.codetools/reports/ct8-install7{3,5}.log.
So today the batch runner is designed, built and documented but not scheduled on this machine. Whether a batch has run since 2026-10-14 is not measured.
How a batch runs
From the module docstrings of batch_runner.py, schedule.py, readiness.py,
cpuset.py and provisioner.py:
What each verb checks
gate provision
Idempotent provisioning of the installer container from env/contract.toml:
"one step per contract item … nothing for what the contract does not declare.
Every step probes first and acts only on the difference" (provisioner.py). It
writes /opt/codetools-gate/PROVISION.json with the sha256 of the contract it
satisfied. --units also installs the timer.
gate readiness
"The gate's readiness probes, run before ANY batch, derived from
env/contract.toml — one probe per contract item, none that is not an item …
the container must be RUNNING, its PROVISION.json must record the hash of THIS
contract, and every item's probe must pass inside it" (readiness.py).
The contract (env/contract.toml, ADR-0039) declares 13 items today:
batch-user (uid 1100, not root), locale (C.UTF-8), tool-uv,
tool-python, tool-ruff, tool-git, tool-swipl, user-manager
(a systemd --user for the gate user), basetemp-root, tmp-hygiene,
endpoint-memgraph, capacity (performance_cores_unshared = 4,
efficiency_cores = 4) and schedule (full_every_merges = 10). Each item's
comment names the 2026-10-13 incident behind it: batch 1 ran as root with the C
locale (410 s, 8 red tests), batch 2 found a stale /tmp trace file and no user
manager (671 s, 10 red tests) — ADR-0039's context table.
gate cpuset
Derives the container's limits.cpu from the declared capacity and the sysfs
topology: performance cores first, one thread per physical core so no worker
shares a core, then efficiency cores; workers equals the unshared performance
cores (cpuset.py, ADR-0040 rule 3). ADR-0040 records why: on the i7-1260P the
container's "12 CPUs" were about 3 performance and 7 efficiency cores, and the
same suite cost 4,355–4,830 CPU-seconds inside against 2,155 on the host.
--apply sets it.
gate run --once
One batch, as in the diagram. Scope rules:
- Per merge:
affected(ADR-0040 rule 1, 300 s target), selected "against the newest full verify record on the executor whatever its outcome (ADR-0042)". ADR-0042's rule set, verbatim from Mohamed: "tests that are not changed or test changed code or blast radius rule"; "every run must attach to a tag or baseline". A full batch is never a prerequisite. - Scheduled:
fullwhenfull_every_mergesmerges have landed, when the merge touchedsrc/codetools/testing/{pool,shard_plan,runner}.pyorsrc/codetools/deploy/*select*.py, or on--scope full(schedule.py,FULL_TRIGGER_PATHS).--reasonrecords why an explicit scope was chosen. - The runner is "the single writer of the verify record, the run-once ledger and
the promote for the gate prefix" (
batch_runner.py); a second runner exitscoalesced(ADR-0036 rule 2). - Reuse: the
testverb keeps ADR-0024/0042 selection, then reuses any in-scope test whose (id, content key) has a passing row in the shared ledger (ADR-0044, composing with orchestrata's ADR-0088 — decisions).
gate status
Prints the last batch record.
Related codetools gates outside codetools gate
| Gate | What it does | Source |
|---|---|---|
codetools deploy select-affected |
"bound a changed-file set to a measured selection from a facts document on stdin (RUL-040 fail-closed JSON contract)": exit 0 bounded, 2 named refusal, 1 tool error; "never a bare full run" | codetools deploy --help; commit 8f82f29f (2026-10-20). Orchestrata's P-RUL040 Stage 0 adjudication e7570a88d chose it as the seam; whether orchestrata's run_tests.py --affected calls it today is not measured. |
Review gate (inside deploy install verify) |
Runs the ruff pinned beside the interpreter before PATH's, so a hook or unit with a bare PATH still finds ruff==0.15.12 |
commit 129d419f (2026-10-22) |
| Live-systemd lock | Serialises every test that drives the real systemd --user; ADR-0033 narrows it to each live call |
commit b52409af (2026-10-13), docs/adr/0033-* |
| ct-install post-promote checks | After codetools deploy install … --no-verify, runs codetools deploy verify-identity --prefix /opt/codetools --expect-commit <sha> and ~/bin/ct-smoke <sha> (version names the commit; ast map maps a 3-symbol repo with class Child(Base); mcp list has the ast map tool). Either failing runs codetools deploy rollback and exits 12. |
~/bin/ct-install lines 50–66, ~/bin/ct-smoke |
The ct-install path is the "Hermes model" Mohamed asked for on 2026-10-22 ("make
the installer like hermes"): no suite gate at deploy time, proof through the
installed command instead. The suite-gated verify stays available by running
codetools deploy install by hand (~/bin/ct-install header, lines 43–49).
Prolog as the decision layer
ADR-0004 (Accepted, 2026-09-24): "the gates including the blast radius logic …
designed, built and run in prolog". ADR-0023 (Proposed, amended): every
deterministic gate's decision is a Prolog rule set; "Python atoms gather the data
for speed, Prolog decides"; every gate verb supports --explain.
Typical failures and how to fix them
| Symptom | Cause (source) | Fix |
|---|---|---|
Batch refused infra naming an item |
A contract probe failed inside the container, or PROVISION.json records a different contract hash (readiness.py) |
codetools gate provision, then codetools gate readiness |
affected batch refuses with a missing baseline |
No full verify record with coverage contexts on this executor (schedule.py, ADR-0042 rule 4) |
ADR-0024's one bootstrap run per executor, recorded as the first baseline; never a silent full run |
| Thermal refusal | Capacity/thermal state outside the declaration (REQ-012-049 in batch_runner.py; ADR-0040 measured a 96 °C package, ADR-0043 a 100 °C package at a 394 MHz clock floor) |
Wait, or run on an executor that meets ADR-0040 rule 4 |
Batch exits coalesced |
Another batch holds the lock (ADR-0036 rule 2) | Nothing: the merge joins the next batch |
ct-install INSTALL-EXIT 12 and ROLLED-BACK |
verify-identity or ct-smoke failed after promote (~/bin/ct-install) |
Read the log in reports/ct8-install<label>.log; fix and re-run with a new label |
Install refused at verify on PYTHONPATH |
The Claude settings env exports PYTHONPATH=/opt/orchestrata-tools/shim, which codetools' import-shadow guard refuses (install 68, commit 6979a4ad) |
ct-install now unsets PYTHONPATH PYTEST_ADDOPTS; do the same for any hand run |