Skip to content

Remove the debt artifacts and put the Rust suite under an automatic gate - #284

Merged
niveousdragon merged 5 commits into
mainfrom
fix/remove-debt-artifacts
Aug 31, 2026
Merged

Remove the debt artifacts and put the Rust suite under an automatic gate#284
niveousdragon merged 5 commits into
mainfrom
fix/remove-debt-artifacts

Conversation

@niveousdragon

Copy link
Copy Markdown
Contributor

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:

  • four audit ledgers and a remediation plan in docs/;
  • python/tests/test_structural_debt_ceilings.py, whose ceilings of 105
    unreferenced public functions, 185 silent WCOJ declines and 107 environment
    names assert that this much debt is an acceptable release state;
  • a paragraph in ENGINEERING.md saying 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.toml from the same pull request is kept: it repairs a real
defect — cargo unusable outside Linux — rather than recording one.

Putting the Rust suite under a gate

cargo test --workspace --all-targets --release ran under workflow_dispatch
alone, so it ran when somebody remembered to press the button. That is the
mechanism by which a broken test once sat on main until an outside run
happened to find it.

  • Nightly. rust-tests now runs on a schedule (0 2 * * *) against main,
    in addition to workflow_dispatch.
  • Every pull request. A new cuda-slice job runs
    cargo test --all-targets --release -p xlog-cuda -p xlog-gpu on the CUDA
    runner — the two crates whose entire purpose is the device, including the
    certification suite in xlog-gpu/tests. The whole workspace is too long for a
    pull request; this part is not.
  • No path filter on cuda-slice, deliberately. A filter deciding which pull
    requests get GPU coverage leaves whatever it misses unchecked, which is the
    same class of mechanism as the button above.
  • Failures reach a person. report-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 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 concurrency
key grouped by ref alone, so a push to main would have cancelled a nightly run
already an hour in.

Verification

  • python/tests/test_ci_workflow_contract.py gains a test asserting the whole
    shape: the cron entry, schedule in the rust-tests condition, cuda-slice
    on the CUDA runner for same-repository pull requests, the absence of a
    path filter on it, the issue-reporting job's issues: write permission, and
    the event name in the concurrency group.
  • Both negative checks pass: removing schedule from the rust-tests
    condition fails the test, and adding needs: cuda-changes to cuda-slice
    fails it. Tree restored after each.
  • evaluate_python_wheel_gate simulated for schedule: passes on GPU success,
    fails on GPU failure.
  • Contract suite: 16 passed, 1 failed. The failure is
    test_cuda_change_classifier_cli_consumes_null_delimited_git_paths, which
    fails on main too and only off Linux (CRLF from print()); it is a separate
    finding with its own fix, not introduced here.
  • Against the tree as it stood before Publish the debt ledgers, cap three debt classes, and unbreak cargo off Linux #283, exactly one file differs:
    .cargo/config.toml. No dangling references to the deleted files remain.

Not measured: how long cuda-slice takes. No GPU on the machine this was
written 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-main requires nine checks and none of them is GPU-facing. cuda-slice
and python-wheel-gpu should be added — the latter already runs on pull
requests without blocking — along with changelog-ownership.

One subtlety worth recording: python-wheel-gpu reports "skipped" when the
classifier says no CUDA inputs changed, and GitHub counts a skip as a pass. That
makes scripts/cuda_ci.py load-bearing for a required check. cuda-slice has
no such dependency, by design.

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.
@niveousdragon
niveousdragon requested a review from levi770 as a code owner August 30, 2026 18:40
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.
@niveousdragon
niveousdragon merged commit 177f280 into main Aug 31, 2026
13 of 15 checks passed
@niveousdragon
niveousdragon deleted the fix/remove-debt-artifacts branch August 31, 2026 08:46
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