- Built a dynamic enum from constructed built-in/hidden tools so MCP and extension tools are excluded from QA reports.
- Added allowlist guard to silently drop reports targeting non-built-in tools at runtime.
- Stripped `proxy_` prefix before allowlist check so passthrough-wrapped tools resolve correctly.
- Skipped thinking-line writes and clears when stdout is not a TTY.
- Prevented terminal title (set/push/pop) from emitting OSC/xterm escape sequences to piped or non-interactive output.
- Suppressed all ProcessTerminal control writes when stdout isn't a TTY.
- Refactored account header rendering to separate label truncation from reset suffixes and align suffix spacing.
- Introduced a shared section width calculation so provider groups reuse the same account column and bar width.
- Updated aggregate usage text to show free-percentage formatting and shortened account count labels.
- Updated auth refresh to return generation booleans and return false for missing, non-oauth, or null-rotation creds.
- Added stream auth retry logic by wrapping streamSimple and retrying once with a fresh key for pre-start 401 only.
- Added changelog note on streaming auth retries and coding-agent onAuthError flow to refresh stale credentials.
- Added snapshot and stream auth tests for headers/no-store, 304 transitions, long-poll wakes, and retry limits.
- Added generation-aware snapshot contracts with generation, serverNowMs, refresher, and rotatesInMs fields.
- Reworked /v1/snapshot serving and client fetching for If-None-Match long-poll with 304/200 status handling.
- Added status checks in remote-store and SDK/CLI snapshot paths, applying updates only when fetch returns 200.
- Added StreamOptions.onAuthError and stream one-shot 401 retry dispatch using refreshed credentials.
- Switched usage bar fill to floor+partial-block characters (▓, ▒) for finer granularity.
- Removed surrounding `[` / `]` bracket characters from bar output and adjusted column width arithmetic accordingly.
- Replaced dot-filled unknown-state bar brackets with a plain dot run.
- Added a new `setTransports` logger API to swap console and file winston transports at runtime.
- Refactored logger transport creation to lazily build rotating file logs via a shared directory helper.
- Updated auth-broker serve startup/shutdown to use structured logger output and switch to console-only logs for its headless runtime.
- Added `providerRetryWait` and `retryWait` hooks to stream/usage options so tests bypass real scheduler delays.
- Parameterized GitHub Copilot poll intervals and Copilot model retry base delay for fast test execution.
- Replaced `Bun.sleep`/`setTimeout` polling loops with `AbortSignal` event listeners in agent session tests.
- Consolidated auth-gateway E2E helpers into a shared `test/helpers` module, eliminating duplicated `checkGatewayAvailable` implementations.
- Migrated credential-disabled tests from SQLite-backed stores to an in-memory store, removing temp-dir lifecycle overhead.
- Migrated per-object caches (chat/tool starts, model fingerprints, validation contexts, provider indexes, render IDs) from WeakMap to Symbol-keyed properties on the objects themselves.
- Rewrote SSE debug tee as a single-pass inline parser, eliminating the body.tee() + readSseEvents re-parse pipeline.
- Refactored MockModel from a factory function + external WeakMap state into a self-contained class.
- Added FIFO memoization caches for heuristic candidate expansion and namespace suffix lookups.
- Added POST /v1/pi/stream endpoint that accepts canonical Context directly, skipping wire-format translation layers.
- Added client-side streamPiNative dispatch activated via Model.transport = "pi-native".
- Propagated transport field through model registry, provider overrides, and models.yml schema.
- Refactored deriveSessionId to accept explicit arguments instead of ParsedFormatRequest.
- Eliminated double clone of `raw` per SSE event by removing `toRawSseEvent` and relying on the single clone in `notifyRawSseEvent`.
- Extracted regex patterns as module-level constants to avoid recompilation on each call.
- Replaced sort-based model alias selection with a single-pass linear scan, reducing allocations.
- Added bucketed emoji dataset with prefix-indexed lookup for O(log n) suggestions.
- Implemented `:name:` inline replace that fires on closing colon without popup.
- Wired emoji suggestions and completions into PromptActionAutocompleteProvider.
- Extended AutocompleteProvider interface with trySyncInlineReplace hook.
- Added `dev.autoqa.consent` setting and single-flight popup handler wired through `InteractiveMode`.
- Added `flushGrievances` to batch-POST unpushed rows to `dev.autoqaPush.endpoint` with cooldown and single-flight deduplication.
- Added `omp grievances push` subcommand with TTY progress bar for manual draining.
- Migrated shared DB logic to `openAutoQaDb` (with `pushed` column migration) exported from `report-tool-issue`.
- Wrapped initial and subsequent print-mode prompts with `logger.time` for timing instrumentation.
- Printed collected timings after session run when `PI_TIMING` env var is set.
- Added fire-and-forget `preconnectModelHost` to prime DNS/TCP/TLS/H2 before the first API call, saving 100–300ms on transcontinental connections.
- Skipped LSP warmup for non-UI (print/script) sessions to avoid CPU contention with LLM stream consumers.
- Added `omp auth-gateway serve/token/status` — a forward-proxy injecting broker credentials for OpenAI Chat, Anthropic Messages, and OpenAI Responses wire formats.
- Added `GET /v1/usage` to auth-broker and auth-gateway; usage cache switched to 5-min per-credential TTL with jitter and last-good fallback on failure.
- Added `AuthStorage.setConfigApiKey/removeConfigApiKey/clearConfigApiKeys` so `models.yml` `apiKey` beats OAuth tokens without overriding `--api-key`.
- Added `omp auth-broker migrate --from-local` for idempotent upload of local SQLite/env credentials to the broker.
- Added `AuthBrokerClient`, `RemoteAuthCredentialStore`, `AuthBrokerRefresher`, and `startAuthBroker` server in `packages/ai/src/auth-broker`.
- Renamed `AuthCredentialStore` class to `SqliteAuthCredentialStore`; extracted `AuthCredentialStore` as a persistence interface.
- Added `exportSnapshot`, `forceRefreshCredentialById`, `disableCredentialById`, and `upsertCredential` to `AuthStorage` for broker wire protocol.
- Added `omp auth-broker` CLI subcommand (serve, token, login, logout, import, status) and `discoverAuthStorage` broker-mode path keyed on `OMP_AUTH_BROKER_URL`.
- Appended a unique nonce query param to local file imports so Bun treats each reload as a fresh module record.
- Restricted cache busting to relative/absolute path specifiers; bare packages and built-ins are left unchanged.
- Non-interrupting tool-source TTSR matches now prepend a system-reminder to the matched tool's `toolResult` content instead of queuing a loop-wide deferred follow-up turn.
- Text/thinking source matches retain the previous deferred-injection behavior.
- Added deduplication so one rule attaches to exactly one sibling tool call per batch.
- Stale per-tool injections are cleared on abort/error before tools produce results.
- Removed the legacy `parseEvalInput` parser module and `eval.lark`, eliminating `*** Cell` stream parsing.
- Replaced eval tool arguments from single `input` strings to ordered `cells` arrays in tool calls and schema.
- Updated execution to resolve language explicitly, map `py` to `python`, and apply timeout/reset defaults.
- Removed backend sniffing and `ABORT_WARNING` suffix handling, then updated docs and tests to the new JSON cells format.
- Replaced all StringEnum(...) usages with z.enum([...]) across tools, examples, and tests.
- Removed StringEnum re-export from @oh-my-pi/pi-coding-agent public API.
- Condensed verbose tool parameter descriptions to minimal lowercase phrases.
- Renamed AuthCredentialStore to SqliteAuthCredentialStore at usage sites.
- Implemented a unified normalization flow by switching Google/CCA handling to normalizeSchemaForGoogle/CCA.
- Added normalize.ts with recursive node normalization, nullable-union checks, and combiner collapsing.
- Removed sanitize-google.ts and normalize-cca.ts, replacing them with normalize exports in schema indexes.
- Added spill-to-description utilities with spill/paren modes and `$defs` exclusion for unsupported fields.
- Updated MCP bridge and schema tests to use normalizeSchemaFor* APIs with expanded compatibility checks.
- Documented normalization behavior changes and breaking rename in constraints and package changelog files.
- Renamed the internal URL protocol handler from `pi` to `omp` and updated the router export/import wiring to use `OmpProtocolHandler` with the `omp://` scheme.
- Updated embedded documentation link rendering and related validation/error messages in the protocol handler to reference `omp://` URLs.
- Adjusted tests and prompt/docs references so `read` examples and harness documentation guidance now use the renamed `omp://` scheme.
- Replaced `finishCleanup` callback with `isPromptTurnInFlight` predicate to unify settled+cleanup gating.
- Extracted `#beginCancelCleanup` (idempotent) and `#runCancelCleanup` to clarify ownership of slot eviction.
- Fork, queue, and close paths now all gate on the combined settled+cleanup window.
- Added optional AgentTelemetry to summary, handoff, branch-summary, and compact option types.
- Replaced one-shot `completeSimple` usage with `instrumentedCompleteSimple` across compaction, summary, and branch-summary calls and passed `oneshotKind`.
- Added `PiGenAIAttr.OneshotKind`, `InstrumentedChatSpanOptions`, and response-header forwarding in telemetry span lifecycle.
- Added `resolveTelemetry` propagation in coding-agent session and inspect-image paths to pass request-scoped telemetry.
- Added compaction telemetry test harness and span assertions for success, no-telemetry, and error cases.
`getProjectPathCandidates` walks up from cwd to repoRoot (or home as a
fallback). When cwd is anywhere under $HOME and no closer .git boundary
exists, that walk-up reaches the home directory and enumerates
`~/.agent/<segments>` and `~/.agents/<segments>` as project paths.
`getUserPathCandidates` then enumerates the very same directories as
user paths, so every skill/rule/prompt/command/AGENTS.md found there
loaded twice. The capability deduper marks the second copy as shadowed,
but the Extension Dashboard renders shadowed entries — so users see one
active + one greyed-out duplicate of every home-level skill.
Skip the home directory inside the walk-up while still terminating the
loop on it; ancestors above home are still visited if the cwd happens
to live above (e.g. monorepo `home: tempDir` test fixtures).
Tests:
- Drop the duplicated copy of `getProjectPathCandidates` from the
monorepo-skills test; import the real one so behavior stays in sync.
- Replace the old "walk-up stops at home when no repo root" assertion
(which encoded the buggy behavior) with one that pins the new
contract: home-level `.agent[s]/skills` are NOT enumerated as
project paths.
- Add an explicit regression assertion that project ∩ user candidate
sets are empty when cwd is under home.
Fixes#1116
The PTY runner hardcoded CommandBuilder::new("sh"), but on Windows the
user's shell might be a Git Bash absolute path that isn't on PATH. The
non-PTY path already uses the resolved shell from getShellConfig(). Now
the PTY path does the same, passing it through PtyStartOptions.shell.
ConPTY's ClosePseudoConsole can deadlock when it tries to flush output
to a pipe that nobody is reading (microsoft/terminal#1810). This caused
the PTY Promise to never resolve on Windows, making bash commands with
pty:true hang indefinitely.
Root cause: portable-pty's drop(master) calls ClosePseudoConsole
synchronously. If ConPTY's internal render thread is blocked writing to
a full/undrained output pipe, ClosePseudoConsole waits forever.
Fix (three parts):
1. Rust (pty.rs): Reordered teardown to follow Microsoft's recommended
shutdown sequence:
- Drop writer first (close ConPTY input pipe)
- Drain reader thread with 500ms timeout (consume output pipe)
- Drop master in a background thread with recv_timeout(2s):
* Clean case: ClosePseudoConsole completes, thread reclaimed
* Hung case: timeout expires, main thread returns anyway
- Replace child.wait() with try_wait() polling on Windows
(WaitForSingleObject can also hang in ConPTY)
2. TypeScript (bash-pty-selection.ts): Remove the Windows blanket
disable that prevented PTY from ever being used on Windows.
3. Tests: Updated to verify PTY works on Windows with UI context.
Replaces the blanket PTY disable on Windows (PR #1105) with a targeted fix:
- TypeScript: PI_FORCE_PTY env var allows explicit Windows PTY opt-in.
PTY is still disabled by default on Windows to prevent hangs, but power
users who need interactive workflows can override.
- Rust: Adds ct.heartbeat() checks during PTY setup (openpty, spawn, reader
creation) so the existing timeout mechanism works even during setup.
- Rust (Windows): Wraps openpty() in a 5-second startup timeout thread.
If ConPTY hangs during pseudo-console creation, the Promise rejects with
a clear error instead of hanging forever.
Fixes#1103#1106
- Preserved object schemas with explicit `additionalProperties` settings by avoiding strict coercion to false.
- Probed schema strictness before sanitization and set `tool.strict` false for non-strict schemas.
- Set `tool.strict` false for `null`, `true`, and unconstrained `outputSchema` fallbacks.
- Documented the fix in Unreleased changelog entries for both `ai` and `coding-agent` packages.
- Added regression tests covering loose `additionalProperties` and yield strictness behavior across tools.
- SearchTool now tracked the last emitted line and inserted ellipsis markers when noncontiguous match blocks were output.
- Display output gap markers were padded to align with code-frame gutters.
- Added a regression test that verified a no-context search emits an ellipsis between separated matches in the same file.
- Unified line-ending normalization to `replace(/\r\n?/g, "\\n")` in editor, scraper, benchmark, and utils modules.
- Added terminal-aware line sanitization in code-cell rendering to collapse inline carriage returns and avoid overwrite corruption.
- Tightened editor and paste sanitizers to trim control characters consistently after CR normalization.