Skip to content

story-034: The resume guard can refuse when the harness is its own target - #32

Merged
jerodw merged 1 commit into
mainfrom
story/story-034
Aug 13, 2026
Merged

story-034: The resume guard can refuse when the harness is its own target#32
jerodw merged 1 commit into
mainfrom
story/story-034

Conversation

@jerodw

@jerodw jerodw commented Aug 13, 2026

Copy link
Copy Markdown
Owner

unchanged_since_escalation refuses a resume that would provably repeat itself: the story, the branch and the harness all unchanged since the escalation. In this repository — where the harness is the target — it could never refuse.

Why it could never fire

harness_revision is recorded on the first line of _escalate, before the escalation makes its two commits. When harness_root == target_root, those commits move HEAD, so the third leg compares a pre-escalation revision against a post-escalation one and always differs. And when the tree was clean enough that no commits were made, escalation_commit is empty and the second leg returns early instead.

There was no path on which the guard refused. story-028 resumed on 2026-08-12 for that reason and not because anything about it had changed.

What changed

same_repository(target_root, harness_root) decides the case from git rev-parse --show-toplevel in each root, shared only when both succeed and report the same path. Under a shared root the harness leg is skipped and the branch comparison stands alone — which is sound rather than convenient: if the two roots are one tree, the branch leg already establishes that it is exactly the escalation commit with nothing uncommitted, and that covers every change to the harness source too.

The tree-hash alternative — hashing the harness's own source directories rather than comparing HEAD — was considered and rejected, and ARCHITECTURE.md records why rather than leaving the next reader to think of it and wonder.

The bias is preserved

A failing rev-parse on either side reports not shared, matching the one-directional bias _revision, dirty_paths, completion_commits and base_problems already take. This story makes a refusal possible where none was; it must not make a false one possible, and a developer who did change something being told they did not is worse off than one who wastes a run.

Consequence worth knowing

Escalations of story-028's shape now stop resuming without an argument. --stage is the intended override and the refusal message names it, so the escape hatch is in place — but the working habit changes, and the escalation summary's promise that a resume is refused while the story, branch and harness are unchanged becomes true for the first time.

Verification

  • 1681 passed, 18 written; verification passed first iteration, no retries; clean-clone green with the story committed
  • Shared-root behaviour is exercised through fixtures where one checkout serves as both roots; a real l5-run against this repository's own checkout was deliberately not run, since that would move this run's own state

🤖 Generated with Claude Code

…rget

Implemented by the l5 harness story workflow.
@jerodw
jerodw merged commit 4e3ca48 into main Aug 13, 2026
3 checks passed
@jerodw
jerodw deleted the story/story-034 branch August 13, 2026 20:10
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