harness scratch: name the population, and refuse a verdict over zero files - #3060
Merged
Conversation
…files Closes #3059 On a tree holding only .trinity/ -- no bootstrap/tests, no cli/tri/tests -- `tri harness scratch --gate` printed `none` and exited 0. It read nothing. `scan()` builds two directory paths, drops the ones that are not directories, and an empty list produces an empty result, which prints identically to a clean 85-file scan. harness-scratch.yml runs that gate, so its pass survived its subject going missing. It now prints what it read, names every declared directory that is not there, and refuses an empty population with exit 2: nothing failed, the check could not run. Same code scripts/tri uses for an unbuilt compiler (#3045) and t27c corpus for a spec tree with nothing in it (#3025). No behaviour change in CI: bootstrap/tests exists there, the population is 85, the gate stays green. The refusal is reachable only on a tree where the gate could not have meant anything. The same column surfaced a second thing: cli/tri/tests has NEVER existed -- `git log --all -- cli/tri/tests` is empty. Half the declared population has always been absent and nothing said so. `refuses()` is a named function with its own test rather than a line inside `run`, because an untested branch in an integration path is exactly where a mutation of this shape survives -- one did in `tri skill renumber`, hours before this. Three mutants, three kills, each with passed+failed asserted against the expected 3.
Contributor
gHashTag
enabled auto-merge (squash)
September 3, 2026 20:44
Refs #3059 #3050 landed `advice_tests` at the tail of this file while this branch was appending `population_tests` there. Both kept. The first resolution dropped the closing brace of the incoming module -- the compiler said so immediately ('unclosed delimiter', naming line 332), which is the cheapest reader there is for this kind of merge. And a stale reading in the same minute: `tri harness scratch --gate` reported rc=0 while the build was failing, because the binary on disk was the previous one. An exit code from a tool that did not just build is not a reading of the code you are holding.
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
PR DashboardGenerated at: 2026-09-03 20:51:56 UTC
Summary
Seal Status
|
This was referenced Sep 3, 2026
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.
Closes #3059
Measured
A tree holding only
.trinity/:Green, and it read nothing.
scan()builds the two directory paths, callsdirs.retain(|d| d.is_dir()), and an empty list produces an empty result — which prints identically to a clean 85-file scan..github/workflows/harness-scratch.yml:79runs this as--gate, so its pass survived its subject going missing: the class #3025 named, one layer up in Rust rather than in a workflow step.After
test files read 85,directory NOT THERE cli/tri/tests,none, exit 0test files read 0, both directories named,REFUSED … Exit code 2--self-checkExit 2, not 1: nothing failed, the check could not run. Same code
scripts/triuses for an unbuilt compiler (#3045, merged) andt27c corpusfor a spec tree with nothing in it (#3025, in #3040).No behaviour change in CI.
bootstrap/testsexists there, so the population is 85 and the gate stays green. The refusal is reachable only on a tree where the gate could not have meant anything.What the column surfaced on its first run
cli/tri/testshas never existed —git log --oneline --all -1 -- cli/tri/testsprints nothing, andls cli/tri/isCargo.toml skip-baseline.txt skipwatch.py src. Half the declared population has always been absent, and until this column nothing said so. That is not a defect by itself; a scan that names two directories and silently reads one is a scan whose population is smaller than its code claims.Evidence
refuses()always false.rscargo test -p tri --bins→ 545 passed, 0 failed, 0 filtered. Each mutant row assertspassed + failed == 3, because acargo testfilter is a substring and a run that matched nothing reads as a survival.refuses()is a named function with its own test rather than a line insiderun. An untested branch in an integration path is exactly where a mutation of this shape survives — one did intri skill renumber(#3052) hours earlier, and that is the reason for the shape here.Also checked, not fixed
tri mods orphan --gateon the same hollow tree exits 1 withError: No such file or directory (os error 2). It refuses rather than passing, which is the right direction, but the message names no path.