The matcher compares selector ids case-insensitively, but the lock's
bundled-catalog lookup was exact-case: Anthropic/Claude-Opus-5 exact-
matched OpenRouter's flat id while getBundledModel("Anthropic", ...)
missed, silently re-enabling the aggregator shadow the lock exists to
prevent. Scan the named provider's bundled ids case-insensitively.
- Add the `providers.cacheRetention` setting to control prompt-cache retention options per request.
- Forward configured cache retention preferences through the settings-aware stream function.
- Update documentation and test coverage for long cache retention behaviors.
organizeImports sorts the type GeneratedProvider specifier ahead of the named imports, and the formatter collapses the preferred-match arrow chain to one line. Both are biome safe fixes; no behavior change. Resolves the two biome errors that were leaving the 8833 branch's check gate red.
The exact-echo check used accent-insensitive compare, but the collision
suffix path was a case-sensitive startsWith. AuthLoader-3 vs authloader
therefore leaked through as a real description.
The first HUD commit hid Name: Name. The cause was earlier: task
name was copied into identity.label, which became progress.description
and skipped generateTaskLabel. Keep the handle for id allocation, but
only treat eval label as a real UI description so the tiny-model
summary can run.
The anchored Subagents list printed only `Id: description` and treated a
label that repeated the spawn handle as a real description. Show the same
⟨role⟩ badge as inline task rows and omit descriptions that only echo the id.
Addresses review feedback on the initial commit:
- restore the trailing newline at EOF stripped by the first edit
- add a Fixed entry for this change under ## [Unreleased] in the coding-agent CHANGELOG
StopOnTextCriteria decoded the last STOP_DECODE_WINDOW_TOKENS of the whole
sequence, so prompt tokens were eligible for matching. A prompt that itself
contains the stop string stops generation at the first generated token and
yields an empty title.
Anchor the window to the generation boundary by recording the first
generated index per batch entry. Existing local title models are
unaffected: with the assistant-prefill prompt shape, the example `</title>`
tags sit outside the 32-token window for normal messages, so no shipping
model changes behavior. The bug becomes reachable with any chat-level
few-shot prompt that places the stop string near the generation boundary.
The memory-extraction prompt concatenated its instructions, few-shot
examples, and the user message into a single user turn, so a small local
model could not distinguish instructions from input and frequently echoed
the Globex/weather examples instead of extracting facts.
Send the instructions as a real system turn and the raw text as the user
turn. The tiny worker protocol gains a systemPrompt field, and Mnemopi
completion input carries task metadata so the backend selects the right
prompt per call.
Drop the code-built MEMORY_EXTRACTION_TEMPLATE rather than porting it:
prompt text belongs in .md files, and resolveMemoryCompletionInput already
overrides that template for every extraction call, so Mnemopi rendered it
only for the result to be discarded.
Measured on ONNX q4 CPU, LFM2.5-1.2B memory extraction improved from 1/8
to 5/8 once the roles were separated.
Retry: fixed changelog bundle probe asserting latest release equals VERSION (fails on releases with no coding-agent changelog content); widened issue-4593 watchdog test budgets from 5ms to 50ms against CI runner scheduling noise.
A selector like anthropic/claude-opus-5 is both the anthropic provider's
canonical selector and, verbatim, an OpenRouter model id. When the named
provider is out of the candidate set (disabled, missing creds at boot), the
exact provider-scoped reference misses and the raw-id flat match re-binds the
request onto OpenRouter's same-named model. Requests that should fail closed
instead bill the aggregator at per-token Claude prices.
Raw-id fallback is only legitimate when the named provider does not carry the
id (openai/gpt-4o:extended). Lock the reference when it does by checking the
bundled catalog, then fail rather than shadow. openrouter/anthropic/claude-opus-5
still selects OpenRouter explicitly.
isMultiplexerSession() treats TMUX, STY, ZELLIJ, HERDR_ENV=1, the CMUX_*
markers and a tmux/screen TERM as authoritative, and routes rendering down the
path that cannot rebuild scrollback. Nine tests across four files assert the
destructive full-paint behavior and fail for anyone running the suite inside
tmux, screen, Zellij or CMUX.
component-render.test.ts already cleared HERDR_ENV for exactly this reason but
covered only one of the nine signals. Replace it with a shared helper that
clears the whole family and restores it afterwards, and call it from the other
three files.
Three tests fail on a clean checkout depending on where the repo lives and
which terminal runs the suite:
- status-line-path builds its fake home inside the checkout, so a clone under
/tmp lands in a SCRATCH_ROOTS prefix and renders the scratch icon.
- status-line/component renders a fixed 120 columns, so a long checkout path
or branch name pushes the cost segment out of the assertion.
- bash-executor runs an interactive login zsh, which loads the system
/etc/zshrc; under Apple Terminal that appends session-save lines to the
captured output. HOME does not isolate a system-level file.
A developer shell with ANTHROPIC_BASE_URL set reroutes the effective endpoint
away from official, switching off eager tool-input streaming, long cache
retention, the Cowork TLS profile, the Claude Code session header and priority
service tier. 14 tests across 6 files assert those behaviors and fail on a
clean checkout.
Add withOfficialAnthropicEndpoint(), a beforeEach/afterEach pair that removes
the variable and restores it, and call it from the six affected files.
omp update re-threw Bun's raw fetch() UnsupportedProxyProtocol error, telling CLI users to pass verbose:true to fetch() — an instruction unavailable through the CLI. The update fetch catches now detect this failure and report which proxy env var uses an unsupported scheme plus the http/https requirement.
Fixes#8784
Force process termination via `postmortem.quit(0)` in
`Completions.run()` after writing completion scripts to stdout. Loading
all command modules during completion generation leaves open event loop
handles (sockets, timers) that prevent natural process exit, causing
tools like chezmoi to hang.
OpenCode substitutes {env:VAR} and {file:path} in config text at load
time, but OMP's OpenCode discovery ran the generic ${VAR}-only
expandEnvVarsDeep, leaving those tokens literal. An MCP header like
`Bearer {env:MCP_KEY}` reached the server verbatim and returned 401.
The OpenCode loader now applies OpenCode's own substitution to raw
config text before parsing: {env:VAR} -> env value or empty string,
{file:path} -> trimmed, JSON-escaped file contents resolved relative to
the config dir / ~ / absolute, skipping tokens on // comment lines.
Fixes#8778
The Home Manager module symlinked ~/.omp/agent/config.yml to a read-only
/nix/store path. OMP acquires an advisory lock on and atomically rewrites
its config when persisting runtime changes; on macOS the lock backend
creates an flock sidecar next to the target, so the first startup save
failed with "Failed to acquire native file lock ... Permission denied
(os error 13)", breaking every launch once programs.omp.settings was set.
Copy the generated config into place as a writable regular file via
home.activation instead. OMP can now lock and rewrite it, and the next
home-manager switch reapplies the declared settings. The DAG entry is
written literally so the home-manager-free module evaluation in flake.nix
keeps working; that check now asserts the activation entry.
Fixes#8775