Let the claude harness reach the turn boundary at all

F25. rotationTick returned early for claude before reaching federatedTurn,
which has one call site below that return. On the harness both burn-in runs
used, no phase request could ever be read and every human decision recorded
against a live session went undelivered. Claude still skips the occupancy
state machine below, because it owns its context rollover through the
installed hook. A turn boundary is not a rotation.

F26. The phase brief listed every domain-legal target, so run 4's frame
session read "research, implement" and asked for implement, which the
project's path refuses. The path is Orchestra's to know: the brief now names
one step and says a wrong target comes back with the right one.

F27. A refused request only reached recordError, leaving the agent to rewrite
the same rejected file forever with nothing telling it why. federation.
StatusError makes a 409 classifiable, and the refusal is delivered through
sendPrompt under the F20 guarantee. A transport failure is not an answer: the
request survives and the agent is told nothing.

The F25 regression test fails against the unfixed rotationTick.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011xsXyr5J1RACo71YeKG3Pu
This commit is contained in:
2026-08-27 17:29:43 +04:00
parent f27cc4879f
commit fbaaf79bb1
5 changed files with 252 additions and 21 deletions
+108
View File
@@ -985,3 +985,111 @@ they are deliberately outside F20 and stay that way.
Left running and untouched. Whatever it does from here is additional diagnostic
evidence. Run 4 does not wait on it.
## Run 4: failed conformance, 2026-08-27
Task `06G46P6KE25Y04VVF7VRZMHZ78`, issue `kami/test-e2e#4`, revision `1f5bf7e`.
```text
run 4: failed conformance
cause:
f25, claude rotationTick bypassed federatedTurn
evidence:
phase-request.json existed
no WorkPhaseChanged followed
no boundary error was emitted
additional defects:
f26 phase brief advertised invalid shortcut
f27 phase refusal was not delivered to agent
```
### What run 4 did prove
The front half of the chain is clean, with no operator lifecycle intervention.
| seq | at (UTC) | event |
|---|---|---|
| 370 | 13:11:29 | `TaskCreated` v1, 7 acceptance criteria |
| 371 | 13:11:30 | `TaskLeased` v2, epoch `06G46P6Q4EAPF7DFDBFBTA9RJC` |
| 372 | 13:11:33 | `TaskLaunchAcknowledged` v3 |
Issue to confirmed launch: 4 seconds. F14 passes, against run 1 where ingest
set no acceptance at all. F15 and F17 pass again with
`confirmation=editor_cleared submit_attempts=1`.
The agent wrote its request 25 seconds after launch:
```
/tmp/test-e2e-worktrees/06G46P6KE25Y04VVF7VRZMHZ78/.orchestra/phase-request.json
{"from": "frame", "to": "implement"}
```
The artifact half of F21 works. The reading half never ran.
### F25, lifecycle: the turn boundary was unreachable on claude
`rotationTick` returned early for this harness before reaching the boundary,
and `federatedTurn` has exactly one call site, below that return.
```go
if w.harness == "claude" {
if err := w.advanceClaudeContextReset(ctx, id, s); err != nil { ... }
return
}
```
Introduced in `7f12c7f`. Consequences on the harness both burn-in runs used:
no phase request could ever be read, and **every human decision recorded
against a live claude session went undelivered**.
This retracts an earlier claim in this ledger. F23's decisions do reach
`RemoteTurn`, but on claude the worker never asked, so run 3 had no
post-launch send path either. The statement that a comment on `#3` would have
produced a receipt was wrong.
Fixed: claude runs the common boundary after its context reset. It still skips
the occupancy state machine, because it owns its own rollover. A turn boundary
is not a rotation.
### F26, authority: the brief advertised an invalid shortcut
The deployed brief rendered `Legal values for "to" from here: research,
implement`, listing every domain-legal move. The project's path allows only
`research`. The agent took the shortcut, reasonably.
Fixed: the brief names one target and states that a wrong one comes back with
the right one. The project's path is Orchestra's to know.
### F27, lifecycle: a refusal never reached the agent
A refused request only reached `w.recordError`. The agent would rewrite the
same rejected file at every boundary with nothing telling it why, which is the
silent-loop shape this codebase keeps producing.
Fixed: `federation.StatusError` makes a 409 classifiable. A refusal is
delivered through `sendPrompt`, so it travels under the F20 guarantee, and the
request file is cleared. A transport failure keeps the file and tells the agent
nothing, because it is not an answer.
### Ledger
```
F6 closed
F14 closed
F15 closed by detection, transport fix pending live proof
F16 closed, both branches live-proven
F17 fixed, isolated live proof
F18 open observability, non-blocking
F19 fixed
F20 fixed, live proof still pending
F21 artifact half live-proven, reading half pending
F22 fixed, live proof pending
F23 closed as already implemented, undeliverable on claude until F25
F24 open correctness, dormant on current topology
F25 fixed, tests only
F26 fixed, tests only
F27 fixed, tests only
```