Skip to content

story-017: Decide an implementer's test edits by reverting them - #16

Merged
jerodw merged 2 commits into
mainfrom
story/story-017
Aug 8, 2026
Merged

story-017: Decide an implementer's test edits by reverting them#16
jerodw merged 2 commits into
mainfrom
story/story-017

Conversation

@jerodw

@jerodw jerodw commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

Four story artifacts asserted that the implementer's changed-files record lists nothing under tests/. The harness enforced something narrower — may_not_create: ["tests/"], creation only — and never escalated on the difference. Every finding the prose rule produced was a deviation the verifier confirmed was forced, and each was adjudicated by hand: story-011's schema inventory, story-012's working-tree endpoints. story-013 removed one cause and its own validation tests promptly created another.

The causes are unenumerable. The rule was the constant.

This story stops adjudicating and starts deciding. An implementer's edit under a governed prefix is permitted iff reverting it makes the suite fail. A forced repair breaks the suite when reverted; new coverage does not — and that is the authorship the rule existed to prevent. No judgement, no prose, no human in the loop.

Changes

  • orchestration/story_coordinator.py — after a stage that declares both a changed_files record and a may_not_create list, the coordinator collects that stage's own modified and deleted entries under those prefixes (with the story's granted prefixes subtracted), reverts them from HEAD inside a clone, and runs the configured suite. Suite fails → forced repair → permitted. Suite passes → the edit was not load-bearing → escalate. created entries are not collected, because stage output ownership has already escalated on them.
  • workflows/story-workflow.json — the implementer declares revert_check: "revert-check-result.json". As with clean_clone, the key is what turns the check on: removing the declaration disables it with no orchestration change, and the artifact name never appears in code.
  • schemas/revert-check-result.schema.json (new) — records whether the check ran, exactly which paths were reverted, the command, the interpreter, the verdict and an output tail. Coordinator-written like clean-clone-result; nothing routes on it.
  • schemas/manifest.json — the new schema declared. Second use of story-013's mechanism: adding a schema touches schemas/ only.
  • prompts/planner.md — the planner is told to restate an injected restriction exactly as the workflow declares it, or not at all, because a tightened restatement "is not a stricter version of an enforced rule; it is an unenforced rule the harness cannot see broken, and one a legitimate change can make impossible to satisfy."

Testing

834 passed in the working tree, and 834 passed in a fresh clone with the story committed, on Python 3.10.20 (clean-clone-result.json, exit_code: 0). Verification passed first iteration, zero blocking issues.

The verifier drove the check against real git targets with real pytest suites rather than accepting it on description:

  • Forced repair permitted — a rename in src/app.py that the existing tests/test_app.py cannot survive.
  • Added coverage escalated — an appended test function, proved additive by a companion test showing it passes against the module both before and after the change.
  • Deletions decided both ways — deleting a governed path the change broke is permitted; deleting one that still passes is escalated.
  • No governed path costs nothing — a record naming none builds no clone and writes no artifact, asserted by checking that the only clone built during the run was the verifier's.

Notes for review

  • The granularity limit is in the schema description, not buried. The check reverts every governed path at once and decides on one suite run. So a set containing one forced repair is permitted in full, including added coverage sitting in other files of that set, and a single file mixing both is not caught at all. The paths field states exactly what was reverted so a reader can tell what the decision covered rather than assuming it discriminated per file. That was the known cost of the coarse form; per-file or per-hunk narrows it later if evidence justifies the noise.
  • This story could not decide its own test edit. revert-check-result.json is absent from its run directory — the coordinator loaded the workflow before revert_check existed in it. Same self-reference as story-014's clean-clone check and story-012's retry history. Its implementer did modify tests/test_story_007_validation.py, and the verifier examined that repair by hand, as every story before this one had to.
  • The verifier corrected the implementation summary's account of that repair. The summary claimed story-007's fixture passes whatever is reverted; reverting actually escalates, because the fixture's records name paths with no version at HEAD — a "could not run" outcome, not a passing one. The repair is right, the stated mechanism was wrong, and the verifier said so rather than accepting the narrative.
  • The planner guidance is the weak half, deliberately. Prompt guidance is the mechanism that failed five times over the HEAD-baseline rule, so it is not the enforcement here — the revert check is. Guidance reduces how often a planner writes the over-strict sentence; it does not stop it. The mechanical closure belongs to plan-time validation, which the book now also asks for, and is tracked separately.
  • One environment case the verifier flagged as unexercised: a target repository whose configured test command is not a Python interpreter was covered only through the constructed "cannot run" paths.

🤖 Generated with Claude Code

jerodw and others added 2 commits August 8, 2026 01:30
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Implemented by the l5 harness story workflow.
@jerodw
jerodw merged commit fe565a3 into main Aug 8, 2026
3 checks passed
@jerodw
jerodw deleted the story/story-017 branch August 8, 2026 15:54
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