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.
|
"ready_for_verification"}`. It is the whole lever for this rung.
|
||||||
- Ingest turns every issue label into a required capability, so a rig issue
|
- Ingest turns every issue label into a required capability, so a rig issue
|
||||||
must carry no labels or it will not schedule.
|
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