Commit Graph
826 Commits
Author SHA1 Message Date
Codeman maintainer f80f107445 Merge pull request #666: feat(sessions): keep an idle session's prompt cache warm with a guarded keep-alive turn
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:31:08 +02:00
Codeman maintainer 3652670a7d Merge pull request #645: fix(terminal): isolate scroll batches and support tracked Codex scrolling
The remote-history PATH bootstrap that rode along in this PR was left out
at merge (it belongs in its own PR that routes every remote tmux call
through one wrapper), so 242bbfcd's title overstates what lands here.

Conflicts in CLAUDE.md and docs/architecture-invariants.md resolved by
keeping this PR's rewrite of the wheel/touch paragraphs and re-adding
#664's touch-forwarding sentence to both.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:29:53 +02:00
Codeman maintainer 9d30a7ff36 Merge pull request #674: fix(mobile): give a sideways drag on the terminal to the session swipe alone
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:28:49 +02:00
Codeman maintainer 04faa0d3f1 Merge pull request #664: fix(terminal): forward touch scrolling for native SGR mouse tracking
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:28:49 +02:00
Codeman maintainer b4275e690e Merge pull request #665: fix(response-viewer): open markdown links to file paths in the preview, not as a same-origin URL
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:23:17 +02:00
Codeman maintainer cef64dc052 Merge pull request #659: feat(file-viewer): resize and expand the window, back/forward between previewed files
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:23:17 +02:00
Codeman maintainer b67018b318 Merge pull request #670: fix(input): keep the line breaks of a multi-line mux prompt, pasted as one block
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:23:17 +02:00
6eaaa960ff fix(tmux): keep browser keys from switching a tab onto another session (#669)
Squash of PR #669. Browser terminals could be moved onto another session
by tmux's prefix keys: Ctrl+B then ), (, s or w switched the tab's tmux
client to a different session while the tab kept the original's name.
Codeman's tmux socket now keeps only Ctrl+B Ctrl+B (send-prefix) in its
prefix table, and codeman tui and scripts/tmux-manager.sh get F1 as their
way out instead of Ctrl+B d.

Merge-time fixes by the maintainer: on an empty prefix table the
unbind-key that fails no longer skips binding send-prefix; a key tmux lists
escaped (prefix C-\ shows as C-\\) compares equal, so the reset does not rerun on every create;
and reconcileSessions() reduces the table at boot when the socket has live
sessions, so sessions that survive an upgrade are covered too.

Co-authored-by: christianhaberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:23:17 +02:00
Codeman maintainer fde23e3a07 fix(response-viewer): keep a path link's label in the prose font, pin its edges
Merge-time fix for #665.

- A markdown link converted to a preview link became `a.rv-path`, so its
  label ("Our incident record") took the path style: monospace, 0.92em
  and `word-break: break-all`, which split prose mid-word on a phone. The
  anchor now also carries `rv-path-link`, and
  `.rv-text a.rv-path.rv-path-link` resets font and word-break, as the
  File Viewer does for its labelled document links.
- The first new test adds `/tmp/a.json?raw=true` (pins the `?query`
  strip) and `/tmp/` (pins the trailing-slash folder check, since
  findFilePathLinks finds no folder in a bare `/tmp/`), and checks the
  new class.
- The `_linkifyFilePaths` JSDoc and docs/architecture-invariants.md say
  the function also rewrites anchors whose href is a scheme-less,
  non-`//` path, on purpose without FILE_PATH_LINK_PATTERN's root and
  extension filter.
- Mobile Guide: "a web link" in the response viewer opens a tab.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:20:01 +02:00
Codeman maintainer a198b815d2 docs: update the swipe limits and note what pauses or replaces a swipe
Merge-time fix for #674: the mobile-handlers.js @fileoverview still
gave the old 300 ms and 100 px limits (now 500 ms and 50 px), and the
Mobile Guide now says a visible text selection pauses the swipe and a
terminal wider than the screen pans instead of switching.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:18:51 +02:00
Codeman maintainer 6fb9c4ed8a fix(mobile): hand a sideways-opening drag back to the scroll past the swipe's drift limit
Merge-time fix for #674: the first travel past the tap slop decided the
axis for the whole contact, so a scroll that opened on a thumb arc
(+9 px across, +5 px down, then straight down) locked as 'swipe'. Every
later touchmove returned before the scroll code and SwipeHandler gave
the swipe up at its 50 px drift limit, so the gesture did nothing. Past
SwipeHandler.maxVerticalDrift the drag is now handed to 'y' (and the
published axis with it), so it scrolls; a clean sideways swipe, a
vertical scroll and a long-press drag are unchanged.

The source pin in test/session-swipe-gesture.test.ts moves with the
code and also pins the drift value, and a new browser test drives the
real touch listeners: the thumb-arc drag ends as a scroll (it fails
without the fallback, axis stays 'swipe') and a clean sideways swipe
stays a swipe with nothing scrolled. The architecture note and
src/web/CLAUDE.md now say a swipe drag is consumed only up to that
limit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:18:51 +02:00
Codeman maintainer 73ff2339d8 docs(file-viewer): list Alt+Left/Right in the shortcut overlay and help
Merge-time fix for #659.

- Alt+Left/Right (File Viewer back/forward) is a display-only entry in
  DEFAULT_SHORTCUTS, so the Ctrl+? overlay lists it, and a row in the
  help modal's Panels group, pinned in help-modal-shortcuts.test.ts.
  zh-CN entry for the new label; the "Restore size" entry is dropped,
  since nothing shows that string any more.
- The wiki row moves from "Sessions and tabs" to "Everything else".
- The grip comment in styles.css says only phones hide the grip;
  tablets show and use it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:17:05 +02:00
Codeman maintainer d38291b143 docs: describe touch forwarding to native SGR mouse tracking
Merge-time fix for #664: CLAUDE.md and architecture-invariants still
said touch forwards only for claude/copilot and shares the wheel's
gate. Both now name the extra branch in _shouldForwardTouchToApp: a
drag also forwards as SGR wheel reports while xterm itself tracks the
mouse with SGR encoding, and DEFAULT, X10 and SGR-pixel apps fail
closed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:12:25 +02:00
Codeman maintainer 6c97d63499 docs: give the composer frame's mux-fallback rule its current reason
Merge-time fix for #670.

TmuxManager.sendInput() now keeps line feeds and strips only `\r`. The
rule that the composer's bracketed-paste frame must never take the mux
fallback still holds, because the frame maps its line breaks to `\r`:
on tmux the lines weld into one, pasted inside a second pair of markers,
and get submitted. docs/architecture-invariants.md and src/web/CLAUDE.md
now say that instead of "strips every \r and \n" and "pastes the
frame's own markers inside a second paste".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:12:03 +02:00
Codeman maintainer 0ca64f8256 fix(settings): re-evaluate the keep-warm only when its default or cap changes
Merge-time fix for #666 (the review's nit). The settings PUT called
`rescheduleAll()` whenever the body carried either keep-warm key, and the
browser sends both on every App Settings save, so every save of anything
re-read the settings and re-evaluated every session. It now compares the
merged settings with the stored ones, following the rule that a settings
action resolves from `merged`, never from the raw body.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:11:06 +02:00
Codeman maintainer 2a56b2a997 fix(hooks): keep a keep-alive turn's hooks out of the run summary
Merge-time fix for #666. `recordHookEvent()` ran for every `stop`, the run
summary files a `stop` as a warning, and the Away digest lists warnings under
Needs Attention, so each keep-alive nudge added a row there and to the
session's Summary timeline. The hook route now skips the run summary while
`keepAliveReason` is set (the keep-alive turn's `stop` and `idle_prompt`).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:10:48 +02:00
Codeman maintainer f334b59dd3 fix(sessions): log an unreadable settings.json once and retry only sessions that can nudge
Merge-time fix for #666. The strict settings reader plus the retry after a
throw is right for a read that lands mid-write, but a settings.json that
stays broken (a hand edit with a trailing comma) made every session, keep-warm
off included, re-read the file and log a line every 60 seconds until it was
fixed (11 reads and 11 log lines in ten simulated minutes for one session).

The settings read now fails inside `evaluate()`: a given failure is logged
once until a read succeeds, and the retry is armed only for a session that
could nudge (its choice not `false`, the exporter `injected`, a warm report).
Other throws keep the generic retry in `schedule()`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:10:26 +02:00
Codeman maintainer e408fa21bc fix(sessions): retry a failed keep-alive write before the expiry and close its window
Merge-time fix for #666. A nudge only goes out inside the last five minutes
before `expiresAt`, so the check armed a whole `KEEP_WARM_LEAD_MS` after a
failed write landed at or past the expiry and stopped with "too close to
expiry": the retry the status promised never happened. The window
`beginKeepAliveTurn()` opened also stayed open for its ten-minute ceiling
with no turn running.

A failed write now ends the window (`endKeepAliveTurn()` joins
`KeepWarmSessionView`; `Session` already has it) and re-arms at
`min(now + KEEP_WARM_RETRY_MS, expiresAt - KEEP_WARM_LAST_CHANCE_MS)`. The
test advances the clock and sees the second write, and a second one pins
that the retry never lands past the last-chance line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:10:11 +02:00
Codeman maintainer ac8409920b docs: say Codex approval prompts do raise the action alert
Merge-time fix for #645: architecture-invariants said Codex has no hook
alert, so tabAlerts === 'action' could not see its approval prompt. It
can: src/web/screen-blocked.ts reads Codex dialogs off the pane
(capabilities.workDetect.blockedLine) and broadcasts
hook:permission_prompt, which becomes the 'action' tab alert, and both
page-key fallbacks check it. The sentence now says the alert exists and
that the SGR wheel path deliberately does not consult it, because the
0.163.0 measurement showed wheel reports leave the approval selection
unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:04:32 +02:00
Codeman maintainer 30a60f7bb5 Merge pull request #673: fix(mobile): keep the keyboard up when an accessory key is pressed
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:02:18 +02:00
Codeman maintainer 28a7c9bdf5 Merge pull request #668: feat(limits): make the global session cap configurable with CODEMAN_MAX_SESSIONS
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 19:02:18 +02:00
JD 63cada938d fix(mobile): give a sideways drag on the terminal to the session swipe alone
The terminal's touch handler and the session swipe judged every gesture separately, so a sideways flick also ended as a tap on the session being left (a link, a CLI click, a keyboard toggle) or as a vertical scroll. The terminal now locks the dominant axis past the tap slop, hands a sideways drag it cannot pan to the swipe and publishes the axis, and the swipe stands aside for scrolls, pans, a lift the terminal consumed (its selection gesture), touch selections, a second finger and surfaces with controls of their own. A touch that starts outside the terminal resets the published axis, so swiping from the phone home screen into a session keeps working after a terminal scroll. A deliberate swipe gets 500ms instead of 300ms, and vertical drift cancels it mid-gesture instead of only at the lift.
2026-10-21 21:40:27 -04:00
JD d56b90b7c6 fix(mobile): keep the keyboard up when an accessory key is pressed
An accessory key that acts on the terminal (arrows, Tab, Esc, Ctrl, scroll, clear input) took focus on press, so every tap blurred the terminal and the click handler had to focus it again: a blur/focus pair per tap that started a keyboard dismissal and shifted the toolbar each time. Such a key now cancels the mousedown default instead, the same pattern as the Attach input, so the terminal never loses focus on the press; the click-time refocus stays as the fallback. A first tap on clear/compact only arms the confirm and is treated the same way.
2026-10-21 21:40:23 -04:00
Saqeb Akhter 242bbfcd31 fix(terminal): capture remote history and preserve isolated wheel travel (#7) 2026-10-22 02:01:17 +04:00
2fe9105bab fix(skill): sendwait joins a multi-line prompt onto one line
sendwait posted its prompt as is. With the mux now keeping line breaks, a
multi-line prompt goes in as a paste, and right after spawn_worker returns it
can land inside Claude Code's Enter-ignore window. Neither the Enter loop
here nor the server's submit check recognises a pasted block that is still on
the composer, so `Review this:\n- item 1` sat unsent while the re-wait ran
out. sendwait now trims each line, drops blank ones and joins the rest with a
space before building the body, the same result as toSingleLine, like every
other waiting sender.

The preamble stamp moves to 1.43.1 so cached preambles pick the change up;
the plugin mirror is regenerated with scripts/sync-plugin.mjs. The new test
runs the real preamble.sh with CURL stubbed and fails without the join.
docs/api-reference.md gets the submit-check sentence the README and wiki
already carry.

Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 23:31:05 +02:00
302e2660be docs: sendwait takes one line; give the submit-check reason in tui.md
verbs.md section 5.3 (both copies): sendwait's Enter loop and the server's submit
check cannot reliably recognise a multi-line paste, so join the lines or use a file
(section 5.9). docs/tui.md gives the same reason instead of the composer one.

Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 10:19:48 +02:00
c3fa6d8923 docs(limits): state when the 462 ceiling holds; skill docs follow CODEMAN_MAX_SESSIONS
The tab layout's 512 refs also count pinned sessions kept as stopped records, so
the ceiling holds at the default MAX_WEBVIEWS and with no pinned closed sessions.
SKILL.md, verbs.md (both copies) and the cron guide no longer give a fixed 50/25.

Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 10:18:23 +02:00
e58c1a2f19 fix(limits): lower the session ceiling to 462 so the layout budget holds
An owner's tab layout holds at most MAX_TAB_REFS (512) refs, counting saved web
tabs (up to MAX_WEBVIEWS, 50 by default) as well as sessions. With a ceiling of
500, session creation could still fail with HTTP 500 on the layout limit before
the capacity message. 512 - 50 = 462; a test pins the ceiling plus MAX_WEBVIEWS
inside MAX_TAB_REFS so the two limits cannot drift apart again.

Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 08:59:29 +02:00
Codeman maintainer 2b9aa055cd fix(webview): relay the request Content-Length so length-only dashboards get the body
The proxy hands undici the request body as a stream and dropped the browser's
content-length, assuming undici recomputes it. For a stream it cannot: undici
frames it as Transfer-Encoding: chunked. A dashboard that reads only
Content-Length (Python's http.server, many small Go/C servers) then saw an
empty body on every POST through a web tab. Found on a WoL dashboard whose
Shut down posted {"confirm":true} and was refused for a missing flag on every
click through Codeman, while curl straight at it worked.

buildUpstreamRequestHeaders now puts the browser's content-length back when a
body goes upstream (relayBodyLength), it is a plain number, and no
transfer-encoding contradicts it. GET/HEAD never carry it. undici 6.28 frames
the stream with that length and fails cleanly on a mismatch. Side effect:
a DELETE/OPTIONS with content-length 0 now goes upstream with neither header
nor body instead of an empty chunked body.

test/webview-proxy-body-framing.test.ts pins it end to end against a
Content-Length-only upstream; it fails on the old code with
"expected 'chunked' to be null".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 08:34:14 +02:00
157752b4f0 docs(cron): rewrap the single-line prompt paragraph
Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 08:10:00 +02:00
74dcf9a59d docs: the submit check cannot reliably recognise a multi-line paste
It does match one Claude shows inline when the first line has 24+
non-space characters; it misses a short first line and the
[Pasted text #N +k lines] placeholder. Say "cannot reliably" instead of
"cannot".

Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 08:03:55 +02:00
cf9511cb57 fix(tmux): drop leading line breaks from sendInput text
"\nfix it\r" pasted an empty first line. Leading line breaks are now
dropped like trailing ones. Document what useMux does with a line feed,
and that a pane without bracketed paste receives each pasted line break
as CR, so a multi-line write without \r runs every line but the last
there, where the old line-stripping typed the joined text and ran nothing.

Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 08:03:54 +02:00
b073035bdc fix(limits): clamp CODEMAN_MAX_SESSIONS to 500 and document it
Review follow-up. Other bounds assume a small session count: an owner's
tab layout holds at most MAX_TAB_REFS (512) refs and PUT
/api/session-order accepts at most 500 ids, so with
CODEMAN_MAX_SESSIONS=600 the 513th session creation answered HTTP 500
instead of the capacity message. The value is now clamped to a named
MAX_CONCURRENT_SESSIONS_CEILING of 500; any digit string above it
(including one past the safe-integer range) resolves to 500 instead of
falling back to 50. The resolver reads process.env directly, the unused
env parameter is gone.

Docs: a CODEMAN_MAX_SESSIONS row in the Settings Reference environment
table, the env name next to the cap in the cron guide and the
architecture invariants, and both copies of the skill's endpoints
reference now give the per-user cap as half the global cap (25 by
default). The changeset says "1 to 500". The test drops the
`as unknown as string` casts and adds '1000', '501' and an
out-of-range value, each refusing at 500.

Co-Authored-By: Christian Haberl <116439789+christianhaberl@users.noreply.github.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 08:01:24 +02:00
Claudia[bot]andClaude Opus 5.5 fe10cad83f docs: finish dropping the stripped-newline rule from the input docs
The first commit left the old rule standing in places: the gotchas list in
extending-codeman.md still said newlines were stripped and that
"echo A\necho B\r" ran `echo Aecho B`, and so did both READMEs and the
skill's big-input section. Those now describe the paste.

Newlines are only kept on the mux path, so the docs that describe the paste
say "with useMux": without it a multi-line body is not a plain prompt and is
written straight into the pane.

Cron keeps rejecting multi-line prompts, but its docs and the code comments
in cron-service.ts, schemas.ts and respawn-controller.ts gave a reason this
change removes (writeViaMux joining lines, a newline submitting in Ink). The
reason that remains is the submit check, which cannot recognise a
multi-line paste in the composer, and for cron's paste mode the newlines
reaching the CLI as keys.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 04:11:28 +02:00
Claudia[bot]andClaude Opus 5.5 e3de354461 fix(input): keep the line breaks of a multi-line mux prompt, pasted as one block
TmuxManager.sendInput() removed every `\n` before the text reached tmux, so a
multi-line prompt sent with `useMux` (or a multi-line respawn prompt) arrived as
one line with its lines run together: `"echo A\necho B\r"` ran `echo Aecho B`.

The text half of a submit has gone in as one bracketed paste
(buildPasteTextCommands) since the Codex paste-burst fix, and inside the paste
markers Claude Code and Codex insert a pasted line break into the composer
instead of submitting. So the `\n` is now kept (`\r\n` loses only its `\r`) and
the existing paste carries the lines; the Enter stays a separate tmux call.
Multi-line text without an Enter is pasted too rather than typed with
`send-keys -l`, where every line break would reach the pane as a key.
Single-line input is unchanged.

The test-mode gate moves from the top of sendInput() into inputRunner(), as
readPaneRows() does, so a test subclass can record the commands sendInput()
would run instead of pinning the branch shapes on the source.

SubmitVerifier still compares the composer's last glyph line with the prompt
minus its newlines, so it does not reliably recognise a multi-line paste and
may not re-press an Enter that Claude Code ignored. `agent send` and the TUI
therefore keep refusing or joining multi-line input; the docs that described
the stripping now describe the paste and that limit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 03:51:31 +02:00
Claudia[bot]andClaude Opus 5.5 04eb1ed158 feat(limits): make the global session cap configurable with CODEMAN_MAX_SESSIONS
The cap of 50 concurrent sessions was a hard-coded constant, so a machine
with the memory for more (or a small box that wants fewer) had to patch the
source. CODEMAN_MAX_SESSIONS now sets it at startup. The default stays 50,
and anything that is not a positive integer (empty, 0, negative, fractional,
1e3, out of safe-integer range) falls back to it, so a typo never locks
session creation.

Every site keeps reading MAX_CONCURRENT_SESSIONS, so the session routes,
cron launches, the scheduled-run loop and the multi-user per-user cap (half
the global cap unless CODEMAN_MAX_SESSIONS_PER_USER is set) all follow the
variable. The test goes through sessionCapacityState and
sessionCapacityMessage, the check every session-creating route uses.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 03:46:55 +02:00
Saqeb Akhter 131ee1a31e test(terminal): restore reversal assertion and clarify scrolling guidance (#7) 2026-10-20 12:30:52 +04:00
JD 83d80578e4 fix(sessions): read the composer from a styled capture so a prompt suggestion is not a draft
Claude Code draws its prompt suggestion in an empty composer, the first letter in the reverse-video cursor cell and the rest faint, so a plain capture read it as typed text and keep-warm never nudged those sessions. The keep-warm pane read now uses capture-pane -e and drops the suggestion before checking the composer.

Also from review: an off status carries no window, automation and an unreadable composer retry instead of stopping, a failed evaluation re-arms a retry, a trigger during an evaluation queues one follow-up that remove() cancels, and the cap's clock is seeded from lastSubmitAt for pre-upgrade state.
2026-10-19 19:58:14 -04:00
JD 5db6c633d3 fix(sessions): leave a pending idle alert to the user through a keep-alive turn
Only a human spends an idle alert, but the keep-alive turn resolved an unseen one three ways: its working transition, its stop hook, and its own idle prompt replacing the item with a pre-acknowledged one. While the turn runs, a pending idle item is now left exactly as found, the page's stop handler returns on the keep-alive reason before clearing hooks or raising Response Complete, and session:working/session:idle carry keepAlive so the stuck-detection timer neither restarts nor re-arms.

The window that marks the turn closes on its own idle prompt or any other submit instead of a fixed three minutes, which a slow turn's idle prompt (sent a minute after the turn ends) could outlast. The service keeps the default and cap in memory, read through a strict reader so a mid-write read is retried rather than kept, and the cap is clamped before the strict settings save.
2026-10-19 01:42:00 -04:00
JD 71a51df2e2 feat(sessions): keep an idle session's prompt cache warm with a guarded keep-alive turn
Claude Code lets a subscription's one-hour prompt cache expire after an hour idle, and the first turn back re-writes the whole conversation at the cache-write rate; nearly every gap over an hour goes cold, while the saving is concentrated in gaps of one to four hours. Codeman now sends one short keep-alive turn five minutes before the expiry Claude Code reports on its statusline, so the next real prompt still reads the conversation from cache, and stops two hours (configurable) after the last real prompt.

Codeman owns the idle policy for these sessions, as agreed in Discussion #554: a launch with keep-warm on also carries idleCompaction: false in its one --settings JSON, so Claude Code's own idle compaction cannot replace the conversation with a summary a minute before the nudge. It is decided once per launch (keep-warm on, the statusLine exporter injected, Claude Code 2.1.290 or newer, an unknown version fails closed like --name), recorded on the mux record, and picked up by any relaunch; a launch with keep-warm off is byte-identical. A session switched on after launch is kept warm best-effort and the readout says so.

Every guard lives in one pure rulebook: the opt-in (an agent-spawned session does not inherit the app default), a launch that reports cache state, a warm 1h cache with enough tokens at stake and no compaction this gap, a live pane, no usage-limit pause, no respawn, Ralph, task or waiting agent, idle, no open dialog, an empty composer and no recent keystroke. The nudge is a submit and moves lastSubmitAt, which the response viewer's conversation correlation needs; the cap counts from its own persisted lastRealPromptAt instead. Read My Mind drops the exact nudge text, and the turn's stop hook and idle prompt open pre-acknowledged so nothing alerts. The last cache report and the clock survive a restart, so the timer re-arms.
2026-10-18 15:19:08 -04:00
JD 6f785e116f fix(response-viewer): open markdown links to file paths in the preview, not as a same-origin URL
Codex cites files as [label](/abs/path). The chat view gave those links target=_blank, so a click opened <origin>/abs/path and landed on a Fastify 404. Path-shaped hrefs now take the linkified-path shape the file preview already opens; scheme, protocol-relative and fragment links are unchanged.
2026-10-18 14:33:26 -04:00
Saqeb Akhter dbb41c70cf chore: merge upstream master and retain tracked scrolling fixes
Resolve Copilot forwarding and registry/documentation overlaps against upstream e63bb65b. Reuse upstream always policy for measured version-independent forwarders and test slow clicks for Claude, Codex and Copilot.
2026-10-18 14:07:36 +04:00
Devvyn 2cd0d82544 fix(file-viewer): phones ignore expand and the grip, folder paging follows history, swallow Alt+arrows
Under 600px the window stays full screen whatever Expand or a drag says, and both
controls are hidden. Stepping onto a folder-grid entry goes through the grid so its
index follows. Alt+left/right is swallowed at the ends of the list too. Adds tests
for the key handler, the grip clamp and the history/grid case, zh-CN titles and wiki lines.
2026-10-18 18:03:54 +08:00
Saqeb Akhter 1b6c2664b6 fix(terminal): prepay isolated small wheel ticks without amplifying streams
Address the remaining PR #645 review: preserve shell Ctrl/sideways local scrolling, restore the paging threshold export, document tile leading-report lifetime, and update internal and user scrolling documentation.

Refs: https://github.com/johoja12/Codeman/issues/7
2026-10-18 13:59:28 +04:00
Codeman maintainer f744c503c5 Merge branch 'relnext/security-notices': security notices, starting with the OpenCode Console breach
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 10:03:02 +02:00
Codeman maintainer 5e405bbbb9 fix(ui): shorten the OpenCode notice to what OpenCode said, live from 17 October
The message ran 66 words over five sentences, which pushed the update
toast's buttons off a 360x640 phone. It also repeated the card's own
eyebrow ("Security notice for OpenCode users:"), placed the breached
"legacy system" inside the Console (no source says so), and closed with
an unsourced line about the CLI not being affected. The new text (55
words) says what OpenCode said, including its own reassurance that a
user who got no email was not affected, which matters because the card
goes to every opencode user while about 1.4% of Console users were hit.
The zh-CN text follows it and uses 撤销 for revoking keys.

published moves to 2026-10-17, so the notice is already live in every
timezone when the release lands: a browser still on the 17th would
otherwise take the plain update toast and get the notice later as a
separate card. docs/releasing.md says both things for the next notice.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:30:13 +02:00
Saqeb Akhter 8cb3441dd9 fix(terminal): address scrolling review and preserve upstream speed policies
Fix transport-timer regression coverage, zero-delta tile handling and capability documentation. Record isolated Codex 0.163.0 transcript and approval evidence; defer event/batch rate and coarse paging policy changes.

Refs: https://github.com/johoja12/Codeman/issues/7
2026-10-18 11:23:05 +04:00
Codeman maintainer 54d0699abd docs: how security notices work, and how to add and retire one
src/web/CLAUDE.md gets the load-bearing rules (hand-maintained file,
strictly-true availability, one surface per notice per load, seen only
on a user action, no CLI-id branching, theme tokens only), and
docs/releasing.md a section on adding a notice, its fields, and letting
`expires` retire it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 08:59:39 +02:00
Codeman maintainer 8e6abf4bfd Merge pull request #592: feat(cli-registry): GitHub Copilot CLI as a run mode
GitHub Copilot CLI (`copilot`) becomes a run mode: Run menu, welcome
screen, cron and CLI management once it is installed, tmux-backed like
the other agent CLIs, working/idle and the model read off its footer,
launch options through `copilotConfig` (model, resume, continue, the
multi-user-clamped allowAll), Custom Model Endpoints via Copilot's BYOK
variables, MCP sync of its mcp-config.json, a status probe, and the
`codeman agent` verbs (spawn waits for its composer, read returns its
last answer).

The plan-usage quota row that earlier rounds carried was split out on
review and is not part of this merge.

Merge-time commits on top: the wider COPILOT_* clamp and the zh-CN
README rows (maintainer), the Docker sign-in docs, divider rows inside
an answer kept by `agent read`, route tests for the screen-read
last-response branch, and doc drift (Past Sessions, wheelForward JSDoc,
COPILOT_/OMP_ in the env prefix lists).

Verified before merge on Copilot CLI 1.0.98: injected keystrokes,
bracketed paste and Enter reach the TUI in tmux (github/copilot-cli#4180
does not reproduce), a shell tool call completes inside tmux (#4223 does
not reproduce), and a session driven through this branch answered over
send-and-wait.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 08:17:06 +02:00
Codeman maintainer d55267a07c Merge pull request #648: fix(antigravity): show the working indicator while an agy turn runs
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 08:16:43 +02:00