Registered live session resume commands with postmortem handling so a
fatal rejection or exception identifies every recoverable agent before
cleanup. Escaped terminal control characters in recovery output.
Reset-window rotation requires account-specific wording; concurrency caps require an actual cap signal; credential removal gated on AuthFailed without UsageLimit so a valid-but-blocked 403 credential is retained.
(cherry picked from commit 2f72752c2586352a4f7e9e814af1cdb0cf192af4)
Account-reset hint evaluated before short retry hints; account-scoped caps rotate on status 403 or undefined (Devin statusless trailer); statusless concurrency caps marked transient; transient same-model retries use the concurrency backoff.
Refuted: quota-worded concurrency caps were already excluded from rotation before the usage-limit text match.
(cherry picked from commit f2b9a18d715ddbcb6ae703670f2212da36bb2826)
A classifier refusal returned before the `onTurnError` hook that owns
model fallback, so `AdvisorRuntime` treated one provider's policy verdict
as terminal: `Refusal (cyber)` on the advisor model disabled the advisor
outright even with a fallback chain configured. Its only recovery was
stripping echoed primary reasoning and resending once, which does nothing
for a refusal about the content itself.
Route a refusal that outlives the strip through the same hook the generic
failure path uses, mirroring its epoch guard, session-transition requeue,
and requeue-on-recovery. The cascade walks the chain to exhaustion and
only reports the advisor unavailable once the host runs out of candidates,
matching what turn-recovery already allows for the primary.
Each cascade visits a model at most once. A switch re-arms
`#includeThinking` through `#syncModelIdentity`, so chain keys that point
back at each other (A to B, B to A) would otherwise strip-and-resend
against the same pair forever. A successful turn or a reset starts a
fresh walk.
Also stop `/advisor status` throwing when a live advisor has no roster
entry: `formatAdvisorStatus` guarded only the inactive case before
dereferencing `stats.advisors[0]`, and `#ensureAdvisors` clears
`#advisorStatuses` before repopulating it, so a status call landing in
that window hit `undefined.contextWindow`.
Made text replay safety depend on whether the active output sink has committed streamed text.
Kept tool calls, images, and server tools replay-unsafe while covering text and JSON print policies plus a transient socket-close recovery.
Fixes#7625
Align isUnexpectedStopCandidate with #isEmptyAssistantStop: only a signed (non-whitespace thinkingSignature) thinking-only stop is a candidate. Unsigned thinking-only stops stay with the empty-stop retry path and its cap, so unexpected-stop classification no longer re-handles a turn the empty-stop cap already gave up on.
Fixes#7499
isUnexpectedStopCandidate only counted non-whitespace text blocks, so a stopReason:"stop" turn whose sole content was a signed thinking block bypassed the unexpected-stop guard entirely. #isEmptyAssistantStop treats signed thinking as terminal (not empty), so such stops fell through both recovery handlers and the agent silently stopped mid-task.
Count non-whitespace thinking blocks as candidates and feed the thinking text to the classifier when no text block is present.
Fixes#7499
Branched session files preserve entry ids, so leaf-id equality alone let a stale /btw answer promote into a different loaded session. Capture the originating session id at /btw start and require it to match at both the controller gate and every branchFromBtw checkpoint.
Fixes#7474
- Passed the authorized leaf through the branch executor and revalidated it before rewriting history.
- Refused promotion during active turns and bounded post-prompt drains.
- Consumed unavailable branch keys while showing pending and refusal state in the panel.
Fixes#7474
Publish terminal daemon completions to the session that started the
process so idle agents can resume without polling hub status.
Persist every unacknowledged generation with a stable completion ID and
immutable snapshot. Replay the collection after reconnect or broker
recovery, and clear each event only after the owning client acknowledges
it.
Signed-off-by: Christian Stewart <christian@aperture.us>
- Added shared Python call and literal serialization utilities with multiline verbatim support.
- Standardized tool inventories to format as an OpenAI-Harmony functions namespace using TypeScript declarations.
- Updated tool normalization and rendering functions to accept options objects and default to Python-syntax examples.
- Refactored Gemini dialect rendering to leverage shared serialization functions directly.
Completed transcript entries now write through to the OS page cache on
append instead of microtask-batching, supersede in-flight atomic rewrites
with a synchronous full-body publish, and land on the live moveTo path
(source pre-rename, destination post-rename) so a software crash no longer
drops finished user/assistant/tool events. Streaming text remains durable
only at message_end; no fsync/power-loss guarantee is claimed.
Hard-coded 'scout' references reached the model even when the scout
agent was disabled via task.disabledAgents or absent from the session
spawn list. Gate every such reference on scout actually being spawnable:
the task tool description, the delegation gates, the plan-mode and
workflowz notices, the glob/grep/ast-grep guidance, and the task
specialization advisory. Prompt shape is otherwise unchanged; only
erroneous references to the unavailable subagent are dropped.
Closes#7313
A recovered artifact:// read is an ordinary read result, so the next shake
pass elides it into a new artifact, indefinitely. Extends the 5f9558d17a
spill exemption to shake; the dead-end rescue gets a dedicated config
instead of falling through to AGGRESSIVE. Manual /shake unchanged.