docs(turn-loop): document PromptTooLong archive+requeue, TurnOutcome=Result, credential-file session detection
This commit is contained in:
parent
90af3e8d0b
commit
dd7f8c5ebb
1 changed files with 25 additions and 14 deletions
|
|
@ -43,14 +43,18 @@ Each agent harness (`hive serve` — one binary for all agents) runs:
|
||||||
the per-agent web UI login flow; on success the sentinel is
|
the per-agent web UI login flow; on success the sentinel is
|
||||||
cleared and the queued message drives the next turn normally.
|
cleared and the queued message drives the next turn normally.
|
||||||
**Mtime-snapshot resumption**: `wait_for_login`
|
**Mtime-snapshot resumption**: `wait_for_login`
|
||||||
snapshots the `~/.claude/` dir (newest file mtime + file count)
|
snapshots the `~/.claude/` dir (newest mtime + count over the
|
||||||
at entry and only resumes when that snapshot advances — not
|
credential files in `login::CRED_FILE_NAMES`) at entry and only
|
||||||
just when credentials exist on disk. This prevents a silent
|
resumes when that snapshot advances — not just when credentials
|
||||||
infinite-401 loop: stale credentials already on disk at the
|
exist on disk. This prevents a silent infinite-401 loop: stale
|
||||||
time of the 401 no longer cause an immediate false-resume. The
|
credentials already on disk at the time of the 401 no longer cause
|
||||||
`DirSnapshot` struct tracks both axes; either a mtime advance
|
an immediate false-resume. The `DirSnapshot` struct tracks both
|
||||||
OR a file-count change triggers resume (the count axis handles
|
axes; either a mtime advance OR a file-count change triggers resume
|
||||||
filesystems where `modified()` errors on every file).
|
(the count axis handles filesystems where `modified()` errors on
|
||||||
|
every file). Boot detection (`login::has_session`, deciding Online
|
||||||
|
vs NeedsLogin) keys off the same `CRED_FILE_NAMES` set — the files
|
||||||
|
`/logout` deletes — so leftover session-history files don't read as
|
||||||
|
a live session after a logout + container recreate.
|
||||||
7. Emit `LiveEvent::TurnEnd { ok, note }`. Sleep `poll_ms` to avoid
|
7. Emit `LiveEvent::TurnEnd { ok, note }`. Sleep `poll_ms` to avoid
|
||||||
tight loops on transient failures.
|
tight loops on transient failures.
|
||||||
|
|
||||||
|
|
@ -108,14 +112,16 @@ and the manager fall through to operator).
|
||||||
|
|
||||||
### Turn outcomes
|
### Turn outcomes
|
||||||
|
|
||||||
`turn::TurnOutcome` drives the post-claude branch:
|
`turn::TurnOutcome` (`Result<bool, TurnError>` — `Ok(compacted)` on success,
|
||||||
|
else a `TurnError`) drives the post-claude branch:
|
||||||
|
|
||||||
| Outcome | Action |
|
| Outcome | Action |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `Ok` / `Compacted` | `ack_turn` |
|
| `Ok(_)` (`false` normal / `true` compacted) | `ack_turn` |
|
||||||
| `RateLimited` | sleep `HIVE_RATE_LIMIT_SLEEP_SECS` (default 300), requeue inflight, status back to `online` |
|
| `Err(PromptTooLong)` | `drive_turn` archived the session (the lib already compacted + retried and it still overflowed); requeue inflight so the message redelivers into a fresh session that fits — no status park |
|
||||||
| `AuthFailed` | emit `needs_login_idle` sentinel, requeue inflight, park in `wait_for_login` |
|
| `Err(RateLimited)` | sleep `HIVE_RATE_LIMIT_SLEEP_SECS` (default 300), requeue inflight, status back to `online` |
|
||||||
| `Failed(err)` | route `[system] \`<qualified-label>\` claude turn failed:\n<err>` to `<parent>` via `send_to_parent` |
|
| `Err(AuthFailed)` | emit `needs_login_idle` sentinel, requeue inflight, park in `wait_for_login` |
|
||||||
|
| `Err(Failed(err))` | route `[system] \`<qualified-label>\` claude turn failed:\n<err>` to `<parent>` via `send_to_parent` |
|
||||||
|
|
||||||
After the outcome handler, the stats sink records a row and the
|
After the outcome handler, the stats sink records a row and the
|
||||||
`hyperhive-continue` sentinel (dropped by the `request_next_turn`
|
`hyperhive-continue` sentinel (dropped by the `request_next_turn`
|
||||||
|
|
@ -233,7 +239,12 @@ window with two triggers baked into its `run`:
|
||||||
- **Reactive** — claude-code prints `Prompt is too long`. The session is
|
- **Reactive** — claude-code prints `Prompt is too long`. The session is
|
||||||
*already* past the window, so no turn can run on it — the session
|
*already* past the window, so no turn can run on it — the session
|
||||||
`/compact`s straight away and retries the same wake-up prompt once. No
|
`/compact`s straight away and retries the same wake-up prompt once. No
|
||||||
notes-checkpoint turn is possible here: the detail is gone.
|
notes-checkpoint turn is possible here: the detail is gone. If the retry
|
||||||
|
*still* overflows, `run` surfaces `Error::PromptTooLong`; `drive_turn`
|
||||||
|
then archives the session (session lifecycle stays hive-side) and the
|
||||||
|
serve loop requeues the message so it redelivers into a fresh session
|
||||||
|
(see [Turn outcomes](#turn-outcomes) — the wake prompt itself is tiny, so
|
||||||
|
the overflow was the accumulated context the archive clears).
|
||||||
- **Proactive** — a turn finishes cleanly but the last inference's context
|
- **Proactive** — a turn finishes cleanly but the last inference's context
|
||||||
size crossed the policy watermark. While the session is still healthy it
|
size crossed the policy watermark. While the session is still healthy it
|
||||||
runs one synthetic *notes-checkpoint* turn (`CHECKPOINT_PROMPT` —
|
runs one synthetic *notes-checkpoint* turn (`CHECKPOINT_PROMPT` —
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue