Only llama-swap answers what is loaded, so behind a gateway such as Bifrost
nothing was marked and the picker fell back to discovery order apart from the
one CLI that had launched there before. A live session whose own injected
endpoint is that host now promotes its model as "In use by a session", under
its own tag and below llama-swap's "Currently loaded" answer, reading only
what Codeman injected rather than terminal text, and never a stopped session.
When genuinely nothing is known the picker says so instead of leaving an
unmarked wall, and stays quiet for an endpoint that merely failed to answer.
Round-four review smaller item: one getCustomModelForPersist().launchModel expectation, like the pi/grok/omp tests beside it, pins #750 on the one-shot path.
Round-four review smaller items: api-reference now states the opposite-of-apiKey behaviour for an omitted defaultContextLength, and the wiki sentence follows the code, modelContextLengths[id] ?? defaultContextLength: any stored figure beats the default.
Round-four review smaller item: the discovery comment claimed a shared ceiling while schemas.ts restated the literal twice; the constant now lives in schemas.ts (routes already import from it, no cycle) and both bounds reference it.
Round-four review item 4: focusing the search input on every picker open raises the OS keyboard over the list on phones; guard it the way readmymind-ui.js does.
Round-four review item 3: the swap route wrote the new config.toml into the very dir a live codex session uses as CODEX_HOME before checking the pattern, and its refusal then deleted that dir. buildCustomModelInjection is pure, so the check runs on its result and a refused id never touches the filesystem. Pinned by a two-apply codex route test.
- share one context-length resolution (discovered figure, endpoint default fallback) across the routes and boot recovery, with a recovery test
- record listed per-slot context figures with a slot count of 1 and force the slot-count fallback once per rediscovery
- open up the codex model launch token for qwen3-style ids (model-plain-colon), pinned by a spawn-golden case
- pass the full discovered window to opencode as limit.context
- translate the picker search strings and document the discovery precedence
- opencode: write limit.context/output from the discovered context length (#749)
- codex: override the native launch model when a custom endpoint is selected (#750), and set model_context_window
- model picker: add a search/filter box with a no-matches line
Consolidate this release's notes into one changeset (Thanks, the tab
strip, the fixes, the fixes applied while landing) and drop #730's own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#726 attaches the keyCode 229 recovery only when (pointer: coarse)
matches, which keeps a desktop dead key from arriving twice. Chromium
reports the PRIMARY pointer as fine once a mouse, a trackpad cover or a
stylus is attached, so on such an Android device the module was off
while the text still came from the soft keyboard, and the #441 dropped
last character and the #541 autocorrect duplication came back.
The gate is now a coarse pointer OR an Android user agent. Android ran
the recovery unconditionally before #726, so this only keeps that; a
desktop (fine pointer, not Android) and a touchscreen laptop stay off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
setRemoteWorkingDir() records the path for authority only, and today
nothing else reads it for a remote session (loadFixPlanFromDisk's only
callers are setWorkingDir and the local watcher). The watcher now
remembers the remote mode and refuses both the local read and the local
watch for it, so a future caller cannot import a same-named local twin.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ctrl+V's hand-built bracketed paste (#726) and the phone composer's
dropped CSI 200~/201~ markers from the text in ONE pass, so a clipboard
carrying ESC[20 ESC[201~ 1~ came out of it with an ESC[201~ that ended
the frame early: everything after it was typed as keys and each CR ran.
Both now strip until nothing matches. The composer's copy predates this
release; it is the same one-liner.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#722 stopped handing a remote session's workingDir to the Ralph tracker,
which also left isFileAuthoritative false for remote sessions only. That
flag is what keeps the output-based completion guessers off, and it is
true for every local session with a working directory, so a remote loop
could end, and mark every todo done, on a prose line such as "All tasks
completed" while a local one cannot.
setRemoteWorkingDir() records the path without reading or watching the
local disk, so the fix plan stays authoritative as for a local session;
the file still reaches the tracker only through fix-plan/read, over ssh.
The test pins both, and fails on the previous head.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the L-shaped strip to the Tab layouts section of
docs/architecture-invariants.md, the mechanism file src/web/CLAUDE.md
links to.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Set --rv-content-max: none on the File Viewer's rendered document, so
ASCII-diagram blocks (capped by that variable with a 720px fallback the
Response Viewer sets) follow the window like the rest of the document,
and pin it with a third assertion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Export isPathWithinRoot from file-routes.ts and use it for the remote
@fix_plan.md confinement, so the two checks cannot drift; rewrap the
readRemoteFixPlan JSDoc and say NOT_FOUND; list fix-plan/read and the two
write refusals in docs/remote-sessions.md and architecture-invariants.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
toggleSessionImageWatcher checks the response, so any refusal puts the
switch back and toasts an error instead of a success; architecture-
invariants says the image watcher never watches a remote workingDir.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Note in docs/remote-sessions.md that the @fix_plan.md auto-load does not
run for remote sessions, and rewrap the test's header comment.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the @fileoverview the repo carries on every module: why the parser
exists, why it is POST + /api/ only, and that it owns the root '*'
content-type slot.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hand the bracketed frame to the target terminal with input() so onData
scrolls to the bottom, clears the selection, and delivers the bytes.
The paste trap no longer writes the frame itself.
Fixes#716
Co-authored-by: DDT <1786035110@qq.com>
Path links and in-document links carry a placeholder href (#, #fragment) that the click delegate resolves itself, but a middle click fires auxclick, never click, so the browser followed the placeholder and opened the dashboard root in a new tab. A middle click on those links now does what a click does; real URLs keep the browser's own middle click.
The Approvals Inbox strings added a second `Idle: '空闲'` to the ZH_CN
table, beside the original in the status words. Same value, so nothing
changed on screen, but every build warned:
[WARNING] Duplicate key "Idle" in object literal [duplicate-object-key]
A remote-SSH session's workingDir is a path on the remote host, but the
Ralph file routes used local fs on it: fix-plan/read imported a same-named
LOCAL @fix_plan.md (or 404'd), and fix-plan/write and ralph-prompt/write
wrote their files into the local twin of the remote folder. Same root
cause as the Ralph @fix_plan.md watcher fix.
- fix-plan/read reads the file on the remote host through
src/remote-files.ts (the File Viewer's ssh path): one probe of the file
and the workspace, the File Viewer's confinement (a file resolving
outside the workspace is treated as missing), then a capped read (1 MB).
A missing remote file is the same NOT_FOUND as a missing local one; a
non-file, an oversized file or an unreachable host is a failed read,
never a local fallback.
- fix-plan/write and ralph-prompt/write refuse a remote session
(INVALID_INPUT): remote writes are out of scope by design, as for the
File Viewer's remote edit. The Ralph panel already shows the error.
A remote-SSH session's workingDir is a path on the remote host, and the
image watcher watched it on the local disk: a folder that is not there,
or a same-named local folder whose images then popped up as the remote
session's. Same root cause as the Ralph @fix_plan.md watcher fix.
Three places start a watch, and all three now skip a remote session:
setupSessionListeners(), the app-wide toggle in PUT /api/settings (which
re-watches every enabled session), and POST /api/sessions/:id/image-watcher,
which refuses to turn it on (INVALID_INPUT, like the Git fetch settings
route) and still lets it be turned off. The Session Options row is hidden
for a remote session, the way the Git tab is, since the client's
_apiPost() does not throw on a refused request.
KeyCode 229 recovery forwarded a composed character that xterm had
already delivered, so a desktop dead-key backtick arrived twice.
create() now attaches only when the primary pointer is coarse.
Ctrl+V text paste went through terminal.paste(), which drops the
CSI 200~/201~ markers after a replay clears xterm's DECSET 2004
mirror. Plain text is now a hand-built bracketed frame on the
session input path.
Fixes#716
Co-authored-by: DDT <1786035110@qq.com>
CODEMAN_ALLOW_UNAUTHENTICATED_NETWORK and the new
CODEMAN_ALLOW_UNAUTHENTICATED_TUNNEL (#718), with their CLI flags, join
the documented environment variables the versioning policy covers, from
1.46.0, the release that gave each its own meaning.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Handle untyped zero-byte POST streams at the shared API parser boundary.
Keep request.body undefined and preserve existing typed parsers, 404
fallbacks, authentication and webview proxy stream handling.
Reject nonempty untyped streams on the first byte, and cover parser
boundaries, raw HTTP framing and real WebServer routing with regressions.
The merged PRs (mostly #714's git fetch) added about 120 em-dashes in
comments, docs, test names and three settings strings. Each one is now a
comma, colon, semicolon or parentheses. The English settings strings in
index.html and their i18n.js keys change together, and the zh-CN value
for the fetch interval uses full-width parentheses instead of a double
dash. The one left is the regex in constants.js that matches a dash
typed as a word, which is behaviour, not punctuation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-up for the L-shaped header strip:
- _syncTabStripCorner() keeps the plain wrap when the plain strip is
already past --tab-strip-max-height, checked before .tabs-corner goes
on: the float scrolled with the tabs while the toolbar stayed put, so a
scrolled strip put tabs under #headerRight, and a re-render of a
scrolled two-rows strip sized the float from the scrolled frame. The
"- scrollTop" in contentTop is gone (always 0 now).
- A strip just under its max-height that passes it once the float is in
falls back to the plain wrap as well.
- test/tab-strip-corner.browser.test.ts (real Chromium, real header and
styles.css), listed in BROWSER_TEST_GLOBS.
- src/web/CLAUDE.md Tab layouts entry describes the L-shaped classic strip.
Replaces the six contributor changesets (#694, #707, #708, #709, #718,
#713) with one consolidated minor changeset covering all 14 PRs, with the
Thanks section first and the release-review fixes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
terminalLinkLine() cut the URL's first row at its cell to stitch the URL, so a
path in a later column of that row was never scanned. The cut-off columns now
follow the stitched rows as a segment of their own, mapped back to their cells.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The self-gate now says the skill reads saved Codex conversations offline outside a session; the staging
reference says only tagged input gets 409 during a guarded submit (the rest is held), and the API
reference notes a managed write past a full hold queue falls back to a direct write. Also: missing
reference rows, agent --help naming inspect/stage/submit, the tunnel opt-in in Remote Access, MCP wording.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
spacedFilePathOnLine() refused only a FIRST word ending in `$`, so `/mnt/c/My Docs$ ls notes.md`
and `/mnt/c/Users/me/OneDrive - Contoso/proj$ code notes.md` linked the whole line. Any earlier
word ending in `$` now refuses the candidate, and both lines link what master links.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>