Skip to content

fix(prose-tests): command output was never actually recorded#560

Open
leeovery wants to merge 1 commit into
fix/prose-tests-record-the-modelfrom
fix/prose-tests-record-command-output
Open

fix(prose-tests): command output was never actually recorded#560
leeovery wants to merge 1 commit into
fix/prose-tests-record-the-modelfrom
fix/prose-tests-record-command-output

Conversation

@leeovery

@leeovery leeovery commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • The recorder read the wrong field. It took tool_output off a post-tool payload; the field is tool_response, and for a shell it's an object of stdout/stderr, not a string. Every successful call therefore recorded its status and nothing else — rows read → ok with an empty output column.
  • That silence undercut the record's whole purpose. The asserter is told that a claim about what a command produced — a gate rendering empty, a menu having no entries — is settled by the record, not the walker's account. It couldn't be. Claims about output had only the narrative to rest on, which is the exact evidence the record was introduced to replace.
  • A command now gets far more room than a file read (2000 vs 400 chars). A claim turns on a rendered section surviving whole; none turns on the bytes a walker read back.
  • Drops the tool_output_is_error check — it never fired and never could. A failing call doesn't reach PostToolUse; it raises PostToolUseFailure, which was already recording correctly. Reaching the success branch is itself the signal.

Test plan

  • node --test tests/scripts/test-prose-record-action.cjs — 17/17, with five new cases: stdout capture, stderr merging, the command-vs-read budget split, a non-shell response shape, and the failure path
  • Prose gate green: 38/38 across recorder, corpus and snapshot suites
  • Verified against a live walk — the gateway's DATA, DISPLAY and MENU sections now all appear in the record, menu entries included. Before this change the same walk recorded → ok and nothing more.

Why it matters beyond the bug

Steps about display and menus could previously only be evidenced from the walker's narrative. In a Sonnet-walker trial, one case passed cleanly and another failed purely because its narrative was thin — the recorded actions proved the work was done. With output in the record, that evidence moves off the narrative, which is the precondition for revisiting the walker model.

🤖 Generated with Claude Code

Stack

  1. docs(design): prose-tests programme design log #544
  2. feat(prose-tests): the framework — cases, worlds, runner, skill #545
  3. test(prose): feature happy-path corpus — five worlds, seven cases #546
  4. test(prose): bugfix corpus — the investigation-centric surfaces #548
  5. test: retry recursive teardown removals — kill a class of phantom failures #549
  6. fix(entry-skills): close the handoff fences — six files render their arms wrong #550
  7. docs: a contributing page for working on the system #551
  8. fix(entry-skills): every handoff arm says to invoke the skill #552
  9. fix(implementation): environment setup belongs to the setup reference alone #553
  10. fix(prose-tests): the asserter is told which substitutions were armed #554
  11. feat(prose-tests): the mid-flow substitution, and a world only prose can describe #555
  12. test(prose): claims assert consequences, not what was displayed #556
  13. feat(prose-tests): record everything the agents do, results included #557
  14. fix(discussion-entry): the handoff reports the source it actually had #558
  15. fix(prose-tests): the stop hook records, and names the model that walked #559
  16. fix(prose-tests): command output was never actually recorded #560 👈 current
  17. feat(prose-tests): judge the walk as told, not the summary returned #561
  18. feat(prose-tests): decide in code what an agent should not be deciding #562
  19. test(prose): a case starts where a session starts #563
  20. feat(prose-tests): walk on Sonnet, judge on Opus, escalate a failure #564
  21. test(prose): give the eight read-only cases something that can fail #565
  22. test(prose): only walks that can be observed, and checks that survive the trip #566
  23. fix(prose-tests): the verdict names only the model the record names #567
  24. test(prose): discovery, walked to the point where work first exists #568
  25. fix(prose-tests): the asserter judges which of prose or walker was at fault #569
  26. docs(conventions): a step whose reference routes every exit still signposts #570
  27. test(prose): discovery's epic arm, to the same durability boundary #571

The recorder has been reading `tool_output` off a post-tool payload. The
field is `tool_response`, and for a shell it is an object of `stdout` and
`stderr` rather than a string — so every successful call recorded its
status and nothing else. Rows read `→ ok` with an empty output column.

That silence undercut the one thing the record exists for. The asserter
is told a claim about what a command produced — that a gate rendered
empty, that a menu had no entries — is settled by the record rather than
by the walker's account of it. It could not be. With no output there, a
claim about output had only the narrative to rest on, which is precisely
the evidence the record was introduced to replace.

Output now comes from `tool_response`, reading a shell's streams directly
so a command's output stays legible as output instead of a JSON envelope
around it, and a command gets far more room than a file read: a claim
turns on a rendered section surviving whole, never on the bytes a walker
read back.

Also drops the `tool_output_is_error` check, which never fired and never
could. A failing call does not reach PostToolUse at all — it raises
PostToolUseFailure, which was already recording correctly — so arriving
here is itself the success signal.

Verified against a live walk: the gateway's DATA, DISPLAY and MENU
sections now all appear in the record, menu entries included.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Jul 26, 2026
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