Commit Graph
3245 Commits
Author SHA1 Message Date
Codeman maintainer 6744bfcf86 fix(story-mode): the magnifier no longer hides the terminal lines it is held over
On a narrow panel (a phone, a two-column page) Claude holds the lens over
the investigate terminal, and its rim covered the end of the second line
and the ones below it. Those lines now end with an ellipsis short of the
lens's reach (over every frame of its sway); the lines above and below
it keep the terminal's full width, and on a wide panel, where the lens
hangs beside the terminal, nothing changes. A narrower terminal was the
other option and cut every line to about 14 characters on a phone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 05:34:49 +02:00
Codeman maintainer 24abd5a8cb fix(story-mode): a speech balloon never covers the art or Claude's face
A balloon that found no room beside a long caption dropped to just below
it, inside the art band: on the fix loop it covered the code page and the
"19 tests" label of the board, and elsewhere it sat on Claude's face (a
balloon of three lines or fewer was exempt from the clamp). A sweep over
the 11 corpus sessions, every turn, both modes, at 390, 820, 1100 and
1440 px and beside the diff drawer found 131 of 690 balloons covering a
click region or Claude's face.

Every balloon (Claude's, the loop's aimed one, the ask panel's, yours and
a notice) is now placed by _storyFitBalloon from the scene's layout at
its finished frame (StoryArt.layout, a dry run on a scratch canvas), so
an entrance with objects still in flight never moves it or the panel's
height. It must end above every click region under it (its tail above
those under the tail) and above Claude's face; a click region holding
his face is Claude himself and only the face rule applies to it. When
two lines do not fit, the panel grows for caption and balloon together
and the scene stands lower. The growth is computed at the panel's usual
height (storyBalloonRoom, pure), so a refit of the grown panel asks for
the same height: one extra pass, never an oscillation. The rest of a
long text clamps as before.

agent() now names Claude by his default colour, not by being cyan, so
the cyan fourth helper no longer takes the balloon, and the check scene
reports how high Claude's jump lifts his face.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 05:34:28 +02:00
Codeman maintainer ed6c89ff98 fix(story-mode): a failed check that Claude fixes in its next command says so
Flagged by four readers across rounds 10 to 12: after a push, "but a
check after that fails" never said that Claude repaired what the check
found (the new remote pointed at a branch with no commits) and checked
again. When Claude's next command runs that same check again after a
change (`git -C remote.git symbolic-ref HEAD refs/heads/main && git -C
remote.git log …`) and passes, the caption adds "; Claude fixes it, and
the check passes next." A check re-run with no change before it, or one
that fails again, claims nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 18:54:14 +02:00
Codeman maintainer b0898b5441 fix(story-mode): in a turn a helper's report started, looking around is checking what came back
From review round 12: after a helper reported back, Claude's `git log`,
`git show --stat` and a diff of the README example against real output
read "Claude looks around the project". In a turn a report started, a
look that names no file now reads "Claude checks the work that came
back."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 18:20:56 +02:00
Codeman maintainer f6c540276c fix(story-mode): plans you approved, project rules, tag lookups and dry runs (review round 12)
From a reader who has never written code:
- "a save your prompt here did not ask for" on a save that was step 3 of
  the plan you approved ("Verify and commit"): a commit step in an
  approved plan asks for the save. When Claude says a project rule asks
  for its commits (read on its whole message), the line says "…; your
  project's rules do".
- "a check after that fails" read as a failed test where it was `git
  describe` finding no tags: "the version-tag lookup after that fails
  (there are no tags yet)".
- The dry run you asked for never showed: the terminal card took the
  last command's edge-case errors. A dry run in the panel is now what the
  card shows, its "a -> b" lines, under "Claude does the dry run you
  asked for: it shows what would happen, changing nothing."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 18:19:01 +02:00
Codeman maintainer bcfef8af5b fix(story-mode): a quoted report marks what it skips, a run that never loaded says so (review round 11)
From the fact-checker's last items:
- A helper's report quoted in a notice joined its first sentence to one
  from paragraphs later with nothing between: where text was left out,
  the balloon now says "…" (found in the report itself, so two
  sentences that follow each other are never marked).
- "The first run fails on purpose, as you asked" for a run that never
  loaded a test (a collection error) now reads "At first the tests don't
  even load, as you asked; the second run passes.", as a test panel
  already says it.
