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.
Compiled Bun binaries autoload project dotenv files, so snapshotting Bun.env inside one captured the secrets as launcher-owned and forwarded them to every shell. Drop that branch and record launcher values, restoring an empty launcher value that Bun overwrote with a dotenv secret.
- filterChildShellEnv now also filters Bun-autoloaded .env.{NODE_ENV||development}
entries, closing the .env.production/.env.development leak into child shells.
- parseEnvLine skips backslash-escaped quotes when locating the closing
delimiter, restoring baseline/Bun-literal handling of values like JSON="{\"a\":1}"
that the new parser truncated.
- Adds a parseEnvFile regression test for escaped quotes.
startDaemonBrokerFromEnvironment now sets the kernel-visible name via
prctl, so restoring only process.title left the test runner's
/proc/self/comm as "omp daemon brok" for the rest of the Linux run.
applyAnthropicUsageExtras writes usage.cttl from cache_creation while
usage.cacheWrite is written from cache_creation_input_tokens; the two
are independent wire fields, so a partial or stale breakdown made the
unattributed remainder cost $0. Price the remainder at the flat 5m
rate so the ttl split can only re-price write tokens, never drop them.
`CDPATH=` already cleared the variable for the `cd` subshell, so this is
a readability-only change: `CDPATH=''` is the identical POSIX assignment
written with explicit empty quotes. No behavior change, and there was no
CDPATH leak to fix.
- 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.
- Updated the nightly rust toolchain channel in rust-toolchain.toml to nightly-2026-07-28.
- Adopted slice chunking and multiple-of helper methods across native and vendor crates.
- Replaced option map adapters and conditional patterns with idiomatic combinators.
calculateCost priced every cache-write token at model.cost.cacheWrite,
which the catalog populates with Anthropic's 5-minute write rate
(1.25x base input). omp defaults to 1-hour cache retention on
first-party Anthropic, and Anthropic bills 1h writes at 2x base input,
so every default-path cost was understated by a factor of 1.6.
The usage.cttl breakdown needed for correct pricing is already parsed
and stored but calculateCost never read it. Now each component is
priced at its own rate: 5m at cost.cacheWrite, 1h at input*2
(Anthropic's published, model-independent multiplier). Providers that
omit cttl keep the flat-rate calculation.
Fixes#6876
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.
The 17.1.6 Bazel migration dropped maudio's generate-bindings feature, so
the darwin addon shipped maudio-sys's Linux-shaped pregenerated miniaudio
bindings. Those bindings omit the MA_SUPPORT_COREAUDIO backend-state union
members that the macOS build of miniaudio.c actually contains, producing a
Rust/C ABI mismatch: capture callbacks saw zero channels and yielded no PCM.
Re-enable generate-bindings for apple targets only. Patch maudio-sys's build
script to branch on Cargo's TARGET rather than the build-script host, so a
macOS-hosted Linux/Windows cross-build keeps target-family pregenerated
bindings instead of incorrectly running Darwin bindgen. Repin the Bazel graph
to apply the patch and gate bindgen behind the apple target selects.
Fixes#6846
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.