test(_util): match error ANNOUNCEMENTS, not the word "error" (unblocks #70) - #74
Conversation
Manager verification — FIX, fail-before reproduced in both directionsHead Fail-before, this PR's tests against main's The failures split across both properties, which is what makes this a real fix rather than a loosening:
So the guard gets stronger, not weaker: the shipped Tiers: unit 813 passed · ledger 26 · ruff check + format clean (150 files) · That one cli failure is Does it actually unblock #70? The lane did the right experiment rather than a synthetic one — it ran
I am merging on that evidence and will re-run #70's CI next. Squash + |
`assert_no_silent_failure` used a bare `\berror\b`, which is a test for the word appearing rather than for an error being emitted. `doctor` prints every assumption's own DESCRIPTION on a healthy run, so in a catalogue whose subject is error handling one honest sentence turns a green run red -- `read.unavailable_not_absent`'s "... reports UNAVAILABLE (not ERROR) per project ..." matched at offset 125 and failed test_doctor_quick_succeeds_against_the_real_installed_bd on a completely healthy system, blocking PR #70. Replaced with five announcement shapes, each justified by output this project actually emits: `error:` (the shipped `reap` bug, adapter's `ERROR: <cause>` project status, gateway's `ERROR: tokens file...`, argparse's `prog: error: msg`), a JSON `"error": <non-empty>` field (supervisor writes one into printed payloads), `error running`, `unknown command`, and a Python `Traceback`. The last two are NEW coverage -- neither contains the word "error" at all. tests/unit/test_error_announcement_detection.py pins both directions in one file: the innocent case (PR #70's real description text) and the guilty one (`Error: unknown command "reclaim"` with exit 0 still raises).
… the lane artifact root
a963da6 to
2760376
Compare
|
Rebased onto |
Unblocks #70.
model_performance-wp6. Diff is two files, both undertests/.The defect
tests/_util.py'sassert_no_silent_failureusedre.compile(r"\berror\b", re.IGNORECASE). That is not a test for an error being emitted — it is a test for the word appearing, and a command is allowed to talk about errors while succeeding.doctorprints every assumption's own DESCRIPTION on a healthy run, so in a catalogue whose entire subject matter is error handling, one honest sentence turns a green run red. Reproduced locally against PR #70's own head (20557bc),doctor --quick, exit 0:\berror\bmatchesERRORat offset 302 of the combined output →assert_no_silent_failureraises →test_doctor_quick_succeeds_against_the_real_installed_bdFAILS on a completely healthy system.Rewording #70's description was explicitly not done: the trap is in the predicate, and the next assumption would hit it.
The fix
Five announcement shapes instead of one word. Every shape is justified by output this repo actually emits:
error-colon\berror\s*:Error: unknown command "reclaim"(the shippedreapbug);ERROR: <cause>(adapter.py's status for an unreadable project, asinstancesrenders it mid-column);ERROR: tokens file not found(gateway.py:141); argparse/cobra<prog>: error: <msg>. Not anchored to line start — a real announcement is routinely preceded by a program name or a column.json-error-field"error"\s*:\s*<non-empty>supervisor.py:177,189writes{"error": str(e)}into printed payloads.null/""is the no error reading and is deliberately not matched.error-running\berror\s+running\bunknown-command\bunknown command\bpython-traceback^Traceback \(most recent call last\):error_announcement()returns(shape_name, matched_text)and the assertion message carries both, so a CI reader can tell a real announcement from a false positive without re-deriving the regex.This is not purely a loosening: two of the five shapes are coverage the parent commit did not have.
The guarantee is NOT retired
tests/unit/test_error_announcement_detection.pypins both directions in one file (per the acceptance criteria — the failure mode being fenced is the two collapsing into each other). Ten parametrised guilty rows plus three assertion-level tests, includingError: unknown command "reclaim"+ exit 0 → must still raise.Eight of those ten pass on the parent commit AND on this branch. That is the proof the guard survived, rather than an assurance that it did.
Fail-before / fail-after
Full log:
docs/lanes/wp6-error-regex-scope/evidence/fail-before.txt.Parent
ea233a7(tests/_util.pyrestored to the bare\berror\b, this branch's test file in place):First seven = the defect (prose read as an emitted error, including #70's real sentence). Next two = new coverage. Last = the new shape-naming API. The 13 passing include eight of the ten real announcements.
Assertions are written against
looks_like_error_text/assert_no_silent_failure— the API that existed before this change — so the parent run reports the real diagnosis instead of anAttributeError.This branch:
23 passed in 0.22s.Would #70 now pass? Yes.
docs/lanes/wp6-error-regex-scope/evidence/pr70-would-now-pass.txt, from a real run, not a fixture:git worktreeoforigin/pr-70@20557bc, its own venv,doctor --quickagainst the real workspace root sosweeps.alivepasses (the healthy-CI condition) → exit 0,All 35 assumptions hold.\berror\bDoes not re-run #70's CI, and does not touch
jyg.Tiers run (all of them, by name)
make venvinstalls.[dev,web]andmodules/tool-work-tracker[dev], so tier 5 did not silently fail at collection. Raw logs underdocs/lanes/wp6-error-regex-scope/evidence/.make test-unitmake test-integrationmake test-climake test-ledgermake ledger-mutatemake test-modulemake checkThe one failure is
model_performance-jyg, not this change.test_doctor_quick_succeeds_against_the_real_installed_bddies at the earlierassert result.returncode == 0becausesweeps.aliveFAILs under the isolatedAMPLIFIER_WORK_TRACKER_ROOT(conftest.py:308). Proven pre-existing by re-running that single test with parent's_util.py:1 failed in 46.35s, identical signature (evidence/jyg-preexisting.txt).That is also why the regression test is tier 1: tier 3 structurally cannot reach
assert_no_silent_failurewhile jyg is present, which is exactly why this defect was invisible locally and only appeared in CI. I tried to bypass it by exporting the real root;run_cliusessetdefault, so the monkeypatched value wins — attempt recorded rather than dropped (evidence/jyg-cannot-be-bypassed-from-outside.txt).c0eand thetest_supervisor_web.pyport flake did not reproduce in these runs. Reported as observed, not claimed fixed.Why option (1) was NOT taken
Option (1) —
doctoremitting descriptions on a channel the check can exclude — is not in this PR.doctor's output contract; this diff is two files undertests/.Error:announcement arriving on stderr frombditself, under adoctorrun that healed the condition and exited 0. Filteringdoctor's own[PASS]rows would not exclude that. The two options are complements, not alternatives.I did not conclude option (1) is necessary, so there was nothing to stop for.
Discovered work, filed not absorbed
model_performance-kxk(discovered-fromwp6) — a HEALED dirty-schema migration still leaks bd's ownError:line to stderr whiledoctorexits 0. Observed once, not reproducible on the next run; a real intermittent flake source for anytests/clitest funnelling throughassert_no_silent_failure. Product-side output-contract question, not a test-regex one. Capture:evidence/pr70-doctor-quick.run1-transient.stderr.txt.Deviations, called out rather than slipped in
unknown command+Tracebackare new shapes — both named in the item/owner decision, both strengthen the guard, neither can produce the fix: pin the dolt scan directory; stop reporting infrastructure failure as "item not found" #70 false positive."error": <non-empty>shape was not named in the item. It preserves coverage the parent had via\berror\bforsupervisor.py's printed payloads, which a colon-only rule would have dropped.Spend: $0.00 of a $0.00 authority. No API, no DTU, no infrastructure created.
Full note:
docs/lanes/wp6-error-regex-scope/DONE-NOTE.md.