- A list intro without a count ("What failed and how I fixed it:") brings
  its items while they fit in 360 characters, not 260.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 18:05:48 +02:00
Codeman maintainer 1a66dbabfb fix(story-mode): git lookups right after a save read "Claude checks what it saved"
From both round-11 readers: `git --git-dir=origin.git log -1 master;
git status -sb | head -1` after a push read "Claude looks around the
project", so a reader could not tell the save was verified. A look made
only of git lookups (log, status, show, ls-remote, …, piped to head or
tail) after a save in the same turn now reads "Claude checks what it
saved."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 18:00:13 +02:00
Codeman maintainer 84c4be2d77 fix(story-mode): a long caption makes its panel taller instead of covering the art
From review round 11: a long caption ("Claude writes pyproject.toml
and changes test_csvstat.py; the tests pass, then Claude starts a git
repository and saves the work on a new branch …") covered the test
board, the POW and the code card's file name on a two-column panel.

A caption that reaches past the band above the art now makes its panel
taller by the difference (re-fitted on resize and on the Director's cut
toggle). Every scene keeps the panel's usual height as its stage and
stands at the bottom, the background filling the space above, the way
the final panel already did; Claude's balloon is placed against the
moved head. The browser test forces a long caption and checks the panel
grew and the caption ends above the art.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 17:56:55 +02:00
Codeman maintainer dc980d121c fix(story-mode): a new file counts what it ends with, a rewrite is a change, short endings are read (review round 11)
From the fact-checker:
- A script created and then edited in the same panel showed "+95 -3":
  a file created in the span counts what it ends with, never lines
  removed from its own draft (+92), on the badge, the panel and the page.
- "Claude writes 4 files" for files an earlier panel wrote and this one
  rewrote with here-documents: writing a file the turn already touched is
  changing it.
- "Claude says: Compacted": a local command's output is the CLI's own,
  a note, not Claude's words.
- "The CHANGELOG helper is still running" was dropped under "Mission
  complete!": key sentences were read only in endings over 160
  characters; a short ending is read too, and that one is a note.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 17:47:44 +02:00
Codeman maintainer d3c55e04a3 fix(story-mode): what the captions blurred for a reader who skims (review round 11)
From an engineering manager skimming titles and captions:
- "but a check after that fails" under "Mission complete!" where the
  prompt said that step may fail now adds ", as you said it might".
- Saves no prompt of the turn asked for (a project rule, or Claude's own
  idea) were indistinguishable from requested ones: the turn's first such
  save carries a small line, "a save your prompt here did not ask for".
  "save its log with tee" no longer counts as asking to save the work.
- The first save on a branch Claude created says which: "saves the work
  on a new branch (feat/csvstat)".
- "Claude changes 3 files" hid an edit to your CLAUDE.md: a panel that
  wrote some files and patched others says both ("Claude writes
  README.md and .gitignore and changes CLAUDE.md."); a file created and
  then edited in the same panel is written.
- A turn with a problem left and work still out read "Done for now";
  the catch now wins the title.
- A helper's report that is only a path reads "reports back with the
  file it wrote: README.md."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 17:44:06 +02:00
Codeman maintainer 175017f604 fix(story-mode): the badge counts the card it sits on, opinions mid-step, a deviation is a note (review round 10)
From the fact-checker:
- "+37" sat on mathx.py's card, which has 11 of those lines; with
  several files the badge now counts the card in front (the Director's
  cut keeps every file's count).
- A second opinion asked in the middle of a step's calls read "after
  asking"; it now reads "along the way, asks a stronger AI model…".
- "Two places where I didn't follow your wording exactly" under
  "Mission complete!": not following your words is a note ("Done, with a
  note"), and the sentence counts as a word on what you asked.
- A test run that patched a file written a panel before said "Claude
  writes" it: whole files are written, patched ones changed ("Claude
  writes pyproject.toml and changes test_csvstat.py; …").

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 17:22:11 +02:00
Codeman maintainer 713978eb81 fix(story-mode): "the tests pass, then Claude starts a git repository and saves the work"
One "and" fewer where a test run's commit is the first save of a new
repository.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 17:17:23 +02:00
Codeman maintainer 30b907860d fix(story-mode): whose idea a failure was, new repositories everywhere, honest counts (review round 10)
From the person who asked and a fact-checker, reading fresh pages:
- "as planned" for failing first runs the prompt asked for ("it should
  fail because mode is missing", "run them to watch them fail"): those
  read "The first run fails on purpose, as you asked".
- A repository Claude started was told only on a save panel; the first
  save inside a loop or a test run says it too ("Claude starts a git
  repository and saves the work in 4 commits along the way.").
- `git push && git describe --tags; echo "exit=$?"` exits 0, so a
  failure after the push went unsaid; what it printed after the push
  (`fatal:`, `exit=128`) now counts. The commit subject stays on that
  caption too.
- Tool-call counts no longer include second opinions.
- "a layout check" is "a formatting check"; "Turn over" (a game word)
  is "Not done".
- "the last check finds nothing" told nothing: it now says what came
  back empty ("the last one finds a git setting that is not set, which is
  no error").

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 17:16:03 +02:00
Codeman maintainer 05dc6fbd95 fix(story-mode): the final panel grows to its words, never clipping a chip or a long ending
From review round 10: the chip "1 commit, copied to remote.git" was cut
off at the final panel's edge (on four of the eleven sessions), and so
would any ending longer than the panel's fixed 270 px. The final panel's
words now sit in flow, so its row grows (and a phone's 430 px is a
minimum). Its scene keeps the usual size, the panel's minimum height as
its stage, standing at the bottom with the background filling the rest;
otherwise a taller panel scaled Claude up with it. On a phone the words
end above Claude.

The browser test fills the final balloon with a long ending and checks
every chip, the balloon and the title lie inside the panel, at desktop
and phone width; it fails on the old layout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 17:10:35 +02:00
Codeman maintainer f46369a5af fix(story-mode): last words in context, the check after a push, a fresh copy (review round 10)
From the person who asked for the work, reading fresh pages:
- "The result was 4 passed, 1 failed" under "Mission complete!" read as
  a failing end. A test count is no failed step, and Claude's second
  sentence is kept when it is the outcome ("All 5 tests now pass, and the
  change is committed.").
- "Two places where I didn't follow your wording:" showed one. A list
  intro that announces how many brings that many lines.
- "…would fix it for up to 10 files. Want me to add that?" never said
  what "it" was. An offer that points back brings the start of its
  paragraph ("Suffix swap: the two files with the same time would trade
  their _1 suffix. …").
- "Decisions you may want to change" is something for you, like an offer.
- A second opinion whose call failed read as given; it now reads "after
  trying to ask … (no answer came)".
- "but a step after that fails" after a push sounded as if the push
  broke: when everything after it only looks (git log, status), it is "a
  check after that fails".
- Tests run in a fresh clone read "The tests pass in a fresh copy made
  from remote.git."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:59:29 +02:00
Codeman maintainer 2859b3a207 fix(story-mode): two open endings the last words missed
From a recall sample of clean finishes: "the box hasn't answered yet" is
something not done, and "One thing worth flagging: …" is a heads-up.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:52:37 +02:00
Codeman maintainer 9ffe57709e fix(story-mode): "Done, with a note" not for how things were before, nor "still open" as a verb
A sample of the 308 real pages titled "Done, with a note" read as open
work in about nine of ten. The rest were history ("Before, that early
idle could end a wait…", "used to") or "still open" as a verb ("JSON
files still open the live log viewer, as intended"). Neither counts as
something not done any more, and a history sentence is no open problem
either.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:50:55 +02:00
Codeman maintainer 1dd167ebe0 fix(story-mode): a bare repository with flags first is no new project repository, and an error is no empty answer
`git init -q --bare ../origin.git` (flags before --bare) counted as Claude
starting the project's repository. And a last step that printed a usage
message or an error (`error: unknown option`, `grep: x: No such file`)
read as "the last check finds nothing"; it now fails, as it did.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:48:38 +02:00
Codeman maintainer 2ec74273f0 fix(story-mode): a helper reporting back is heard in its own words
From review round 9: a background job's page showed only Claude Code's
line 'Agent "Helper B: write extra pytest tests" finished', so what the
helper said about its own work vanished, here that it had never run its
tests against the real wordcount.py.

The notice balloon now carries the helper's report like Claude's last
words (its first sentence and the key sentences from the rest):
'"Helper B: write extra pytest tests" reports: I wrote the file:
tests/test_extra.py It has 18 test cases … I haven't run it against the
real wordcount.py.' A report that is only a path is its file name, and
absolute paths keep their last two parts, so a long path does not push
the sentence that matters out of a phone's balloon.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:47:23 +02:00
Codeman maintainer 226a7bbbd8 fix(story-mode): "Done, with a catch" only for a problem that is still open
A sweep of 1,314 real transcripts (3,863 pages) titled 330 of them
"Done, with a catch"; a sample showed about half were history or
negations: "I found and fixed a model bug", "Bug fixed: …", "found no
broken links", "Not a problem", "the caveat is gone", "was never
broken", plus names ("bug-fixing", "cron-broken-network",
"#limitations", "the memory warning").

A problem sentence now counts only while it is open: not described as
fixed, gone or the past cause (unless it says "not fixed"), not a
negation, and a bare "warning" no longer counts. "Left out" and "left
open" are open work (a note), unless Claude chose it ("left out on
purpose", "rather than guessed"). 244 pages keep the catch; samples
read as real open problems in about four of five.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:30:34 +02:00
Codeman maintainer 277cc88148 fix(story-mode): a second opinion in front of helpers neither splits them nor counts as one
Since second opinions ride on the next panel, an advisor call sorted to
the front of a helper panel tripped the old rule that kept advisor
panels apart, so "advisor, helper A, helper B" drew two helper panels,
and the first counted the advisor as a helper ("Claude calls in 2
helpers" for one helper). The rule has no job left and is gone; a
riding second opinion is never counted as a helper. One recorded page
changes: "Claude sends 1 helper off to work in the background."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:23:11 +02:00
Codeman maintainer 6a6c7c0949 fix(story-mode): a command whose last check finds nothing answered, it did not fail
From review round 9: "Claude tries a command, and it fails" made up a
problem. The command printed what Claude was after, then exited 1 only
because its last step (`git config user.name`) found nothing set.

A command whose LAST step is a lookup that answers "no" with exit code
1 (grep, `git config`, `test`, `which`), after printing something,
now reads "Claude checks a few things; the last check finds nothing.",
and does not make the turn "Nothing Claude tried worked". A real
failure (another exit code, nothing printed, or the lookup not last)
still fails.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:19:07 +02:00
Codeman maintainer 79b37122df fix(story-mode): a stop names the step Claude was on and what its to-do list still had open
From review round 9: "You stop Claude here, during its step 3." said
where Claude was, not what that meant. The stop now carries the step's
own words, "during its step 3 (new tests under test/)", and when Claude
kept a to-do list, what was still open on it: "Not done yet: Write the
new tests; Update the README and 1 more."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:15:16 +02:00
Codeman maintainer 70b1ebcc19 fix(story-mode): name the files, say when a repository is new, and when a push stayed on this computer
From review round 9 (a newcomer to the project):
- One or two files are named, not counted: "Claude writes .gitignore and
  saves the work", "Claude changes rename_by_date.sh.", "Claude writes
  the new files mathx.py and test_mathx.py." Three or more are counted.
- The first save in a folder Claude turned into a repository says so:
  "Claude starts a git repository and saves the work: …". A `git init
  --bare` (the push target) does not count, nor a folder that already
  had commits.
- A push to a repository in a folder on this computer (`To ./origin.git`)
  is a copy, not an upload: "then copies it to origin.git, a folder on
  this computer", and the final chip reads "copied to origin.git".
- A tool lookup for plan mode reads "Claude gets ready to plan."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 16:11:13 +02:00
Codeman maintainer a80638308b fix(story-mode): a second opinion is a line in the next panel, not a panel of its own
From review round 9: "Claude asks a stronger AI model for a second
opinion" stood as a whole panel on almost every page, and the reader
never learns what it said (the answer is encrypted). An advisor call now
rides on the panel of the step after it (or the last one, when nothing
follows), counted in `secondOpinion`: a small line under the caption,
"after asking a stronger AI model for a second opinion" ("then asks…"
when it came last), and "· after 1 second opinion" in the Director's
cut. Pages lose a panel of noise and keep room for the work.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:49:45 +02:00
Codeman maintainer 555efef53d fix(story-mode): name the check that failed, say whose plan a failure was, and when background work finished
From review round 9:
- "another check" was too vague to act on. A check other than the tests
  is named by its tool: a layout check (a formatter), a style check (a
  linter), a type check, the build. "Fix and test, 2 rounds: a test fails
  and Claude fixes it, then a layout check fails and Claude fixes that;
  everything passes."
- A failure the prompt asked for reads "The first run fails on purpose,
  as you asked; the second passes." ("The tests don't even load, as you
  asked."); one Claude planned itself keeps "Test first: … as planned".
- A test run sent to the background that reported in a later turn reads
  "Claude starts the tests in the background; later they pass.", not as
  if they passed in that turn.
- The test board says "1 test" and, when nothing loaded, "1 error".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:45:17 +02:00
Codeman maintainer 59d70caeb3 fix(story-mode): Claude's last words keep the sentences aimed at you (review round 9)
Two fresh cold readers (the person who asked for the work, a newcomer to
the project) found the round-8 balloons still cut exactly where Claude
turns from describing to asking, offering or warning: "Want me to add
that?", "I can fix the number format whenever you want", the
http.server instruction, the fix that followed a reported bug.

Key sentences are now picked by kind, one of each, at most three, and
shown in the order Claude wrote them: a problem left (with the fix right
after it, when there is one, so it never reads as open), a question or
offer, how to use what was built, something not done or checked yet, a
step that failed, a word on what you asked for, a corrected warning. A
list intro is judged on its own words and brings its first items; a
pointer ("described below") is skipped; a short offer brings what
"that" was.

The final panel reads "Done, with a catch" for a problem left, "Done,
with a note" for something pending, and "Done, with a question" when
the next move is yours (`openNote` is now 'catch' | 'note'; `asks`).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:41:57 +02:00
Codeman maintainer 9c81e4c425 docs(story-mode): what may be drawn on a canvas, since Save image shares it
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:32:49 +02:00
Codeman maintainer e892278abc feat(story-mode): a run panel shows what its command printed
From review round 8: you asked to see a dry run, Claude's balloon said
"Here's the dry run you asked for", and the page showed nothing of it.
A run panel's terminal card now prints, dimmer under the commands, the
first lines its last command printed (the last ones when it failed:
that is where an error is).

The card is drawn on the canvas, so it goes into a saved image someone
may share: a line that looks like a secret (token, password, api key,
credential, inside identifiers too) is left out, addresses and long
token-like strings are masked, and Claude Code's own markers ("(Bash
completed with no output)", tool-error tags) are dropped.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:32:36 +02:00
Codeman maintainer b19317175e fix(story-mode): a stop says where it landed and what was saved before it
From review round 8: "STOPPED" with the balloon "Step 3: new tests under
test/." read like progress, and nothing said what the stop left. The
final panel now names the step Claude last announced and the commits made
before the stop: "You stop Claude here, during its step 3. Saved before
the stop: 2 commits."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:27:30 +02:00
Codeman maintainer 88040c997d fix(story-mode): no celebration when the turn is not a clean finish
From review round 8: "Mission complete!" with confetti and cheering
helpers sat over balloons saying the page will not work as opened, a
helper's tests have not run, or a problem is left. The final panel is now
calm (no confetti, a neutral robot) whenever work was still out at the
turn's end, nothing worked, or Claude's last words name an open problem
(`page.openNote`: a key point about something wrong, not done, not
checked or not fixed); the last of these reads "Done, with a catch".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:23:19 +02:00
Codeman maintainer faca7571e2 docs(story-mode): keyPoints and finishedLater
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:18:07 +02:00
Codeman maintainer 6a7d8393dc fix(story-mode): what the cold readers believed that was not so (review round 8)
Two agents read only the comic of the eleven recorded sessions (one who
has never written code, one engineering manager skimming), wrote down
what they believed, then compared with the transcripts. Both were misled
in the same places, and the cause was the same: the final panel kept
Claude's first sentence or two, and what a reader must not lose sat
further into its last message.

- Claude's last words now keep key sentences from anywhere in its final
  message (read in full, past the label's clip): an open problem or a
  quirk, something not yet done, checked or confirmed, work still out,
  what you asked for or expected, a correction of an earlier warning
  (with the sentence it refers to). A bare "I didn't" counts only when
  nothing stronger is there; table rows, list intros and questions never.
  "I built the pomodoro timer. Opening the page: it won't work if you
  double-click index.html…"; "…That note makes the current behaviour
  clear, but it doesn't fix it."; "As you expected, git describe --tags
  then failed because the repo has no tags."
- A turn that ended with helpers or a background command still out says
  so: "Done for now", and "Claude's part is done in 36 seconds. Its 2
  helpers finished later and reported back." (`finishedLater`).
- A failure you asked for, or that Claude said it expected, reads as the
  plan: "Test first: the first run fails as planned, the second
  passes.", "The tests don't even load, as planned." A loop that failed
  once on a test and once on another check says both, and the commits
  made inside a loop are part of its story; the final panel counts the
  turn's commits ("5 commits, uploaded").
- One or two files read are named ("Claude checks README.md." in a
  turn a report started); a tool lookup reads "Claude gets the tools it
  needs ready." again (it was overwritten) without its query; the
  advisor is "a stronger AI model", and one that answered with an error
  "gets no answer"; a commit message loses its `feat:` prefix in the
  plain caption.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 15:17:54 +02:00
Codeman maintainer 8daa158e21 docs(story-mode): the background event field
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:52:31 +02:00
Codeman maintainer 61e1ad6454 test(story-mode): two more real sessions in the corpus; background runs and script writes told right
Round 6's two sessions join the corpus (sanitized like the others, and
checked to draw the same pages as the originals): tests that do not load,
a fix-fail-fix-pass loop, a commit then a push in its own command, a push
with a failing step after it, an append; two helpers and a command in the
background whose reports come back as turns of their own.

Replaying them showed two captions to fix:
- A test command that ran in the background and reported back read "The
  tests pass.", as if they ran during that turn: "The tests run in the
  background and pass." (events keep `background`).
- A python script that rewrote README.md drew as "Claude works in the
  terminal." beside a separate change panel. A plain command that writes
  project files (a script fed by a here-document, or one Claude Code says
  changed files) is an edit: "Claude changes 3 files."

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:52:20 +02:00
Codeman maintainer a6a28d66a6 docs(story-mode): the changeset no longer promises an exact diff for every write
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:46:57 +02:00
Codeman maintainer d2d58a5239 docs(story-mode): the Bash share measured on every local transcript
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:45:59 +02:00
Codeman maintainer 42d1c75a19 fix(story-mode): the rest of the PR review: lookups, polling, frame budget, linear links
From review round 7 (PR review):

- With no hook path (normal after a server restart), the transcript was
  looked up by conversation id only; it now also tries the Codeman id and
  a recovered session's `restored-<fragment>` transcript, as
  last-response does, and keeps what it found briefly (a lookup reads
  every project folder; a miss is kept only 4 s).
- A session Story Mode cannot draw is not polled, and a page with nothing
  drawn yet is polled like a finished one (every 15 s), not every 4 s.
- Helper steps: one request per helper is drawn, the newest; a failed
  refetch never writes over steps already shown.
- The Director's cut toggle, a skin change and the fonts arriving redraw
  within the frame budget, not every panel in one task.
- A bare name under an `ls` header finds its folder in one pass over the
  lines; a search per link over the text before it was quadratic (about
  1.5 s for 700 links on agent output).
- A page of many questions still keeps to 12 panels: questions fold last.
- Opening Story Mode while it is open never starts a second runtime; the
  status announcer carries data-i18n-skip; the turn key in the ETag is
  clipped.
- The crafted-input timing test runs at sizes where the old code took 6
  to 29 s and the new one under 10 ms, with a 1.5 s bound.
- Docs: `older`, `origin` (`scheduled`), which route answers a 500;
  mobile.css's stale comment; an orphaned doc comment.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:44:37 +02:00
Codeman maintainer e7ce3b8e56 fix(story-mode): live helper steps behind an unchanged page, a clean reopen, no wedged view
From review round 7 (PR review):

- A helper's drawer froze while the helper worked: a background helper
  writes only to its own transcript, so the parent page answered 304 and
  the refresh returned before anything refreshed the drawer. An unchanged
  page now still refreshes an open drawer's working helpers (ETag'd).
- A helper messaged twice read as superseded ("The trail stops here…"):
  its one-page run took its ending from the first turn. It takes the last.
- More than 60 turns in a small file listed the newest 60 with no hint;
  `older` is now set whenever the list leaves turns out.
- One /story request that never settled wedged the view, even across a
  reopen. Requests carry a token and a 30 s timeout, and opening resets
  the request state, with what was announced and shown.
- The background canvases (megabytes each at 2x) are released when Story
  Mode closes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:38:13 +02:00
Codeman maintainer 91ee063fc2 test(story-mode): another user's session is a 404 on both Story routes
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:35:01 +02:00
Codeman maintainer 250a77d945 fix(story-mode): the reader cannot stall the server, and reads only real transcripts
From review round 7 (security):

- Eviction past the per-transcript caps dropped entries one shift() at
  a time after the whole tail was parsed: quadratic and never yielding
  (a 2 s event-loop stall on a 70 MB long turn, 51 s from 300k entries).
  It is one splice, done at every 1 MB yield, so the peak stays near the
  caps; and a window that saw a turn start which was then trimmed away no
  longer widens to a bigger tail that would be trimmed the same.
- A FIFO or a device in place of a transcript or a helper's .meta.json
  (stat said size 0, then open() waited for a writer) pinned a libuv
  worker per request; four of them hang every fs, dns and crypto call on
  the server. Files are now opened non-blocking, checked with the
  handle's own stat (a regular file only) and read through that handle.
- The cache held 6 transcripts for everyone, so a seventh open view made
  every poll a full re-read, and a 304 was decided only after reading. An
  unchanged file is now a 304 from a stat alone, and the cache holds up
  to 24 transcripts within 30 million characters.
- Story Mode is the first route to send a transcript's content to the
  browser, so the hook-reported path is used only when it really lies
  (symlinks resolved) in a Claude projects folder: the session's
  relocated CLAUDE_CONFIG_DIR (now also used for the lookup by id) or the
  server's. Anything else falls back to the lookup by conversation id.

Tests move their transcripts into the (temp) projects folder and cover a
path outside it, a symlink out of it, a FIFO transcript, a FIFO meta file
and a 100,000-entry tail.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:34:28 +02:00
Codeman maintainer 7aa7106cb4 docs(story-mode): this round's fields and the invariants behind the frontend fixes
API reference: `roundsOk` carries `null` for a run still going, a
background command's `output`, script writes in `edits`, what `helpers`
counts, and the page text budget behind `truncated`.

src/web/CLAUDE.md: panels kept by identity, the balloon text span the
clamp must target, the drawer's unchanged-refresh skip and held turn, the
drawer under the bar and the inert page behind a full-width one, and text
tokens versus accents.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:11:51 +02:00
Codeman maintainer 21de40309d fix(story-mode): no input shape blocks the server: linear tag and commit scans
Every string Story Mode matches is agent-written (and an agent can be
prompt-injected), and one regex call blocks the single-threaded server.
Timing each helper at its own input cap with crafted shapes found five
that were quadratic or worse:

- A lazy `<tag>[\s\S]*?</tag>` rescans to the end for every opener that
  never closes: system reminders, teammate messages and task-notification
  fields took 1.5 to 29 s on 0.5 to 1 MB of prompt text. They are found
  with indexOf now (withoutBlocks, blocks, blockText1).
- The commit message regex backtracked over many `git commit` tokens
  (290 ms at 4,000 characters, growing x8.7 per doubling) and ran on the
  whole command. It is a bounded line-by-line scan with the same rules.
- The "This command modified …" note was searched with a lazy match per
  repeat of the phrase (7 s on 1 MB of output). It is one anchored try
  at its last occurrence, where Claude Code appends it.
- firstSentence and planFromText now read only the start they need.

The worst shape is now under 10 ms at 1 MB. A test times five of them at
sizes where the old code took a second or more.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:11:01 +02:00
Codeman maintainer 67595ea980 perf(story-mode): a page budget that halves the longest live pages
A sweep of the Story core over every local transcript (1,311 files,
3,855 turns: no errors, never more than 12 panels, the slowest page 12
ms) found pages up to 551 KB (157 KB gzipped), refetched every few
seconds while a long turn runs. The page text budget (outputs, hunks,
helper texts; the oldest events give theirs up first) goes from 400,000
to 120,000 characters: 94% of turns never reach it, and the longest page
is now 74 KB gzipped.

An edit whose lines the budget dropped now says so ("left out to keep a
long turn fast"), instead of the wording for a file a script wrote.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 14:03:01 +02:00
Codeman maintainer 99c15777f5 test(story-mode): a too-tall balloon clamps its text, not the hidden speaker words
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 13:55:28 +02:00
Codeman maintainer b739e8e59a fix(story-mode): balloons clamp again, and the loop's stays above its board
The speaker words added for screen readers became the balloon's first
child, and the clamp took that element instead of the text: long balloons
were no longer cut to fit and ran over the art (the loop's covered the
test count). The clamp now finds the text by its class.

The loop has no Claude to keep clear of on the left, so its balloon may
run wide and is clamped down to one line rather than over the board it
points at; on a 400 px panel "All 19 tests pass…" now ends above "19
tests".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 13:55:01 +02:00
Codeman maintainer 6e45831909 fix(story-mode): read right by a screen reader, and the last of review round 6
Accessibility (review6-c):
- A panel is named "Panel 2 of 7" and its caption is read once, as its
  content (it was the name and the content both).
- Balloons say who speaks, visually hidden ("Claude says: ", "You say: ",
  "Claude asks: ", "Notice: "); Save image leaves those words out.
- The overlay is named "Story Mode: <session>", the drawer by its kind and
  title ("Diff 2 files"), the final panel's chips by what they open, and
  the wire's panel labels are headings.
- While a file preview opened from a panel is up, the overlay is not
  aria-modal (the preview sits beside it), and is again once focus returns.
- The focus ring on a click region gets a light band under its dashes; on
  the loop's magenta halftone it vanished.

From review6-b:
- "Mission complete!" no longer shows while a helper or a background
  command is still out ("To be continued…").
- A background command's drawer says "Started in the background…", then
  "Finished in the background, exit code 0…", instead of the launch note
  meant for Claude ("do not poll that file").
- `sed -n '5,25p' README.md` is a printed file, offered in the drawer.
- A report turn no longer counts the helper it answers as one it started.
- A helper's `cd /work/x && ls` keeps its folder as ".".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 13:51:11 +02:00
Codeman maintainer 89c222086a fix(story-mode): text contrast of at least 4.5:1 in both skins
From review round 6 (accessibility): in the paper skin the accents were
used as text colours, and yellow, light green and pink on white fell to
1.42 to 4.48:1 (the "running" tag, the pencils' "Claude is working…",
diff markers, ok/error tags, +N/−N counts, "You approved it", LIVE); in
the dark skin the panel's LIVE tag (white on pink, 3.09) and the note
balloon's "Notice" label (2.74) were under too.

Text now takes its own tokens (--story-go-text, -bad-text, -wait-text,
-pencil-text, the LIVE tag's pair, -note-ink): the accents themselves in
the dark skin, darker ones in the paper skin. Fills and borders keep the
accents. Every pair measured 4.87:1 or better, the tinted diff rows
included.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 13:46:21 +02:00
Codeman maintainer 3cdcfdd8be chore(story-mode): lint clean (control-character regexes, a case block)
Two control-character regexes (the NUL span markers, terminal escape
codes) get their eslint-disable directive on the line it covers, and the
montage case gets its own block for its declaration.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 13:43:20 +02:00
Codeman maintainer d4df9b18b2 fix(story-mode): a drawer stays with its turn, focus never falls to the page, live loop marks
From review round 6:

- An open drawer was not tied to its turn: when the newest turn moved on,
  a helper drawer went blank and a report drawer silently became the next
  turn's prompt. The drawer now remembers its turn; when the newest turn
  moves on, the page holds that turn (the picker lists the new one, and
  the status line says so) until the drawer closes, then follows the
  newest again. Picking a turn yourself wins.
- Previous on the second turn (or Next onto the last) disabled the
  focused button and dropped focus to the page body. Focus moves to the
  turn picker first.
- The drawer covered the right half of the bar at desktop widths; it now
  starts under the bar there too. Where it covers the whole page (a
  narrow window, a phone) the page behind it is inert, so Tab no longer
  walks the panels it hides.
- A live loop shows the runs that finished, and the one still going as an
  open circle (`roundsOk` carries `null` for it).
- The diff of a command that also printed something (`cat >> NOTES.md
  <<EOF ... cat calc_stats.py`) shows what it printed, with "Open
  calc_stats.py".
- "Red as expected: collection error." stays on its check, not the save
  after it. Parked on an older turn, a new turn is announced. A new panel
  is sized as it is inserted (no empty first frame). The turn picker is
  44 px on touch screens, and the diff drawer no longer says "Live diff"
  beside its LIVE tag.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 13:42:13 +02:00