Commit Graph
3172 Commits
Author SHA1 Message Date
Codeman maintainer d7a6644c2f fix(story-mode): one verdict per call, failed saves, and loops that end at a check
From review round 2 (a question, failing tests first, and a push):

- A run that reported failed tests is now failed on the event itself, so
  its drawer and wire tags agree with the panel (the TDD red run was a red
  panel with a green "ok" tag; `; echo "exit=$?"` had hidden the exit code).
- A save whose command failed says so ("Claude tries to send the work up,
  and the command fails."), stamps ERROR instead of SAVED, and counts the
  error in the Director's cut. A save still running stamps nothing.
- A loop ends at its last check: README, .gitignore and the like written
  after the tests passed are their own fix panel instead of disappearing
  into the loop's diff.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 10:43:04 +02:00
Codeman maintainer 848566828f fix(story-mode): read how current Claude Code builds deliver prompts and end turns
Found by replaying round-2 review transcripts while the reviews ran, then
surveyed across 150 local transcripts:

- A prompt typed while Claude works writes no user line in current builds,
  only a queued_command attachment where Claude took it in (602 of them
  locally, 485 of those background-task reports). It now joins the running
  turn; a report that lands mid-turn is a notice on the wire, not a new
  mission panel, and a background helper's answer joins back from it.
- Some sessions never write turn_duration (13 of 135 locally): the Stop
  hook's stop_hook_summary (never preventedContinuation in 815 seen) now
  ends the turn, timed by its own span. Before, such a session's turns
  never ended.
- A helper started as a teammate (teammate_spawned) is a background helper;
  its <teammate-message> reports (text or a JSON idle notification) join it
  by name, and the turn they start reads "readme-writer: README done".
- A <cross-session-message> names its sender; pasted text loses Claude
  Code's <pasted_content> wrapper (it showed in balloons and the picker).
- The mission panel, its balloon and its drawer follow who sent each
  prompt (you, a background job, another session), not who started the turn.
- A caption names a script by its first line that says something, not
  `set -e`, a bare `cd` or `S=/tmp/...`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 10:41:14 +02:00
Codeman maintainer 03cb3a5961 fix(story-mode): balloons over the speaker, honest boards, and drawers that keep up
From review round 1, checked against screenshots of the reviewers' real
transcripts at desktop and phone width:

- Claude's balloon is placed in the band above the head the scene drew, its
  tail pointing down at it, and clamped to stay inside the panel and off the
  head. Per-kind CSS offsets had covered the POW burst, the agent's head on a
  half-width fix panel and the first line of a terminal; a long prompt ran
  out of the mission panel. Save image clamps the same way.
- A board only shows real counts; a check that reported none shows one
  verdict instead of 21 invented dots, and the loop shows its last run.
- The mission panel opens the whole prompt, and on a task turn what the
  background job reported.
- A background helper says "in the background" and "still working" until it
  reports back, its drawer keeps polling while it works, and the final panel
  counts helpers still out.
- A fix made from the terminal opens what ran instead of an empty diff.
- The wire files Claude's words under the panel that draws them, and its
  last words under the final panel.
- A drawer follows its panel by the first event it showed when a refresh
  regroups panels (a check folding into a loop), not by kind.
- Click regions reused for a new page get the new label; a new turn draws
  all its panels fresh.
- Output links skip globs and paths a tool elided; prose links rooted paths
  only; paths inside the session folder read short (clicks keep the full
  path), and files Claude printed with cat open relative to that folder.
- File cards keep a name's separators (rename_by_ / date.sh), code drops
  ligatures (`!==` stays three characters), counts drop "−0", and the turn
  picker's text stops before its chevron.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 10:23:27 +02:00
Codeman maintainer 38585a806b fix(story-mode): draw what real sessions did, from review round 1
Three review agents watched real Claude Code workers build small programs
and compared every panel with the transcript. Replaying their transcripts
through the core found, and now fixes:

- A Bash call was classified from its 400-character display clip, so a
  commit or a test run late in a long one-liner vanished (a failing pytest
  run drew as "saves the work"). The intent, the printed files and whether
  a save ships are now read from the whole command.
- A test run that reports failures failed, even when `| tail` hid the exit
  code. With that, the real fix-test-fix-test sequence folds into one loop:
  "Fix and test, 2 rounds. It passes in the end."
- node:test (`# pass 7`), all-failing pytest (`3 failed in 0.1s`) and
  pytest errors are counted.
- A helper started in the background was drawn as finished, with Claude
  Code's internal launch notes as its answer. It now stays running until its
  task notification arrives; the answer, tool count and duration are joined
  back onto it, and the final panel says when helpers are still out.
- The notification turn reported Claude Code's own duration, counted from
  the first prompt (2 min 38 s for a 21 s turn); a turn is capped at its span.
- Logging into scratch (`| tee "$S/dry.txt"`, `> /tmp/x`) counted as an edit;
  redirect targets are read quote-aware, and a here-document's body is data.
- A probe (`pytest --version`) reads as looking around, not running a tool.
- A plan Claude writes as a numbered list (no plan tool, as in current
  Claude Code builds) is drawn as a plan panel; files it cats are file cards.
- A balloon: code spans stay whole, an ellipsis or e.g. does not end the
  sentence, a remark about the check that just ran stays on that check, and
  a loop shows the last word of its rounds.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 10:11:47 +02:00
Codeman maintainer 13964e35db perf(story-mode): parse transcript tails per line and yield to the event loop
The first read decoded the whole tail as one string and parsed it in one
synchronous pass. Lines are now decoded one at a time straight from the buffer
and the loop yields every 1 MB. Measured on the largest local transcripts
(110, 64, 49 MB): a cold read takes 39-50 ms instead of 100-123 ms, and the
longest event-loop stall is 8-10 ms.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:56:56 +02:00
Codeman maintainer 10f92fde8c perf(story-mode): repaint panels by need, not at display rate
Every visible panel was repainted on every animation frame: five panels cost
~81% of one core (main thread, 2x screen, measured with Chrome's own task
counters). Panels now repaint at 30 fps while their entrance plays, 15 fps
for the newest panel of a running turn, and 6 fps once settled; a settled
panel holds still after 20 s until the pointer passes over it. Clocks still
run in real time. Measured: 11.6% in the first 10 s, 2.4% once the page has
settled, 5.1% with the pointer on a panel.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:55:43 +02:00
Codeman maintainer 0c45682136 feat(story-mode): save as image, a helper's own steps, a way in on phones, and polish
- Save image: the page as one PNG to share (each panel canvas, then every
  caption, balloon and chip redrawn from its computed style and box).
- The helper drawer lists what the helper did, read live from its own
  transcript (GET .../story/helpers/:agentId), led by the task Claude gave it.
- Session Options has a Story button (same setting), the way in on phones.
- A turn a background task or another session started reads as a notice,
  not as your speech balloon.
- Wide panels keep their scene in a centered stage instead of spreading the
  art to both ends; the fix panel's agent stands next to the page.
- An unchanged page (same ETag) is neither parsed nor redrawn.
- Paths inside the session's folder are shown short; clicks keep full paths.
- Tab stays inside the overlay; a missing 2D context skips the art, not the page.
- A rebindable Story Mode shortcut (no default chord).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:51:48 +02:00
Codeman maintainer d313b868d4 test(story-mode): end to end in a real browser (browser suite)
A real server in test mode, real Chromium, a synthetic transcript handed over
through a real stop hook: off by default, the header button draws the running
turn, a grown transcript plus a hook redraws it live over SSE, the code page
opens the diff, Escape closes drawer then overlay, and a phone-width viewport
has no sideways scroll. Listed in BROWSER_TEST_GLOBS (nightly, not the gate).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:46:10 +02:00
Codeman maintainer fb71180632 feat(story-mode): a helper's own steps, from its transcript
GET /api/sessions/:id/story/helpers/:agentId draws one helper (an Agent call)
as a page from its own transcript, <conversation>/subagents/agent-<id>.jsonl
beside the session's, with the type, description and finished flag from its
.meta.json. The file is derived from the session's own transcript path and an
id checked against [A-Za-z0-9_-]{1,64}; a helper with no file yet is page
null, not an error. The reducer gains a sidechain mode (every helper line is a
sidechain line) and keeps the agentId of Agent results, so the main page links
each helper to its steps. Same gates and ETag/304 as /story, now shared.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:41:39 +02:00
Codeman maintainer fc279f998c fix(story-mode): judge each part of a Bash one-liner, and keep underscores in balloons
Found by watching real workers: `node --test` was drawn as plain terminal work,
`git -c user.name=x commit` was not seen as saving, and a probe such as
`pytest --version` became a failing test. Commands are now split into their
simple commands (quote-aware, at && || ; | and newlines); each part is judged by
what it starts with after env assignments and wrappers like timeout and sudo,
git's own -c/-C options are skipped, a --version/--help probe is not a run, and
the strongest intent wins (test, save, build, edit, run, look). File
housekeeping (mkdir, touch, cp, mv, rm) and git init/add are plain commands.

Balloons dropped every _ and * as markdown (test_wcount.py read testwcount.py);
now only paired emphasis at word boundaries and line-start markers go.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:38:24 +02:00
Codeman maintainer dfe023d49d test(story-mode): frontend overlay test in JSDOM, every scene drawn in every shape
Runs the real story-mode.js against pages the real server core builds from
invented transcripts: panels, captions, balloons, the turn picker, the
Director's cut wire, file and diff clicks with their line numbers, output
links through the terminal's own path matcher, a live refresh that keeps
existing panels' clocks, activity filtering, Escape one layer per press,
teardown, error notes and the setting switch. A permissive fake 2D context
lets every scene draw every panel kind across its whole animation, at four
sizes, in both reading levels, without throwing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:35:03 +02:00
Codeman maintainer 7c21973c54 perf(story-mode): 304 for an unchanged page, and a longer read for a turn bigger than the tail
GET /story now sends a weak ETag (server start, transcript size and mtime, turn)
with Cache-Control: no-cache, and answers 304 before building anything when the
transcript has not changed, so a live view's polls cost a stat.

A turn can be bigger than the 8 MB tail on its own (tool results carry whole
files, ~60 KB per result line on large local transcripts), which cut its first
panels. When the window holds no prompt, the reader re-reads a 24 MB, then a
64 MB tail.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:31:40 +02:00
Codeman maintainer d20208bda6 fix(story-mode): Escape closes a file preview opened from a panel first
Codeman's file preview has no Escape of its own outside the folder grid, so with
Story Mode on top it stayed open and blocked the page. While Story Mode is open,
Escape now closes one layer per press: the preview, then the drawer, then the
overlay. A folder grid and a preview in edit mode keep their own keys.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:27:23 +02:00
Codeman maintainer 2653db10b5 feat(story-mode): draw a Claude session's turns as comic pages, live
Story Mode is an opt-in header button (showStoryButton, per device, default
off, kept off phones) that opens the active Claude Code session as comic pages:
one page per prompt, panels for reading code, planning, helpers, edits, tests
(POW/KRAK), questions and saving, each with a plain story caption and a
Director's cut caption naming the tools. Files open in the existing file
preview, the code page opens the exact diff, a test board opens the output,
and a running turn redraws as Claude works.

Server: GET /api/sessions/:id/story (experimental) reads a bounded tail of the
session's own transcript. A pure core (src/story-mode.ts) reduces lines,
joins tool calls with their results, splits turns at prompts and
turn_duration, and groups events into at most 12 panels; Bash calls are
sorted by what the command does. The reader (src/story-reader.ts) caches
reduced entries and reads only appended bytes while the file grows.

Frontend: story-mode.js (canvas frame engine, live refresh from transcript and
hook SSE events plus a poll while a turn runs, details drawer, the wire) and
story-mode.css, with two self-hosted OFL comic fonts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 09:22:06 +02:00
Codeman maintainer 0ab71d61d1 docs: fix the typecheck command and two stale link labels in CLAUDE.md
The Quick Reference listed `npm run typecheck` as `tsc --noEmit` alone; the
script also type-checks the scripts via `tsc -p config/tsconfig.scripts.json`.
The circuit-breaker and ultracode pointers showed pre-rename anchor names as
their labels while the hrefs already pointed at the current headings.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 06:12:38 +02:00
Codeman maintainer de99a6d57a docs: tighten the inbox, push and idle-detection wording
Follow-up to the previous commit, after a fact check against the code.

- Answer surfaces: the header bell answers Claude prompts, the phone
  strip only Claude dialogs (and only with the inbox on), and push
  Approve/Deny only a Claude permission prompt (PUSH_EVENT_MAP gives
  actions to permission_prompt alone). README, its Chinese mirror, the
  notifications page and the phone guide now say so.
- Antigravity and Grok Build: after the 3 s launch settle, idle is armed
  only by Claude's prompt marker and working only by a braille spinner,
  so "idle when output stops changing" was wrong. The wiki, the grok
  guide and the API reference now call their status unreliable.
- DeepSeek Harness: its idle and working reports become stop and
  agent_working, which drive respawn, waits and the inbox but not the
  session's own working/idle display. Keeping Agents Running says that,
  and that the respawn path needs the status bridge.
- The wait section of the API reference no longer calls exit the only
  dependable signal for screen-checked modes; the inbox page names how
  Codex and DeepSeek items clear; Core Concepts and Hooks And
  Integrations no longer call DeepSeek "the one" exception; Agent CLIs
  notes that Codex dialogs still raise the red alert; the inbox design
  doc notes the alert-only items.
- Skill: stop and blocked list deepseek, and SKILL.md no longer says
  codex has neither a transcript nor blocked. Mirrored with
  scripts/sync-plugin.mjs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:28:03 +02:00
Codeman maintainer e17eb633c3 docs: correct which CLIs the Approvals Inbox and screen-checked idle cover
The README (and its Chinese mirror) said the Approvals Inbox queues every
pending prompt and answers it from the bell or the phone. It holds prompts
from Claude Code, Codex (screen-read) and DeepSeek Harness only, and only
Claude's are answerable: Codex and DeepSeek items are alerts that say to
answer in the terminal, with no Approve/Deny on the push or the phone strip.
The wiki, the TUI guide and the phone guide now say the same.

Keeping Agents Running, Troubleshooting and the API reference still said
every CLI but Claude, Codex and DeepSeek falls back to output
stabilization. OpenCode, Gemini CLI, Pi and OMP declare
capabilities.workDetect too and get the same screen check; only
Antigravity and Grok Build declare none. Core Concepts now mentions
Codex's screen-read dialogs, and the respawn gotcha notes that DeepSeek's
own end-of-turn report reaches the respawn controller.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:07:10 +02:00
Codeman maintainer ce809eac41 chore: version packages
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
codeman@1.42.0
2026-10-16 13:23:48 +02:00
Codeman maintainer 25bd792550 docs(changeset): add the multi-user admin-only settings fix
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 13:23:40 +02:00
Codeman maintainer 973943e942 docs(multi-user): document the settings read, system operations and own picks
- docs/api-reference.md: a non-admin's GET /api/settings omits
  voiceSettings.apiKey, caseOrder and lastUsedCase; a new "System
  operations" table for the admin-only routes and the scoped
  POST /api/auth/revoke; the error-code table now lists FORBIDDEN and the
  other multi-user codes (PASSWORD_CHANGE_REQUIRED, USER_NOT_FOUND,
  USER_EXISTS, LAST_ADMIN).
- docs/wiki/Multi-User-Mode.md: what a regular user reads, that their run
  mode and respawn presets stay theirs on the device, the slow sign-in
  case, and the admin-only system operations.
- docs/multi-user-plan.md: Settings and System ops rows marked implemented.
- CLAUDE.md: the Multi-user mode paragraph names the new pieces and tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 13:13:35 +02:00
Codeman maintainer 5a297cd3e4 fix(multi-user): read a refused settings write as admin-only in the browser
Two gaps in how a regular user's browser handled the admin-only settings
writes:

- The role comes from GET /api/me, which answers after page load, and on
  a failed request admin-ui.js falls back to a single-user admin. A save
  made then was sent, came back 403, and still said "Settings saved",
  while the refused server-wide change stayed on the device. A 403
  FORBIDDEN on a settings write now ends that save like a known
  non-admin's: synced keys back to the server's value, the one admin-only
  notice, and the page is read-only from then on (_noteSettingsWriteRefusal).
  The display-key list moved into one method (_displaySettingKeySet), so
  that split no longer depends on GET /api/settings having loaded.
- A regular user's run mode and respawn presets were skipped for the
  server but overwritten by the server's on the next page load, while
  "Saved preset" said otherwise. They are now kept as that user's own on
  the device and put back over the server's after the settings load and
  on codeman:me (_rememberOwnSetting, _applyOwnSettings).

Admins and single-user mode are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 13:12:09 +02:00
Codeman maintainer 24a1c6c427 fix(multi-user): make the server-wide system operations admin-only
docs/multi-user-plan.md lists the system operations as admin-only, but
these routes had no role check, so any signed-in regular user could run
them in multi-user mode:

- POST /api/auth/revoke with an empty body cleared EVERY login session on
  the server, every admin's included. A non-admin now revokes only their
  own logins, and a named sessionToken only when it is one of theirs.
- POST /api/system/update (update and restart the server for everyone),
  POST /api/system/span-displays (a window on the server's desktop),
  POST /api/tunnel/qr/regenerate (clears every user's pending QR login
  code) and POST /api/cleanup-state (drops every user's stale session
  records) now answer 403 FORBIDDEN to a non-admin.
- GET /api/tunnel/info lists only a non-admin's own logins (it showed the
  address and browser of every user's sessions).

Admins and single-user mode are unchanged. The tunnel panel's Regenerate
QR button no longer reports success for a refused request.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 13:11:41 +02:00
Codeman maintainer 33f0bc423f fix(multi-user): keep the admin's Deepgram key out of a non-admin's settings read
GET /api/settings returned the whole settings.json to every signed-in user.
An admin's App Settings save stores the Deepgram key there
(voiceSettings.apiKey), so any regular user could read it, and their
browser copied it into its own voice config and dictated on the admin's
account. caseOrder and lastUsedCase also named the admin's cases.

In multi-user mode a non-admin now reads the file without those three
(settingsForNonAdmin). Admins and single-user mode get the file as it
is. Pinned by route tests and the live multi-user test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 13:10:59 +02:00
Codeman maintainer 31c03ab62d docs(multi-user): server-wide settings writes are admin-only
api-reference gains a Settings section (GET/PUT /api/settings, the model
config, the case order and PUT /api/config, with the 403 FORBIDDEN a non-admin
gets in multi-user mode). The Multi-User Mode wiki page explains what a regular
user's App Settings save does now, Settings-Reference links it, the plan's
Settings row is marked implemented, and CLAUDE.md notes the gate for the
Multi-user paragraph and for anyone adding a settings write.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 12:18:20 +02:00
Codeman maintainer cb928aefe2 test(multi-user): pin admin-only settings writes, server and browser
- test/routes/system-routes-settings-admin-only.test.ts (app.inject): a
  non-admin PUT /api/settings is 403 FORBIDDEN before the body is parsed, and
  nothing is written, no watcher toggled, no tunnel started, no history limit
  set; the same gate on PUT /api/execution/model-config, PUT /api/config and
  PUT /api/cases/order; admins and single-user mode write as before; GET stays
  readable.
- test/settings-admin-only-multiuser.test.ts (live server, port 0, real
  multi-user auth): settings.json is byte-identical after a non-admin's PUTs,
  and a non-admin's quick-start or Ralph loop no longer records lastUsedCase.
- test/settings-admin-only-ui.test.ts (real index.html in JSDOM): a non-admin
  App Settings save sends no PUT, keeps per-device keys, keeps synced keys at
  the server value, and toasts once only on a real synced change; the
  background writes are skipped; admins still PUT; zh-CN for both toasts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 12:16:34 +02:00
Codeman maintainer a798c461db fix(multi-user): skip server-wide settings writes for a non-admin browser
With PUT /api/settings admin-only in multi-user mode, a non-admin's page must
not run into the 403. `_settingsReadOnly()` (settings-ui.js) reads the role
from window.__codemanUser; single-user mode and admins are unchanged.

For a non-admin, App Settings Save/Apply still saves the per-device keys to
localStorage exactly as before, but sends neither the settings PUT nor the
model-config PUT, and keeps every synced key at the server's value (the next
page load would put it back anyway). Only when the user really changed a
synced setting do they get one toast that server-wide settings can only be
changed by an admin; a form baseline taken at open keeps an untouched default
that no admin ever stored from reading as a change. The background writes
(run mode, respawn presets and their load-time migration, last used case,
case order, the tunnel toggles) are not sent, and a 403 FORBIDDEN on a tunnel
enable is no longer mistaken for the no-password prompt. zh-CN for both toasts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 12:12:50 +02:00
Codeman maintainer df0ece6fb4 fix(multi-user): make server-wide settings writes admin-only
In multi-user mode any signed-in non-admin could rewrite the server-wide
~/.codeman/settings.json through PUT /api/settings (feature switches, the
plan-usage collection switch, run mode, respawn presets, the tunnel), although
docs/multi-user-plan.md makes settings writes admin-only.

PUT /api/settings now answers 403 FORBIDDEN for a non-admin before anything is
parsed, written, toggled or started. The other request paths that write a
server-wide setting get the same gate: PUT /api/execution/model-config (the
modelConfig key), PUT /api/config (state.json app config) and
PUT /api/cases/order (the one global caseOrder list). Quick-start and
ralph-loop start no longer record a non-admin's lastUsedCase in settings.json,
where every user could read it. GET /api/settings stays readable by everyone;
single-user mode is unchanged (requireAdmin short-circuits there).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 12:06:05 +02:00
Codeman maintainer b4aed4e485 fix(release): stamp the codeman skill preamble 1.42.0
#642 stamped the preamble with the version it expected to ship in, 1.41.2. The release is 1.42.0, so the stamp would name a version that never existed. Any new value makes cached preambles from the broken version stale, which is what the stamp is for.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 11:43:47 +02:00
Codeman maintainer ab9fc1b424 docs(changeset): make it 1.42.0 (minor) and add #618
The owner chose a minor release. #618's own changeset is folded into the release changeset like the others.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 02:40:15 +02:00
Codeman maintainer 15a73dfa05 Merge pull request #618 from opticon454/feat/whats-new
feat: announce each release once with a toast generated from the changelog

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 02:39:49 +02:00
Codeman maintainer 123831660a docs(changeset): 1.41.2 release notes
One release changeset for #616, #617, #621, #622, #623, #624, #625, #628, #632, #634, #635 and #642. The changesets carried by #616, #617 and #642 are folded into it and removed (#617's was minor; 1.41.2 is a patch release).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 02:05:14 +02:00
Codeman maintainer 5483811753 Merge pull request #625 from Ark0N/feat/git-worktrees
feat(worktrees): create, open and remove git worktrees of a case

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 02:00:32 +02:00
Codeman maintainer c76600315e Merge pull request #624 from Ark0N/feat/codex-blocked-detection
feat(codex): raise codex approval, question and trust dialogs as BLOCKED

Conflict resolved against #634 in src/session.ts _probePaneWorking():
#624's assignment (a dialog on screen is never work) is kept, and #634's
trust-dialog verdict block (log the hold once, remember the reading)
follows it, before _readWatching().

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 02:00:29 +02:00
Codeman maintainer 9aa3083280 Merge pull request #634 from JDProfresh/fix/idle-not-on-trust-dialog
fix(idle): hold idle while the workspace trust dialog is on screen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:55 +02:00
Codeman maintainer eec2895dd7 Merge pull request #635 from JDProfresh/fix/trust-dialog-deferred-read
fix(trust-dialog): re-read a throttled trust-dialog scan instead of dropping it

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:55 +02:00
Codeman maintainer d080004436 Merge pull request #617 from opticon454/feat/custom-keybindings
feat(shortcuts): rebindable previous/next session, duplicate-chord refusal, rebinds stay out of the PTY

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:51 +02:00
Codeman maintainer 5eccaca3bc Merge pull request #616 from opticon454/fix/deepseek-install-path
fix(deepseek): find pnpm when installing the terminal profile, and install it with dsh

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:51 +02:00
Codeman maintainer 16bbd260e2 Merge pull request #642 from Ark0N/fix/skill-positional-args
fix(skill): keep the §0 bootstrap intact when Claude Code loads the skill with arguments

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:46 +02:00
Codeman maintainer 8084cae0fe Merge pull request #628 from Randalix/fix/codex-submit-paste
fix(tmux): submit text as a bracketed paste so Codex does not swallow Enter

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:46 +02:00
Codeman maintainer c5417abd27 Merge pull request #632 from ludovicfourrage/fix/capture-pane-sgr-reset-629
fix(tmux): reset captured SGR before live output resumes

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:46 +02:00
Codeman maintainer 6e4181a2e6 Merge pull request #622 from JDProfresh/fix/attach-video-containers
fix(uploads): refuse an unsupported video before uploading it

Conflict resolved against #621 in src/web/public/image-input.js (the
_promptAttachKind doc comment only): #621's comment is kept with #622's
clause that a video MIME counts only for the containers the server
admits; #622's video MIME check and #621's document branch both stay.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:42 +02:00
Codeman maintainer 0866090bc3 Merge pull request #621 from JDProfresh/feat/prompt-upload-documents
feat(uploads): prompt uploads take documents

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:23 +02:00
Codeman maintainer 48637e9920 Merge pull request #623 from JDProfresh/fix/prompt-cache-report-bounds
fix(telemetry): gate the prompt cache like the model report, and keep the first 20 miss causes

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:59:23 +02:00
Codeman maintainer 4b73ec8417 fix(#624): read codex's trust prompt as BLOCKED when it ends in esc back
On codex-cli 0.162.0, with 0.163.0 released, every launch first shows the
"Update available" prompt, and choosing Skip leads to a variant of the
workspace trust prompt: "2. Back to Agent Command Center" over the key-hint
row "enter continue · esc back". The pattern only accepted cancel,
interrupt, quit, answer or all as the closing word, so a fresh git repo
launched from Codeman sat on that trust prompt reading idle, with no red
alert and no blocked signal (measured live on a throwaway instance).

Adding "back" is safe because the hint row must still START with one of
the anchored hints ("enter continue" here): the popups the user opens at
the keyboard (/model, /permissions, /review, Implement this plan?) end in
"esc back" too, but their row starts with "enter select", so they stay
unmatched, as every existing negative fixture confirms. The new fixture is
the live capture with the scratch path replaced.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:42:40 +02:00
Codeman maintainer 688bdfb970 fix(#616): install pnpm only when none is on PATH
The DeepSeek install command asked npm for dsh and pnpm in one go. On a
machine that already has pnpm through corepack (`corepack enable` puts a
pnpm shim in node's own bin directory, which is npm's global bin for nvm
and Homebrew installs), `npm install -g pnpm` refuses to overwrite that
shim with EEXIST, and because both packages were in the same command the
whole install failed: dsh was not installed either. Measured with npm 10
against a scratch prefix holding a corepack-style shim. On master the same
machine installed dsh fine and the profile install used the existing pnpm.

The command is now `npm install -g @deepseek-ai/dsh && (command -v pnpm
>/dev/null || npm install -g pnpm)`, so pnpm is installed only when the
install environment has none, and a failed dsh install still fails the
command. The two hints that embed it follow (the launch-table drift test
requires that), and the catalogue is regenerated; install.sh withholds
the command for a launcher-only CLI, so its block is unchanged.

The test now runs the real stock string through /bin/sh with a fake npm
on a PATH it controls, for the three cases: no pnpm, an existing pnpm,
and a failing dsh install.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:37:41 +02:00
Codeman maintainer bea9865cff fix(#625): never remove a worktree that is, or holds, a Docker case workspace
The Docker rule was applied to the CASE folder and its common git dir
only. A Docker case can be linked to any host folder, including a managed
worktree (`<repo>/.claude/worktrees/<name>`), which is a natural setup for
running one of the parallel agents in a container. Removing that worktree
from the local case's dialog, or through Close Session's "Kill & remove
worktree", ran `git worktree remove`, which runs a git status INSIDE the
tree (container-written files, checkout filters on this machine) and then
deletes the whole tree, ignored files included, while the container still
mounts it. Reproduced on an isolated instance: DELETE answered 200 and the
Docker case's workspace was gone.

That contradicts the invariant the PR itself documents in CLAUDE.md ("git
never runs ... at or inside a Docker workspace"). removeCaseWorktree now
refuses (400) a present worktree that is, sits inside, or holds a Docker
case workspace, before any git runs; the DELETE route passes the Docker
roots it already reads for the case check. A worktree whose folder is gone
is unaffected (git only drops its record there). Unit and route tests
cover both directions and an unrelated Docker workspace; docs updated.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:36:45 +02:00
Codeman maintainer a61db218ee fix(#618): translate the release toast for zh-CN
The toast every user sees once per release had no zh-CN entries, so a
Chinese interface showed it, button included, in English. The button
gets an entry and the frame a translateDynamic pattern that keeps the
version, the "(+N more)" count and the highlights (those come from
CHANGELOG.md and stay English). Tested through the real i18n.js in JSDOM,
plus a pin on the strings settings-ui.js builds, which the pattern
depends on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:28:54 +02:00
Codeman maintainer 71439c525b fix(#618): document whats-new.json in the release procedure
docs/releasing.md step 3 lists everything `npm run version-packages`
writes, and the COM commit stages explicit paths, so the new generated
file has to be named there: committed with the release, the version
check in test/whats-new.test.ts that fails a hand bump (with the two
commands that regenerate it), and that a release without bold lead-ins
ships an empty list and no toast.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:27:54 +02:00
Codeman maintainer f2154a5d33 fix(#618): read lead-ins behind the changesets commit prefix, skip group labels
`changeset version` prefixes the first line of every committed changeset
with its commit ("- d18deed: **Lead.** text"), so a changeset that opens
with its bold lead-in, which is the shape the release notes ask for, was
never matched in a changesets-bot release. The pattern now allows that
prefix.

The release notes also put group labels in bold at the start of a line:
"**Fixes.**" and "**Fixes applied while landing.**" (1.41.1, 1.41.0,
1.35.0, 1.33.3). Those were taken as highlights, so a release with few
features announced "... · Fixes applied while landing". They are skipped
like the Thanks block. Tests cover both, and a release with no lead-ins.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:27:26 +02:00
Codeman maintainer 02ea9251f8 fix(#618): keep the release commit green when a release has no bold lead-ins
The shipped-json test asserted at least one highlight. Many releases are
written without bold lead-ins (1.32.1, 1.29.1 and 1.24.7 here, and every
changesets-bot release whose changesets are plain sentences, this PR's own
changeset included), and the generator handles that on purpose: it warns
and writes an empty list, and the client then stays quiet. Running
`npm run version-packages` in a scratch copy with only this PR's changeset
produced `{"version":"1.42.0","highlights":[]}` and turned the gate red
on exactly the release commit. The version check, which is what keeps a
hand bump from shipping the previous release's notes, stays.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 01:27:26 +02:00