The symmetric-padding change shrank the framed-block content width to
outputBlockContentWidth(width); the Ask renderer still pre-rendered its
question/result Markdown at the old width-2 budget, so maximal-width rows
re-wrapped inside the block and spilled a trailing fragment row.
Track tool-call ids whose failed-attempt cards were retracted until agent-loop emits their synthetic skipped-tool completion. Ignore the synthetic start and consume the matching end so the no-pending handler cannot recreate the failed card.
Extended the retry regression through the exact message_end -> synthetic tool start/end -> auto-retry sequence.
Fixes#6879
Seal an uncommitted pending tool card before removing it from the transcript so ToolExecutionComponent cancels its spinner, todo strike, and edit-preview work instead of continuing to schedule renders while detached.
Added a fake-timer regression proving an animated write card renders while pending and stops component-scoped renders after an aborted turn retracts it.
Fixes#6879
Reset #lastReadGroup before retracting a superseded grouped read so the retry creates and mounts a fresh group instead of updating the detached component. Clear the removed call's read tracking as well.
Added regression coverage for an aborted grouped read followed by a visible successful retry.
Fixes#6879
An assistant turn that streamed tool calls and then ended with error/aborted
(a provider blip that auto-retries, a TTSR rewind) has its never-run cards
dropped from the active context, but EventController#handleMessageEnd only
sealed them in place. The retry re-streamed fresh cards below, so each call
rendered twice.
Retract the never-run pending tool cards still in the live region (never
committed to native scrollback, so removable) and forget them from pendingTools
and the timeline map at message_end; a card already on the scrollback tape is
still sealed in place. Follow-up to #6516 / #6519.
Fixes#6879
- Add `omp cleanse` command and workflow execution infrastructure.
- Implement project file discovery, automatic checker execution, and multi-format diagnostic parsing.
- Provide subagent dispatch, session runtime, and task balancing with bin packing.
- Include comprehensive tests for diagnostic parsing and orchestration loops.
- Kept the last successfully classified effort when a later classification fails.
- Added regression coverage for the success-then-failure transition.
Fixes#6877
Only a peer-scoped wait (from, no ids) is internal messaging; bare and ids waits settle on background-job delivery whose snapshot is the job result.
Fixes#6872
Treated an object-valued mcpServers manifest field as the server map, rooting relative stdio paths at the plugin root, so plugins declaring servers inline no longer fell through to .mcp.json.
Fixes#6871
Resolved mcpServers file pointers from OMP and Claude plugin manifests before the conventional root config fallback.
Updated marketplace installer documentation for runtime symlink and lockfile registration.
Fixes#6871
- Reworked the `/guided-goal` command to send a hidden interview brief instead of a modal popup flow.
- Removed the deprecated `guided-setup.ts` module and system prompt template.
- Updated goal tool availability and activation logic to support goal creation during the interview.
- Replaced existing tests and added new verification for the updated guided-goal workflow.
Upstream @earendil-works/pi-ai re-exported isContextOverflow from its
package root, but omp's @oh-my-pi/pi-ai barrel forwards only
./error/rate-limit, so the shim's `export * from "@oh-my-pi/pi-ai"` left
it off the surface. Plugins importing it (pi-blackhole) tripped Bun's
static named-export check during validation, both on disk and through the
omp-legacy-pi-bundled: virtual namespace.
Audited the upstream root surface rather than fix one symbol at a time:
of its runtime exports only isContextOverflow (now under
@oh-my-pi/pi-ai/error) and parseJsonWithRepair/parseStreamingJson/
repairJson (relocated to @oh-my-pi/pi-utils) still exist in omp. Bridge
exactly that set through the shim and pin it with a regression test that
exercises each helper's behavior.
Fixes#6859
- Remove the per-call `save` option from `tab.screenshot()` to simplify usage.
- Update `tab.screenshot()` to return the saved file path as a promise string.
- Configure screenshot persistence to use daemon path or custom `browser.screenshotDir`.
- Add comprehensive tests verifying temp path return and custom directory saving.
A recovered detached daemon has no in-memory process handle, so two
concurrent refreshes can both enter settle for the same dead pid. The
initial guard runs before detached output is read; both continuations
could therefore pass it and then double-settle the generation.
Recheck generation and settled states after the awaited output read,
and cover concurrent refreshes against a recovered daemon. Without the
post-read guard the regression test observes restartCount 2 instead of
1.
Fixes#6852
A detached restart:"always" daemon that exits quickly parks in the
`restarting` state with process/pid cleared and a restartTimer armed.
Every subsequent op ran #refreshDetached, which only skips terminal
states, so it fell through to a re-entrant #settle. #settle's guard
only checked generation and terminalState, so re-entry proceeded:
restartCount++ and record.restartTimer was overwritten without clearing
the previously armed timer, orphaning it.
Consequences: stop cleared only the last timer, so an orphaned timer
later fired #launch (resetting stopRequested) and resurrected the
daemon; and restartCount phantom-inflated on every list/logs poll.
Add `restarting` to #settle's entry guard: it is a settled state
(child exited, relaunch timer pending) and no legitimate caller settles
while in it. Closes both the timer leak and the count inflation.
Fixes#6852
Historical @earendil-works/pi-ai exports isRetryableAssistantError from its
package root (utils/retry.ts), but OMP's legacy-pi-ai-shim re-exports
@oh-my-pi/pi-ai, whose root never carried the symbol. Plugins importing it
(e.g. @router-for-me/pi-cliproxyapi-provider >= 1.4.9) failed Bun's static
named-export validation, rolling back install.
Port the upstream transient-error classifier into the shim, preserving the
provider-error wording tables so legacy retry semantics match.
Fixes#6847
- Remove `annotateForStaleness` and `hasFreshBacklog` from the advisor runtime.
- Stop appending staleness warnings to delivered advisor notes when newer primary turns queue.
- Add the `ts-no-local-is-record` built-in rule to detect local `isRecord` definitions and direct agents to shared guards.
- Add unit tests validating detection of local function and lambda definitions for the new rule.
- Replaced getTool with getExecutableTool in CursorExecBridgeOptions to prioritize mounted-device permission wrappers over canonical tools.
- Updated createAgentSession to check isAutoQaEnabled against restricted tool filtering when configuring system prompts.
- Added test coverage verifying execution overrides preserve approval gates and restricted sessions omit auto-qa guidance.
- Replaced the `XdevRegistry` class with the `XdevState` interface and pure helper functions across core and session tools.
- Updated session configurations, tool execution, and renderers to utilize canonical tool map initialization and sharing.
- Adapted unit tests and mocks to use `XdevState` and associated helper functions for permission and dispatch verification.
User-initiated `!`/`$` (and RPC bash) executions persist as
`bashExecution`/`pythonExecution` roles, which are always user-run —
the model's bash goes through `toolCall`. The history serializer emitted
them as a bare `→ bash! …` line and cleared the watched-mode role label,
so in advisor deltas the command trailed the `**agent**:` block with no
user attribution. The advisor then misread user-run commands as agent
actions (e.g. a false blocker over a user-run worktree cleanup).
Render these lines under a `**user**:` label in watched mode and prefix
them `→ user-bash!` / `→ user-python!` so provenance is explicit in every
render path.
Fixes#6837
- branch() and navigateTree() now return the selected user message's image
parts (selectedImages/editorImages) alongside the text, extracted in marker
order by #extractUserMessageImages.
- CustomEditor.setDraft() replaces the composer draft with text plus its
pending images, so restored [Image #N] markers resolve on resubmit instead
of degrading to literal text.
- Wired all six restore call sites (selector-controller, extension-ui-controller)
through setDraft; updated rpc-subagents mocks for the new branch shape.
- Added offline regression tests for branch/navigateTree image restitution,
multi-image marker order, and text-only prompts.
- read now treats an xd://-mounted inspect_image as available (top-level
predicate OR mounted device gated by the effective mode), so default
xdev sessions with a text-only model keep metadata-guidance reads
instead of inlining images the provider boundary would scrub
- advisor tool session stops inheriting the primary's isToolActive and
xdevRegistry: advisors cannot execute xd:// devices, so their reads
inline images again
- setModelWithProviderSessionReset is now async and awaited at every
callsite, so retry-fallback model switches cannot race the
inspect_image tool-slate reconcile
- regression tests for both xd:// availability directions