Skip to content

fix(behaviors): break the identical-resubmit loop in planner_behavior_upsert#97

Merged
m62624 merged 6 commits into
mainfrom
fix/planner-behavior-upsert-guidance
Jul 8, 2026
Merged

fix(behaviors): break the identical-resubmit loop in planner_behavior_upsert#97
m62624 merged 6 commits into
mainfrom
fix/planner-behavior-upsert-guidance

Conversation

@m62624

@m62624 m62624 commented Jul 8, 2026

Copy link
Copy Markdown
Owner

No description provided.

m62624 and others added 2 commits July 8, 2026 14:17
…_upsert

A live run stalled: the model resubmitted a byte-identical behavior board 13
times because upsert MERGES (an omitted `requirement` keeps its old null) and
each write returned a bare "written" success. The model read success and looped,
never learning that setup-project owned REQ-1 with no behavior citing it — the
gap tdd_coverage was silently blocking on.

Surface both traps on the write itself (nudge, never a block — the board is
already saved): name an identical resubmit as a no-op, and name every in-scope
owned REQ no behavior cites, with the exact `"requirement": "REQ-n"` to set.
Logic extracted to computeBehaviorBoardNudges with unit coverage, including the
exact loop the session hit. Also clarify the `requirement` schema: a single
REQ-n string (never an array) whose omission the tdd_coverage gate blocks on.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pable prose

The previous "account for generated artifacts" paragraph was conditional prose
the model skipped entirely on a live run — no .gitignore task, no note. Rewrite
it as a default action (the plan carries a task that ignores the toolchain's
output) with one narrow escape (already ignored → say so in a line), and point
to it from the write_task_files step so it is not lost in the section body.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the fix label Jul 8, 2026
m62624 and others added 4 commits July 8, 2026 14:29
Groundwork for structural anti-orphan: a task can declare the taskIds it builds
on. The plan_coverage gate will justify a non-discharging setup task by having a
discharging task depend on it — not by borrowing a REQ it does not implement.
Optional, deduped, rendered into task.md, and defaulted to [] on read so legacy
task.json parses unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
planner_task_upsert now takes `dependsOn` (build-order taskIds) and its
`requirements` description no longer says "OR enables" — a task cites only the
REQ-n it actually discharges. A setup task that implements nothing leaves
requirements empty and earns its place via dependsOn. Existence of the cited
taskIds and cycle rejection are deferred to the plan_coverage gate (a forward
reference to a not-yet-created sibling task is legitimate at upsert time).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The plan_coverage gate had two conflicting demands: every task must cite a REQ
(else orphan), yet every owned REQ must be exercised by a behavior at
tdd_coverage. A cargo-init task satisfied the first by borrowing REQ-1, which
trapped it under the second. Break the double meaning of task.requirements.

In dependency mode (any task declares dependsOn) the compiler emits a
justification web: a task is not orphan if it discharges a REQ OR a discharging
task transitively depends on it (depends_on facts + CLOSE depends_on TRANSITIVE
+ two RULEs + a premise). CLOSE also rejects a dependency cycle — a DAG check
the old model lacked (found in TS for a clean gate message, not an engine
crash). Verified end-to-end through the real elenchus engine in the compiler
tests. Legacy plans (no dependsOn anywhere) keep the old TOTAL traces ON tasks,
grandfathered so resume never breaks.

The gate reports unknown dependsOn ids and cycles, maps the is_justified block
back to the orphan taskId, folds dependsOn into the staleness hash, and its
orphan guidance now points at dependsOn instead of a borrowed REQ.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…asks

Update planning.md and the vrf/storage AGENTS.md to the split model: a task's
`requirements` are only what it discharges, an infra task earns its place via
`dependsOn`, and the plan_coverage gate justifies a task if it discharges a REQ
or a discharging task (transitively) depends on it (dependsOn forms a DAG).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@m62624 m62624 merged commit 98a7097 into main Jul 8, 2026
5 checks passed
@m62624 m62624 deleted the fix/planner-behavior-upsert-guidance branch July 8, 2026 10:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant