Skip to content

story-042: A plan may assign an existing file to the implementer - #39

Merged
jerodw merged 1 commit into
mainfrom
story/story-042
Aug 15, 2026
Merged

story-042: A plan may assign an existing file to the implementer#39
jerodw merged 1 commit into
mainfrom
story/story-042

Conversation

@jerodw

@jerodw jerodw commented Aug 15, 2026

Copy link
Copy Markdown
Owner

plan_validation.assignment_problems refused a plan that assigned a tests/ path to the implementer, because the workflow says the implementer may not create files there. But likely_file_changes does not record whether a file will be created or modified, so the check guessed creation and refused both.

The two rules it conflated

  • Creating is banned. may_not_create: ["tests/"], enforced after the stage runs against changed-files.json's created list.
  • Modifying is conditional. The revert check restores the implementer's edits under governed prefixes and re-runs the suite: still passing means they were not forced and the run escalates; failing means they were, and the run records implementer edits under tests/ permitted.

The plan-time check was applying the first rule to a case the second one owns.

It only bit an honest plan

story-041's planning session was refused for four files — test_clean_clone_check.py, test_revert_check.py, test_self_routing_retry.py, test_no_target_stack_in_harness_source.py — all of which already exist. The implementer cannot create them; it can only edit them, which that story requires because they assert on the fields and config key it renames.

Meanwhile the three stories before it each had their implementer edit files under tests/, each was permitted by the revert check, and none of their plans listed a tests/ file at all:

story-035   tests/test_harness_layer_extraction.py
story-037   tests/test_story_017_validation.py + two more
story-040   tests/test_clean_clone_check.py, tests/test_stage_output_ownership.py

So the check refused a plan that forecast its forced edits and missed the ones that stayed quiet. It rewarded vagueness.

What changed

assignment_problems(story, stages, root) now refuses only when the assigned path does not exist:

and not (Path(root) / path).exists()

scripts/l5-plan threads the target root through artifact_problems. The fact is derived from the repository rather than declared: an action: create | modify field was considered and rejected, because it would be the planner's claim, the check would still have to verify it, and roughly forty committed artifacts do not carry it.

The create-half is untouched — a plan naming a new tests/ file for the implementer is still refused, still names both resolutions, and test_the_conflict_story_031_carried_is_reported holds that against a real historical instance.

Verification

  • 2271 passed, 23 written; verification passed on the first iteration, no retries; clean-clone green with the story committed
  • test_pre_flight_does_not_start_refusing_the_assignment_classrun_story never called this check and must not begin to, so no run behaviour changes
  • test_no_committed_artifact_becomes_unrunnable — every committed artifact still validates
  • Checked directly against the observed case: story-041's committed artifact now reports clean

🤖 Generated with Claude Code

Implemented by the l5 harness story workflow.
@jerodw
jerodw merged commit bd41096 into main Aug 15, 2026
3 checks passed
@jerodw
jerodw deleted the story/story-042 branch August 15, 2026 20:50
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