Kept the Bun event loop live across subagent yield drains and delayed parent result flushes. Added a timer-lifecycle regression for the idle flush.
Fixes#8462
Expose the Pi-compatible tui, rpc, json, or print host mode to every extension context and cover mode transitions in the runner regression suite.
Fixes#8419
- Generalized thinking loop guard and helper functions to support Gemini, DeepSeek, and Grok model families.
- Replaced `withGeminiThinkingLoopGuard` and related Gemini-specific symbols with generalized counterparts.
- Removed deprecated `enableGeminiThinkingLoopGuard` options and associated tests.
- Updated test suites and agent session logic to use the generalized thinking loop guard and model family tokens.
- Replaced blanket subagent advisor global settings with fine-grained per-agent configuration and frontmatter support.
- Added dashboard keybindings and inline override editors for managing agent advisor patterns.
- Implemented settings migration logic to convert legacy global options into per-agent settings.
- Updated session persistence and execution layers to restore and enforce per-agent advisor behaviors.
- Added a 60-character minimum length threshold for demoting interrupted thinking into hidden continuity context in agent-session.ts.
- Updated LLM message conversion in messages.ts to strip incomplete thinking from user-interrupted assistant turns regardless of continuity note presence.
- Added test coverage in agent-session-interrupted-thinking.test.ts verifying behavior for reasoning lengths below and at the threshold.
- Added the `--external-thinking` CLI flag alongside model capability checks to gate external thinking tool availability.
- Updated Anthropic and Google transports to honor `forceReasoningOff` for native thinking-off controls.
- Renamed the `thoughts` property and parameter to `notes` across think fixtures, tools, and tests.
- Updated system prompt instructions and test suites to verify transport-specific thinking and tool activation.
- Added support for external thinking and forced reasoning disablement across AI provider options and request transformers.
- Implemented the private scratchpad think tool along with its renderer, system prompt rules, and schema configuration.
- Updated agent session management and SDK tools to support dynamic runtime activation of the think tool via the externalThinking setting.
- Added comprehensive unit tests covering reasoning fallbacks, tool activation, and rendering behavior.
/handoff mints a fresh session via newSession(), producing a new
artifactsDir and an empty local/ root. The handoff document routinely
references plans and scratch files under '/data/workspaces/can1357__oh-my-pi__8261/.omp-session/2026-08-11T16-39-09-489Z_019ff1b1-31b1-7000-81f5-c540f4ebf43d/local/,' so every reference
became a dangling pointer in the new session. The plan approve-and-execute
path already copies artifacts across the boundary; handoff did not.
Extracted the plan-approve copy helper into a shared copyLocalArtifacts()
in local-protocol.ts and invoke it across the handoff session switch
(best-effort, since the switch is already committed).
Fixes#8261
Allowed advisor streams to treat Google STOP responses without visible content as successful silence while preserving the default retry behavior for interactive agents.
Added provider and advisor-path regressions covering retry counts, system instructions, and the advise declaration.
Fixes#8223
Every session dispose broadcast the shutdown abort reason, so an explicit
hard kill of a subagent (release with tombstone, then live.dispose()) tagged
its nested children as shutdown and rediscovered them as parked instead of
terminal.
- Gate ASYNC_JOB_MANAGER_SHUTDOWN_REASON on #ownedAsyncJobManager so only the
top-level owning session's dispose (genuine process shutdown) uses it.
- Subagent disposes propagate a generic cancellation, keeping nested children
terminal.
- Cover the subagent generic-cancel path alongside the owning-session shutdown.
Fixes#8216
Session teardown pre-cancels owner jobs via #cancelOwnAsyncJobs before
manager.dispose(), so the shutdown abort reason must ride along that
cancelAll or an owned subagent job sees a generic caller signal and is
tombstoned instead of parked.
- Forward an abort reason through AsyncJobManager.cancelAll.
- Pass ASYNC_JOB_MANAGER_SHUTDOWN_REASON from #disposeOwnedAsyncJobs.
- Cover owned-job shutdown tagging through a real AgentSession dispose.
Fixes#8216
System and mode prompts referenced tools that may be absent from the
session catalog, forcing the model to satisfy requirements it cannot
execute (generalizes #8139's browser-verification mismatch):
- system-prompt.md: browser verification now keys on the actual UI
surface and available tools (browser/computer/TUI/CLI), with an
explicit behavioral/smoke-test fallback when no runtime tool exists;
todo workflow guidance and the AST-section grep hint are gated on
tool presence; the auto-QA report_issue block additionally requires
the write tool.
- project-prompt.md: workspace-tree drill-in and additional-roots tool
hints only name tools present in the session.
- plan-mode-active.md: ask-tool directives get a prose fallback and
scout-via-task dispatch is gated on the task tool (render site now
passes askAvailable/taskAvailable).
- orchestrate-notice.md: the tool budget, verify gates, todo tracking,
and inline-edit guidance are gated on tool presence; the notice is
skipped entirely when the task tool is inactive (render fn takes the
active tool list).
Adds regression tests for each gate; changelog entry.
The renderer-provenance gate (PR #7774) keys the built-in tool renderer
registry on `hasBuiltInTool(name)`. In apply_patch mode the built-in `edit`
tool presents on the wire as `apply_patch` (`customWireName`), and tool cards
render the streamed call under that wire name. `hasBuiltInTool` only checked
literal registry names, so `hasBuiltInTool("apply_patch")` was false and the
edit renderer/preview was skipped.
Resolve a built-in tool's `customWireName` alias to its built-in owner, while
still letting an extension that registers the literal alias name shadow it
(the agent loop routes exact-name matches ahead of wire aliases).
Fixes#8184
The auto_compaction_end event and its frame-rescue variant emitted the unstripped snapcompact preserveData, forcing the RPC shrink ladder on every unattended pass and risking a silently dropped event. Strip the archive from both event payloads while keeping it in the persisted compaction entry.
Fixes#8168
Kept the frame archive in the persisted compaction entry while omitting it from the returned CompactionResult, preventing protocol v1 from reporting a false failure after a completed manual compaction.
Fixes#8168
Why:
The module-global array memo strongly retains the most recently converted
transcript and output after its session is disposed.
Changes:
- Store exact-repeat and append-growth state in a WeakMap per input array.
- Preserve generation invalidation and per-message weak caching.
Evidence:
- Seven disposal runs collected both arrays after 50 forced-GC passes and
reduced median heap delta by 87.54%.
Refs #8119
Why:
SessionManager.open() parses the complete journal for its header and then
setSessionFile() parses the same journal again.
Changes:
- Reuse the entries already loaded by open() through a private setup path.
- Keep the public setSessionFile() contract unchanged.
Evidence:
- A 19.98 MB, 12,000-entry journal improved from 48.011 ms to
25.406 ms median across 15 runs with identical restored state.
Refs #8117