Record run 20: the mismatch and replan ladder holds, and F66
Both halves proven live. A human_decision mismatch stops the task, the blocker packet states the contradiction, and a Gitea reply resumes the same plan in 55 seconds with no reseal. A replan reopens into plan while the old plan stays accepted with its progress, and sealing the replacement moves plan_ref, retains the old one in history, stops the old progress counting, and hands the successor the replacement whole. F66 recorded: the planning session a replan convenes is told nothing about the contradiction it exists to fix, though all of it is durable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVbaKucEYBjMqVeUgJUsc1
This commit is contained in:
@@ -2848,3 +2848,102 @@ unchanged.
|
||||
"ready_for_verification"}`. It is the whole lever for this rung.
|
||||
- Ingest turns every issue label into a required capability, so a rig issue
|
||||
must carry no labels or it will not schedule.
|
||||
|
||||
## Run 20, 2026-08-29: the mismatch and replan ladder, and three defects
|
||||
|
||||
Task `06G4WJ9T4F35NZC4Z8QQXM9Z6G` (issue 29) on `de18f37`, plus a first attempt
|
||||
on `06G4WDJ06G7FK00QF73Z9DDBT4` (issue 27) on `c587f2c` that found F65.
|
||||
|
||||
The lever throughout is the agent's own file, written by the operator with the
|
||||
worker stopped: `.orchestra/plan-mismatch.json`, carrying `phase_id`,
|
||||
`observed`, `contradicts`, `evidence` and `requested_action`. The worker fills
|
||||
`plan_ref` and `at_sha` from what it can verify, never from the file.
|
||||
|
||||
### F65: a task that stops for a human never stopped
|
||||
|
||||
Found on the first attempt, live:
|
||||
|
||||
```text
|
||||
16:04:25 PlanMismatchRecorded phase-2 human_decision
|
||||
16:04:25 worker: plan mismatch refused: task version conflict
|
||||
16:04:48 PlanPhaseVerified phase-1 work continues as if nothing happened
|
||||
```
|
||||
|
||||
`Store.Append` fences every lifecycle event on a leased task against the
|
||||
current owner and epoch. `blockForPlanMismatch` carried neither `harness_id`
|
||||
nor `lease_epoch`, so the block was refused on every task that was actually
|
||||
running, which is every task that can produce a mismatch. The observation was
|
||||
durable and the transition silently did not happen: the repo's own documented
|
||||
failure shape. `raiseTrajectoryGate` had the identical omission, so the
|
||||
trajectory gate could never have stopped a live task either.
|
||||
|
||||
`RecordPlanMismatch` also returns that error after the record is already
|
||||
appended, so the worker told the agent its report was refused for a report
|
||||
Orchestra had accepted.
|
||||
|
||||
Fixed in `de18f37` with one `fenceToLease` helper, called by all three stops.
|
||||
The human-decision path already did it correctly and explained why in a
|
||||
comment; that comment is now the helper.
|
||||
|
||||
**Why no test caught it.** `planWith` never leased its task, so every
|
||||
plan-progress and plan-mismatch test ran in a state no agent can be in. The
|
||||
`lease` helper in the same package carries a comment warning about exactly
|
||||
that. It leases now, and the mismatch block test fails without the fence with
|
||||
the same `task version conflict`.
|
||||
|
||||
### Proven: human_decision stops, and the reply resumes the same plan
|
||||
|
||||
```text
|
||||
16:24:21 PlanMismatchRecorded phase-2 human_decision
|
||||
16:24:21 TaskBlocked plan_mismatch, lifecycle awaiting_human
|
||||
18:24:46 HumanDecisionRecorded operator_instruction (Gitea's timestamp)
|
||||
16:25:16 TaskCorrected resumed
|
||||
16:25:16 TaskLeased plan_ref unchanged at 0bc8ef84
|
||||
16:25:21 TaskPickupValidated
|
||||
```
|
||||
|
||||
55 seconds from block to resumed, on the same plan, with no reseal. The
|
||||
blocker packet states the observation, the plan's claim and the evidence.
|
||||
|
||||
This is also the live proof of F64: before `6cb2f93` nothing read a blocked
|
||||
task's comments, because the reconciler ran only before a lease and at a turn
|
||||
boundary, and a blocked task is never leased.
|
||||
|
||||
### Proven: replan keeps the old plan until a replacement seals
|
||||
|
||||
```text
|
||||
16:26:07 PlanMismatchRecorded phase-3 replan
|
||||
16:26:07 WorkPhaseChanged plan reopen=PlanMismatchRecorded
|
||||
during planning: plan_ref 0bc8ef84 accepted, phase-1 and phase-2 counted
|
||||
after the seal:
|
||||
plan_ref 922f293b
|
||||
plan_history [0bc8ef84]
|
||||
progress empty
|
||||
successor in implement: four phases, all "not started"
|
||||
```
|
||||
|
||||
The successor's launch context carries the replacement whole, with files,
|
||||
changes and verification per phase. The old progress stops counting because
|
||||
`PlanPhases()` drops records whose plan ref is not the accepted one. An
|
||||
abandoned replan would have cost nothing.
|
||||
|
||||
### F66: the planner replans blind
|
||||
|
||||
The planning session convened by a replan is given the ordinary plan brief and
|
||||
an empty template. Its launch context says nothing about the plan that already
|
||||
exists, the contradiction that reopened the phase, the phase id, the evidence,
|
||||
or the fact that its output supersedes an accepted plan. The only human input
|
||||
it carried was an unrelated earlier correction.
|
||||
|
||||
Everything it needs is already durable. `PlanMismatchRecorded` holds the phase,
|
||||
the observation, the contradiction and the evidence, and `reopenPhase` writes
|
||||
`reopen_phase_id` onto the `WorkPhaseChanged` payload. None of it reaches the
|
||||
agent, so nothing stops the replacement from sealing with the same
|
||||
contradiction in it.
|
||||
|
||||
### Smaller observation
|
||||
|
||||
The implement session kept working after the reopen. It verified phase-2
|
||||
against the old plan 40 seconds after the task had moved to `plan`. Harmless,
|
||||
because supersession discards it, but the reopen does not end the session that
|
||||
reported the contradiction. That session rotates at its own next boundary.
|
||||
|
||||
Reference in New Issue
Block a user