feat(orchestrator): soft occupancy threshold requests handoff early (S11 partial)
Coordinator.Soft (default 0.55, ORCHESTRA_OCCUPANCY_SOFT) makes rotate() and TurnDecision request a handoff advisory-only once occupancy crosses the soft threshold, well before Hard forces a release/rotation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
This commit is contained in:
@@ -882,6 +882,34 @@ and `TaskAmended` in `store.apply` now populate/update all four fields
|
||||
as amendable. Covered by `TestTaskAmendedAppliesAllFields`
|
||||
(`internal/store/store_test.go`).
|
||||
|
||||
## S11 — partial fix, 2026-07-27 (soft threshold)
|
||||
|
||||
Of S11's four missing pieces (soft ~55% threshold, milestone rotation, thrash
|
||||
detection, agent-initiated `ROTATE`), only the first is landed here.
|
||||
|
||||
`Coordinator` gained a `Soft float64` field (default 0.55 via `soft()` when
|
||||
unset, configurable through `ORCHESTRA_OCCUPANCY_SOFT`). Both `rotate()` (the
|
||||
periodic ticker) and `TurnDecision` (the synchronous per-turn path) now check
|
||||
occupancy against `Soft` before `Hard`: at or above soft but below hard, they
|
||||
call the adapter's `HandoffRequester.RequestHandoff` once (same
|
||||
"ask, don't invent" convention as the hard-threshold path,
|
||||
`Session.HandoffRequested` guarding re-prompts) and — for `TurnDecision` —
|
||||
return `prepare_handoff` without requiring a turn boundary, since this is
|
||||
advisory: the agent keeps working, the task stays leased. Only once occupancy
|
||||
clears `Hard` does the existing boundary-check/release path run. Covered by
|
||||
`TestTurnDecision/"prepare_handoff at soft threshold, below hard, without a
|
||||
turn boundary"` (internal/orchestrator/rotation_test.go), asserting a
|
||||
handoff request fires and the task remains `StateLeased`.
|
||||
|
||||
**Still open from S11:** milestone rotation, thrash detection (N failed test
|
||||
runs / same file M times / identical tool calls as a circuit breaker with
|
||||
`reason=thrash` and populated `dead_ends`), and agent-initiated `ROTATE`. All
|
||||
three need either transcript/tool-call introspection this repo doesn't yet
|
||||
have a source for, or an explicit in-band signal from the agent — bigger than
|
||||
a threshold comparison, not attempted this pass.
|
||||
|
||||
`go build ./...`, `go vet ./...`, `go test ./...` all pass.
|
||||
|
||||
### Design consequences (not yet implemented)
|
||||
|
||||
1. **Percentages are a level, not a delta.**
|
||||
|
||||
Reference in New Issue
Block a user