A failing test suite passes agent.test.unit: its completion only checks that the report exists #137
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
agent.test.unitcompletes onpaths-exist:.osf/test/unit.json(src/osf/pipeline/nodes.py). After the agent's turn, Braid runs the suite itself (run_declared_lane). It writes a correct verdict tounit.json, withexit_code,greenandreasons, but nothing reads that verdict afterwards: the step logs "lane red" and succeeds.osf.pipeline.applysays this step's completion issuites-green:unit("exit 0, a clean ban lint, and the mutation gate on the diff"). That predicate exists, andscript.test.unituses it. The agent step has been onpaths-existsince the first 22-node pipeline (23349d1).The session working on #125 found this in run 41's report:
exit_code: 0,green: false, 20 ban violations. Every production run that reached the step passed it:Three runs merged with a red suite. The only green report (run 33) is from a quick fix whose agent unit step was skipped. Runs 39 and 41 have no untested scenarios because #121 added the spec tags.
The ban lint is not ready to block
In run 41, all 20 findings are on good tests:
expect(screen.queryByRole("button", { name: "Start the next hand" })).toBeNull(). They fail if the control appears.expect(parseState(without)).toBeNull()in "rejects a payload missing the hand_result field".getByRole(...)throws when the button is missing,fireEvent.clickpresses it, thenexpect(onStartNextHand).toHaveBeenCalledTimes(1). It does not pass with the module deleted.describe("parseState", ...). The tests inside are tagged, and coverage is 31 of 31 scenarios.Blocking on the lint as it is would stop runs over good tests, and push agents to make them worse to get past it.
Proposal
Block on the suite now.
agent.test.unitholds only when the report's exit code is 0 and the report is fresh (its tree is the worktree's). This could be an argument tosuites-greenthat leaves the lint and coverage advisory.predicate_failedis already mediated, so a red suite gets two more attempts briefed with the failing output, then goes to a person instead of merging.Fix the lint's precision.
toBeNull()ornot.toBeInTheDocument()on a query) and a function's return value as behaviour.getBy*andfindBy*queries as assertions.describewhose tests are tagged.Measure the result against the tests of runs 22 to 41.
Then make the lint and scenario coverage block too (
suites-green:unitin full). State the rules in the apply brief as well: most tests are written during apply, and today the rules are only in the test step's brief.Related: #125 (the verification steps redo each other's work).
Also in scope (folded in at the user's word): the error after a second cut-off still says the model was cut off "the second time after being asked to answer without thinking" (
_cut_offinsrc/osf/engine/executors.py). Since #136, the re-prompt after a cut-off thinks briefly (thebriefvariant), so the text should say that.Work starts after the session implementing #125, #126, #127, #114, #113 and #73 has pushed. It also edits
nodes.pyandprompts.py.Corrections after checking this against the code. They are recorded in the proposal,
test-lanes-hold-on-the-verdict, which is waiting for review before any code changes.expect(parseState(…)).not.toBeNull().agent.test.e2ehas the same hole. It also completes onpaths-exist, so it is included.Correction to my previous comment: 17 of run 41's 20 findings were on tests written before the run, and 3 on run 41's own tests, all three sound. I wrote 15 and 5. The measurement recorded in the change's design confirms 17 and 3.
Shipped in
62ce2e3,f81f567,5277bf2,b15aae3,78129f2and05d82dd. Deployed in deploy 99 (81ca5f5, 11:38 on 2026-10-03). Archived inea993c4astest-lanes-hold-on-the-verdict.The test steps hold on the suite's verdict.
agent.test.unitandagent.test.e2enow complete on a new check,lane-passed. The lane report Braid writes must record exit 0 for the code as it is now, and an e2e lane must leave Playwright's artifacts on disk. A red or stale lane is tried again, twice as before, then goes to a person. It can no longer merge. Runs already in flight keep the pipeline they started with.A retry is told everything. The briefing lists every reason the lane check gave, and says that the suite's output is in the report's
stdout_tail.The lint judges the run's own tests, by what they assert. It reads only the blocks the run's diff touches, and asks about imports only for files the run added.
getBy…orfindBy…query as an assertion.toBeNull(),toBeUndefined()or an assertion about a query existence-only.describe's.The lint, scenario coverage and mutation are recorded in the report and shown in the step's summary, but they do not decide yet.
The briefs for apply, unit tests and quick fixes list the lint's own rules from one table, say it flags rather than rejects, and carry the new tagging guidance.
The message after a second cut-off now says the re-prompt asked for brief reasoning.
Measured over runs 22 to 41 on production; the figures are in the design.
Checked on production:
lane-passed;Left for a follow-up: making the lint and scenario coverage decide. Before that, settle whether a test a run only adapted should owe a tag.