Remove the debt artifacts and put the Rust suite under an automatic gate - #284
Merged
Conversation
The project is in release stage, where technical-debt artifacts do not belong in the tree. #283 added four audit ledgers, a remediation plan, and python/tests/test_structural_debt_ceilings.py, whose ceilings of 105 unreferenced public functions, 185 silent WCOJ declines and 107 environment names record a debt level as acceptable rather than remove it. ENGINEERING.md gained a paragraph stating the same inside the binding contract. All of it is reverted. Audit findings are tracked outside the release repository, one issue per finding, and each is closed by the change that fixes it: the counts go to zero, and the tests that hold them there assert zero rather than a ceiling. The wording about the two kinds of WCOJ decline is reverted with the rest. It states an observability requirement the dispatcher does not meet today, so it belongs in the same change as the counter that satisfies it, not ahead of it. .cargo/config.toml from the same pull request is kept: it repairs a real defect (cargo unusable outside Linux) rather than recording one.
…ice crates cargo test --workspace --all-targets --release ran under workflow_dispatch alone, so it ran when somebody remembered to press the button. A regression once sat on main until an outside run happened to find it. It now runs on a nightly schedule against main. The workspace suite takes up to two hours, which is too long to put on a pull request, so cuda-slice runs the two crates whose purpose is the device -- including the certification suite in xlog-gpu/tests -- on every pull request from this repository. It carries no path filter on purpose: a filter deciding which pull requests get GPU coverage leaves whatever it misses unchecked, which is the mechanism that produced the regression above. A scheduled failure opens an issue, or comments on the open one when a previous night already failed. A nightly run whose failure reaches nobody is a cron job, not a gate. Two details the schedule exposed. The change classifier rejected any event it did not recognise, so a scheduled run would have failed in its first job before reaching the tests. And the concurrency key grouped by ref alone, so a push to main would have cancelled a nightly run already an hour in. python/tests/test_ci_workflow_contract.py asserts the whole shape, including the absence of a path filter on cuda-slice. Making cuda-slice and python-wheel-gpu required checks is a ruleset change and is not part of this commit.
report-scheduled-failure fired on failure(), which excludes a cancellation. A job that no self-hosted CUDA runner accepts stays queued until GitHub's 24-hour limit and is then cancelled, so the one outcome meaning "the nightly did not run at all" was the one that reported nothing. That is not hypothetical. The CUDA runner has accepted no job since 2026-08-28T10:38Z: the next GPU job after that sat queued for exactly 24 hours and was cancelled, and both GPU jobs on this pull request have been queued for hours without starting. The condition is now "some dependency did not succeed", with always() so the job still runs after a cancelled dependency, and the issue body carries each dependency's actual result instead of asserting a test failure. The contract test asserts the new shape and rejects the old one.
artifact_gate.jsonl holds three records of an agent gate -- timestamps and empty lists -- written by tooling that lives outside this repository. It is internal state, not part of the product, and a release tree should not carry it. It also caused a concrete problem twice: the writer appends to it while a checkout sits idle, so any working tree accumulates an uncommitted change to a tracked file and ordinary git operations refuse to switch branches. Untracked rather than deleted, and added to .gitignore: the local file survives for whatever writes it, and git stops noticing.
The audit ledgers, the remediation plan and the telemetry file were removed earlier in this pull request, but nothing stopped them coming back: they still sit untracked in working copies, so an ordinary `git add -A` would recommit them. The same is true of the analysis scratch directory, generated clippy reports, handoff notes and worktree directories created inside the checkout. They are now named in .gitignore. Findings are tracked outside this repository, one issue per finding, and a release tree carries none of them. Contributor-facing rules are deliberately untouched: AGENTS.md, CLAUDE.md, CONTRIBUTING.md, ENGINEERING.md, ROADMAP.md and docs/DOCS-PROTOCOL.md state what a change must satisfy rather than what our current state happens to be, which is the line this commit draws.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The project is in release stage, where technical-debt artifacts do not belong in
the tree. This reverts the part of #283 that recorded debt, and replaces the
mechanism it stood in for: instead of capping three debt classes at their
current size, the Rust test suite now runs under a gate that catches whatever
grows.
Removing the debt artifacts
#283 added 1725 lines. 1696 of them recorded debt rather than removed it:
docs/;python/tests/test_structural_debt_ceilings.py, whose ceilings of 105unreferenced public functions, 185 silent WCOJ declines and 107 environment
names assert that this much debt is an acceptable release state;
ENGINEERING.mdsaying the same inside the binding contract.All of it is gone. Findings are tracked outside the release repository, one
issue per finding, and each is closed by the change that fixes it — the counts
go to zero, and the tests that hold them there assert zero rather than a
ceiling.
The wording about the two kinds of WCOJ decline is reverted with the rest. It
states an observability requirement the dispatcher does not meet today, so it
belongs in the same change as the counter that satisfies it, not ahead of it.
.cargo/config.tomlfrom the same pull request is kept: it repairs a realdefect —
cargounusable outside Linux — rather than recording one.Putting the Rust suite under a gate
cargo test --workspace --all-targets --releaseran underworkflow_dispatchalone, so it ran when somebody remembered to press the button. That is the
mechanism by which a broken test once sat on
mainuntil an outside runhappened to find it.
rust-testsnow runs on a schedule (0 2 * * *) againstmain,in addition to
workflow_dispatch.cuda-slicejob runscargo test --all-targets --release -p xlog-cuda -p xlog-gpuon the CUDArunner — the two crates whose entire purpose is the device, including the
certification suite in
xlog-gpu/tests. The whole workspace is too long for apull request; this part is not.
cuda-slice, deliberately. A filter deciding which pullrequests get GPU coverage leaves whatever it misses unchecked, which is the
same class of mechanism as the button above.
report-scheduled-failureopens an issue, orcomments on the open one when a previous night already failed. A nightly run
whose failure reaches nobody is a cron job, not a gate.
Two defects surfaced while wiring the schedule and are fixed here. The change
classifier rejected any event it did not recognise, so a scheduled run would
have failed in its first job before reaching the tests. And the
concurrencykey grouped by ref alone, so a push to
mainwould have cancelled a nightly runalready an hour in.
Verification
python/tests/test_ci_workflow_contract.pygains a test asserting the wholeshape: the cron entry,
schedulein therust-testscondition,cuda-sliceon the CUDA runner for same-repository pull requests, the absence of a
path filter on it, the issue-reporting job's
issues: writepermission, andthe event name in the concurrency group.
schedulefrom therust-testscondition fails the test, and adding
needs: cuda-changestocuda-slicefails it. Tree restored after each.
evaluate_python_wheel_gatesimulated forschedule: passes on GPU success,fails on GPU failure.
test_cuda_change_classifier_cli_consumes_null_delimited_git_paths, whichfails on
maintoo and only off Linux (CRLF fromprint()); it is a separatefinding with its own fix, not introduced here.
.cargo/config.toml. No dangling references to the deleted files remain.Not measured: how long
cuda-slicetakes. No GPU on the machine this waswritten on. The 60-minute timeout is generous on purpose; this pull request is
its first real run.
Follow-up that is a ruleset change, not a commit
protect-mainrequires nine checks and none of them is GPU-facing.cuda-sliceand
python-wheel-gpushould be added — the latter already runs on pullrequests without blocking — along with
changelog-ownership.One subtlety worth recording:
python-wheel-gpureports "skipped" when theclassifier says no CUDA inputs changed, and GitHub counts a skip as a pass. That
makes
scripts/cuda_ci.pyload-bearing for a required check.cuda-slicehasno such dependency, by design.