Skip to content

feat(harness): a build-test-fix cycle for every component - #51

Merged
tmttodd merged 3 commits into
mainfrom
harness/per-component
Oct 24, 2026
Merged

tmttodd merged 3 commits into
mainfrom
harness/per-component

Conversation

@tmttodd

@tmttodd tmttodd commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

What this is

Every Corvus component now has a real build > test > fix harness, and CI runs all of them.
The interpreter is pinned to 3.12 and ruff to 0.17.1 inside every venv, so local and CI
finally agree on what a green run means.

make cycle at the repo root is the one command. Per component: make -C <component> cycle.

Per component

Component Targets Evidence on this branch
corvus-v2 setup build lint test fix metrics metrics-check run check cycle mutation conformance clean build ok (health + auth + 401); 90 tests; 73.0%; metrics fresh; mutation: all mutants caught; conformance: 2 passed 0 failed
corvus-sdk setup build lint test fix cycle clean 54 tests (was 35); client.py 100%, models.py 100%
corvus-cli setup build lint test fix cycle clean 50 tests (was 0); main.py 100%, config.py 100%
corvus-server setup lint import fix cycle clean lint clean; real import on 3.12.15 (soc2 APIRouter, typer app 11 commands)
corvus-hooks setup lint import fix cycle clean lint clean; 8 scripts byte-compiled; corvus_core imports
corvus-splunk setup validate cycle clean 6 conf, 5 xml, 3 csv, 1 py validated

The fix target is proven, not just declared: inject a ruff-fixable violation, make fix,
make lint passes, and the file is byte-identical to HEAD afterwards. make fix on a clean
tree is a no-op.

Two real bugs the harness surfaced

  1. The metrics drift guard could not see the drift that had happened. The committed
    dev-metrics.json claimed 108 tests / 79.1% / 1274 lines; a fresh 3.12 run is 90 tests /
    73.0% / 1277. The old guard compared only coverage percent (tolerance 7.0) and line totals,
    so the 108-vs-90 test drift passed silently. It now gates the test count exactly, and the
    tolerance is 1.0 because the interpreter is pinned on both sides.
  2. The P1 capability gate was never gated. BUILD-PLAN.md requires "the conformance suite
    runs green in CI with the mutation evidence". At HEAD, ci-v2.yaml ran neither. There is now
    a phase-gates job that runs both.

Please read before merging

ruff --fix repaired 26 pre-existing violations in the archived corvus-hooks scripts
(7 files, +16/−19). They are mechanical and behavior-preserving — IOError is OSError
(the same object), and the Optional/Dict → X | None changes are under
from __future__ import annotations so they never evaluate at runtime. But they are a diff on
archived v1 code, and they are in this PR because otherwise the new lint guard would ship red.

What the harness does not prove

docs/DEV-READINESS-REVIEW.md maps the plan and vision against the current state, with every
claim instrumented. The sharpest findings:

  • The clients speak v1. The deployed container runs corvus.engine_shim (Dockerfile:21),
    which serves one route. The SDK's 100% coverage and the CLI's 100% coverage are against
    mocked HTTP: 27 of the SDK's 30 /ops paths and 12 of the CLI's 15 are not served by v2.
    Green here proves the client's own logic, not parity.
  • The trust ledger is unwired. TrustLedger has no importer and nothing writes ops_trust,
    so every live conflict answer carries the default ESCALATE. Capability 3 (graded autonomy)
    is not on the deployed path.
  • The live capture store is an emptyDir — decision records do not survive a pod restart.

None of these are fixed here. They are named so the next goal starts from evidence.

Rollback

Revert the merge commit; the tree returns to the pre-PR state. No data is migrated or deleted.

Closes nothing — the follow-ups above are deliberately out of scope.

Every component now owns setup/build/lint/test/fix/cycle in its own Makefile
and the root Makefile is the umbrella. The interpreter is pinned to 3.12 and
ruff to 0.17.1 inside every venv, so local and CI finally agree.

- corvus-v2: the harness moves into corvus-v2/Makefile and gains the "fix"
  target the old "Build > Test > Fix" comment promised but never had. "build"
  is now a real proof (health + authenticated read + the 401 control) in
  scripts/dev_check.py. Deps floored at the tested versions, capped at the
  next major.
- corvus-sdk: new harness; 54 tests (was 35), client.py and models.py at 100%.
- corvus-cli: new harness; 50 tests from zero, main.py and config.py at 100%.
- corvus-server / corvus-hooks: lint + import guards only. v1 is archived at
  v1-archive and not deployed; no tests are resurrected for it.
- corvus-splunk: config validation (conf/xml/csv/py).
- CI: a matrix over all six components, plus a phase-gates job for the
  mutation and conformance targets that BUILD-PLAN.md requires of CI but that
  CI had never run.

The metrics drift guard now gates the test count. It previously compared only
coverage percent (tolerance 7.0) and line totals, so the committed
108-tests/79.1% file passed against a 90-test/73.0% run. The tolerance is
recalibrated to 1.0 now that the interpreter is pinned on both sides.

Also: ruff --fix repaired 26 pre-existing violations in the archived
corvus-hooks scripts. They are mechanical and behavior-preserving
(IOError->OSError is the same object; Optional/Dict -> X | None under
"from __future__ import annotations"), but they are a real diff on archived
code, called out here so a reviewer sees them coming.

docs/DEV-READINESS-REVIEW.md: the plan and vision against what the harness can
prove today, with every claim instrumented.
…ed its own shell

Two measured defects in the v2 conformance target, both found by running it in CI:

1. It cleaned up with pkill -f "engine_shim --port 8933". The recipe's own shell
   carries that string in its argv, so pkill matched the shell and killed it: the
   run passed 2/0 and make then reported "Terminated", exit 2 (CI 40058979560).
   It now kills the shim by PID.
2. It bound a fixed 8933. This host runs a launchd agent
   (com.themillertribe.corvus-v2-engine) already bound to 127.0.0.1:8933 from a
   different worktree, so a local "pass" was evidence about that process, not this
   code. The port is now ephemeral and a shim that fails to start fails loudly.

Recorded both in docs/DEV-READINESS-REVIEW.md as blind spots.
@tmttodd
tmttodd merged commit be0ba58 into main Oct 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant