cawdev-cli 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/runner/README.md CHANGED
@@ -356,18 +356,100 @@ browser anywhere and the terminal collects the session when you approve.
356
356
  error — it is what an expired session looks like, and the answer is the same as
357
357
  having none.
358
358
 
359
- ### Advanced mode: one window per session
360
-
361
- `/advanced-mode` splits the terminal the way emacs does: **one window per
362
- session** this machine is running — or ran since you attached — above **the
363
- prompt, which stays at the bottom** the way a shell's does. Each window's title says what kind of
364
- session it is (`plan`, `dev`, `review`, `ask`…), where it stands, the card and
365
- the project, and its body is that session's output as it arrives. A frame's
366
- colour is its session's state — **red while it runs, green once it finished**
367
- (a plan planned, a dev developed), amber if it stopped any other way — and
368
- the focused window is drawn in heavy lines; `tab` and `shift+tab` move the focus, `1`–`9`
369
- jump to a window, and `enter` prompts the focused session exactly as it does
370
- outside the mode. `/advanced-mode` again (or `/advanced-mode off`) leaves.
359
+ ### Advanced mode: one card per session
360
+
361
+ **Advanced mode is the default terminal (R624).** `cawdev` opens in it wherever
362
+ the terminal can draw it — a TTY, not `TERM=dumb`, at least 80×24. Below that,
363
+ or through a pipe (`--watch-only | …`), it is the scrollback, with one line
364
+ saying why. `cawdev --simple` and `/simple` are the scrollback terminal;
365
+ `/advanced-mode` is the way back; the choice is remembered per platform in
366
+ `prefs.mjs` (`mode: simple|advanced`) beside `/agent` and `/matrix`. This does
367
+ not reopen R81 — it weighs it again: with several sessions and a roadmap on one
368
+ machine, R81's reason (a full-screen repaint eats the scrollback) no longer
369
+ wins, and the scrollback is one key away. `/export` (or `/export 3`,
370
+ `/export R29`) lays a session's log into the normal screen so the terminal's own
371
+ search and copy reach it; quitting and `/simple` lay in what the focused
372
+ session said.
373
+
374
+ **The motion is a spinner and a robot, not rain.** The rain is **off by
375
+ default** (`/matrix on` brings it back exactly as it was, remembered). A
376
+ running card's status mark, and the mark on the current stage of its walk,
377
+ turn: `◴ ◵ ◶ ◷` for a stage that writes (plan, code, merge, release, roadmap,
378
+ interview), `◜ ◝ ◞ ◟` for one that only reads (test, ask, audit, scope), a
379
+ frame every two ticks of the 120 ms clock. A waiting card holds `◆`, a queued
380
+ one rests on the spinner's first frame. A status that changes is drawn
381
+ reversed for four ticks. The robots (a finished plan, a finished development
382
+ docked at `▶ review`, nothing built, a landing at `▶ main`, a merge in flight)
383
+ move whether the rain is on or off. `n`/`N` move to the next/previous card
384
+ that needs you (`n` still refuses when the focused card holds a permission
385
+ request); `/close 3`, `/close all` and `w` close ended cards. A running card is
386
+ refused with `that session is still running · x x cancels it`.
387
+
388
+ `/advanced-mode` gives **one card per session** this machine is running, or
389
+ has run since you attached. The cards sit above **the prompt, which stays at
390
+ the bottom** the way a shell's does. A session's log scrolling past in a corner was neither readable
391
+ nor meant to be read live, so a card shows what a glance needs:
392
+
393
+ ```
394
+ ┏━ 1 DEV R42 Payments refund flow ━━━━━━━━ ● running · 12m ━┓
395
+ ┃ Claude · Opus 5.5 ▸ saasng · …/saasng-auto-2 ┃
396
+ ┃ plan ✓ ─ implement ● ─ test ○ ─ verify ○ ┃
397
+ ┃ now: Bash npm test -- refund ┃
398
+ ┃ リサ ニ 2 3 ノ ニ7 2 3 ヤ ┃
399
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
400
+ ```
401
+
402
+ - **The top border** has the card's number, a badge for the kind of session,
403
+ the card and its title, and the status.
404
+ - Badges are reversed so they never read as a status: `PLAN` violet, `DEV`
405
+ terracotta, `REVIEW`/`MERGE`/`RELEASE` light, anything else grey.
406
+ - Statuses: `● running · 12m`, `◆ waiting on you` (or
407
+ `waiting · permission`, `waiting · screenshots`), `◌ queued`, `✓ finished`,
408
+ `✓ planned` (a plan that finished), `✓ finished · nothing built`, `✕ failed`.
409
+ - **The rows inside**, top down:
410
+ - the agent and model, the project and the checkout;
411
+ - the stage walk while the session runs (from the daemon's snapshot, its
412
+ `stage` and `stages`), or the commits once it has finished;
413
+ - ONE line of what it is doing.
414
+ - **The "doing" line.** While it works this is the last tool call (`now: …`),
415
+ even when it has said something since. Before its first tool, it is the last
416
+ thing it said. A queued session says why it waits. An ended session that
417
+ failed or built nothing gives the first line of why. While it waits on you,
418
+ this line holds the question or the tool asking permission.
419
+ - **The last line** says what can be done: an ended session's next step, or
420
+ the keys for what it waits on.
421
+
422
+ A card's frame, and everything inside it, take the status's colour: green
423
+ running or finished, amber waiting or finished having built nothing, grey
424
+ queued, red stopped. The focused card is drawn in heavy lines. **The rows a
425
+ card does not need are rain**: falling glyphs in the status's colour, at its
426
+ speed.
427
+
428
+ | Status | Rain |
429
+ |---|---|
430
+ | running | green, fast, dense |
431
+ | waiting on you | amber, half that speed |
432
+ | queued | grey, slow and sparse |
433
+ | finished | a slow green drizzle |
434
+ | **planned** (a plan that finished) | no rain: a small robot paces along the bottom of the card, waving and blinking, holding up `✓ plan done` |
435
+ | finished, nothing built | slow amber |
436
+ | stopped or failed | slow red |
437
+
438
+ It moves a step every 120 ms, and only while the cards are on screen.
439
+ **`/matrix off`** stills it and is remembered (`prefs.mjs`); `/matrix on` brings
440
+ it back. With it off the rain is gone, but a planned card keeps its robot,
441
+ standing still, because the robot is the news that the card is ready to develop. `session-cards.mjs` is all of it, pure: the grid, a card, the rain at a
442
+ given tick, a function of the session's id, so each session keeps its own drops.
443
+
444
+ **A session's log is `/view`'s.** `/view` takes the focused card's session over
445
+ the whole screen. `/view 2` takes card 2, `/view R42` the session on R42, and
446
+ **`v`** on a card does the same. The log follows the end as it grows. Scroll up
447
+ and it holds still; `G` follows again. **`tab`** goes to the next session's log
448
+ without going back, and `esc` gives the cards back.
449
+
450
+ On the cards, `tab` and `shift+tab` move the focus, `1`–`9` jump to a card,
451
+ and `enter` prompts the focused session exactly as it does outside the mode.
452
+ `/advanced-mode` again (or `/advanced-mode off`) leaves.
371
453
 
372
454
  It is drawn on the terminal's **alternate screen**, like nano or emacs, and
373
455
  holds still the way they do: auto-wrap is off, so nothing ever scrolls the
@@ -378,17 +460,23 @@ for printing into the scrollback still holds, and this mode is something you
378
460
  ask for rather than the default. On the way out, what the watched session said
379
461
  meanwhile is laid into the scrollback, so nothing was lost by watching it here.
380
462
 
381
- **The PLANNED cards run across the top, grouped by project** — a line with
382
- each project's name over its cards and a rule between two projects, every
383
- project this machine serves included ("nothing planned" is an answer) — one
384
- small box each, titled with the card and its status — `R3 (Planned)` — the cards of
385
- every project this machine serves that are ready to be developed, read again
386
- every thirty seconds. **`d`** lists them and develops the one you pick, on this
387
- machine and on the card's own branch — except on a finished plan's window, where
388
- it is that plan's `/develop` (below) with no list; `/new dev` with nothing after it does the
389
- same anywhere, and `/new dev R3` goes straight to one. A full-width rule
390
- under the strip separates the board from the session windows; it comes out of
391
- the strip's own rows, never the windows'.
463
+ **The roadmap runs across the top, grouped by project** — Considering,
464
+ Planned and In development side by side, one line per card, read again every
465
+ thirty seconds. **`b`** (or **`/board`**) puts the focus into the roadmap
466
+ strip (`❯` marks the focused card and an overflowing column scrolls with it):
467
+ `←`/`→` (or `h`/`l`) step across columns and projects, `↑`/`↓` (or `j`/`k`)
468
+ step through the column's cards, and a preview panel directly below the strip
469
+ shows the focused card's **full untruncated title and description** (read on
470
+ demand from `GET /api/projects/:slug/roadmap/:ref` and cached, scrolled with
471
+ `space` / `PgDn` / `PgUp`). From a focused card in the strip, `p` plans it,
472
+ `d` develops it, `v` (or `enter`) prints the full card record, and `esc` (or
473
+ `b` / `/board off`) returns focus to the session cards. Outside board focus,
474
+ **`d`** lists the PLANNED cards and CONFIRMED issues and develops the one you
475
+ pick, on this machine and on the card's own branch — except on a finished
476
+ plan's window, where it is that plan's `/develop` (below) with no list; `/new
477
+ dev` with nothing after it does the same anywhere, and `/new dev R3` goes
478
+ straight to one. A full-width rule under the strip separates the board from
479
+ the session cards; it comes out of the strip's own rows, never the cards'.
392
480
 
393
481
  **`/refresh`** reads the cards again now rather than on the next tick, and
394
482
  says what it found per project — `saasng: 5 considering · 2 planned · 1 in
@@ -396,14 +484,16 @@ development` — and which project could not be read, and why. A project that
396
484
  cannot be read keeps its last cards and no other's: one unreadable slug used
397
485
  to leave every column of every project at 0, silently.
398
486
 
399
- **Four windows at most.** Past four, the rest are named on one line above the
400
- prompt — number, kind, state, card, in the state's colour — and `tab` (or the
401
- number) onto one brings it up in place of another. The focused session always
402
- has a window, then the ones still running, then the ended ones, each most
403
- recently looked at first.
487
+ **As many cards as fit.** Up to three across, as many as the width holds at 38
488
+ columns each, and as many rows as the height holds at six. Each row of cards is
489
+ up to eleven tall, and the prompt has whatever is left. The cards that do not
490
+ fit are named on one line above the prompt (number, kind, state, card, in the
491
+ state's colour), and `tab` (or the number) onto one brings it up in place of
492
+ another. The focused session always has a card, then the ones still running,
493
+ then the ended ones, each most recently looked at first.
404
494
 
405
- A window stays up when its session ends, and its last line says what can be
406
- done next:
495
+ A card stays up when its session ends, and its last line says what can be done
496
+ next:
407
497
 
408
498
  - **`d`** or **`/develop`** on a finished plan — the window says `d develops R2
409
499
  here, in place of this plan` — starts the development of its card, on
@@ -436,6 +526,13 @@ done next:
436
526
  project's runs, kept when `carriesOnHere` — yours, `canCarryOn`, and its
437
527
  checkout on this machine or none), listed in the scrollback, and given a
438
528
  window that opens on why it stopped.
529
+ - **`/clean`** is offered beside `/continue` when a session stopped on a git
530
+ lock a crash left behind (`Unable to create '…/.git/index.lock': File
531
+ exists`), which `/continue` alone would only fail on again
532
+ (`git-lock.mjs`). It removes the lock named in the failure, and only one
533
+ inside that run's own checkout (or its reading worktree's admin directory),
534
+ older than a minute, on a run this machine took. One `/clean` frees every
535
+ session stopped on the same lock; `/continue` then picks each up.
439
536
  - **Finished, having built nothing** — a dev session that ended FINISHED
440
537
  with no commit (IMPLEMENT stopped on a plan it would not follow, say) —
441
538
  reads `finished · nothing built`, in amber rather than green, offers no
@@ -476,6 +573,22 @@ sentence; `--anyway` starts it regardless, the same decision the console's
476
573
  panel asks for. All four commands need you signed in (`/login`), and they work
477
574
  outside advanced mode too, on the session you are watching.
478
575
 
576
+ **Several cards on one line are one batch** (R606): `/new dev R3 R5 R7`,
577
+ `/new plan R3,R5,R7`, `/new plan+dev R3 R5 R7`, in the order written, aimed at
578
+ this machine. It is the console's *Start runs on 3 cards* (`POST
579
+ …/runs/batch`), and the platform holds the order on the runs (`after_run_id`),
580
+ so quitting the terminal does not stop the sequence. `dev` is a branch each,
581
+ queued here; `--in-order` is one branch, each run from the last one's commits,
582
+ named with `--branch <name>` or else the first card's. `plan` plans the cards
583
+ one after another (a plan takes no checkout, so only the chain keeps them in
584
+ turn). `plan+dev` plans a card, builds it as soon as its plan is written (the
585
+ project's hand-off switch is not asked: you asked on the line), and plans the
586
+ next once that build has finished: plan R3, build R3, plan R5, build R5. A build
587
+ that fails or is cancelled holds the rest until it is carried on or started over.
588
+ A card the platform skips is named with its reason (`batchStartedLines`).
589
+ `--again` and `--show` are one card's answers and a batch refuses them;
590
+ `--codex` and `/agent` apply to every card.
591
+
479
592
  **The prompt says which window it acts on.** In advanced mode the line at the
480
593
  bottom leads with the focused window's number — `[2] cawdev ▸ /pr`, `[2]
481
594
  enter prompts “…”` — and a command's answer keeps the number of the window it
@@ -514,8 +627,8 @@ card — in the browser, on the console this terminal signed in to.
514
627
  **On a session waiting for you** — a question, or a permission such as a stage
515
628
  gate whose summary is the whole plan — the prompt only has room for the start
516
629
  of it, and says so: `/view reads it all · /open answers it on cawdev`.
517
- **`/view`** then opens the READER: one window over the whole screen with the
518
- session's output and, under a rule, the request in full (the question and its
630
+ **`/view`** then opens the READER: the session's log over the whole screen
631
+ (as above) and, under a rule, the request in full (the question and its
519
632
  options; the permission's summary, its input and its keys). It opens on the
520
633
  request; `↑`/`↓` (and the wheel), `PgUp`/`PgDn`, `g`/`G` scroll it, `esc`
521
634
  closes it, and any other key closes it and does what it always does — `a`
@@ -571,6 +684,58 @@ a model. Titled by its words (`cardTitleFor`), the whole text in its body;
571
684
  the project chosen exactly as `/new` chooses it (`@project`, else advanced
572
685
  mode narrowed to one, else asked).
573
686
 
687
+ **`/review`** reads a card's branch and acts on it from here: the focused
688
+ session's card, or `/review R42 (@project)`. The diff is local git
689
+ (`diff-view.mjs`: `git fetch origin <base> <branch>`, which moves refs only,
690
+ then `git diff base...branch` from the merge base, in the session's checkout or
691
+ one the config names), so no diff crosses the API and a working checkout is
692
+ never touched; a failed fetch reads what the checkout has and says it may be
693
+ behind. File bytes are made printable before they are drawn. In advanced mode
694
+ it is the reader (`n`/`p` files, `f` fold; lockfiles, binaries and files over
695
+ `FOLD_OVER_LINES` start folded) with `d` Done, `c` changes requested (the note
696
+ is asked in the prompt; empty goes back to the diff) and `m` merge, offered on
697
+ a Done branch to a person holding Merge and pressed twice. Outside it the diff
698
+ is printed and the acts are `/review done|changes <note>|merge|agent-merge`.
699
+ Each act is the platform's endpoint (`work-items/{id}/verdict`, `/merge`,
700
+ `/agent-merge`); after a merge the card is read every five seconds until it is
701
+ MERGED or the merge FAILED (`followMerge`).
702
+
703
+ **While it merges, the card's sessions are out of reach** (`markMerging`,
704
+ `refuseWhileMerging`). Their cards turn grey and say `⇢ merging` and
705
+ `r42-pay → main`. Instead of rain, a robot looking ahead (`[>_>]`) carries the
706
+ branch (`[■]`) to `▶ main` and walks back for the next load
707
+ (`session-cards.mjs` `mergingRobotLines`). Enter, `d`, `x` and the bare
708
+ commands that act on the branch or its checkout are refused with the reason:
709
+ `/pr`, `/continue`, `/clean`, `/drop`, `/close`, `/cancel`, `/develop` and
710
+ `/review` (`DISABLED_WHILE_MERGING`). `/view` and `/open` still work.
711
+ - **Once it lands**, the card closes by itself (a session still running only
712
+ loses the mark).
713
+ - **If the merge hits a conflict** (the merge's `failure` is `CONFLICT`, or an
714
+ older runner's words say so), the card goes back to development
715
+ (`resolveConflict`).
716
+ - The branch is sent back, Not done, with an order as its note
717
+ (`conflictOrder`): merge `origin/main` into the branch, resolve every
718
+ conflict keeping what both sides meant, change nothing else, run the tests,
719
+ commit and push. The next session on the card is handed that note.
720
+ - That session is started here again (`again`), with the agent that built
721
+ the branch. The old card gives way to the new one, which takes the focus.
722
+ - Once it is Done, `/review` and `m` merge it again. `/review agent-merge`
723
+ is still there for an agent of its own.
724
+ - **If the merge fails any other way** (not permitted, unreachable…), no
725
+ agent can fix it. The card comes back red, `✕ merge failed`, with the
726
+ machine's words and `/review` on its last line, and every act is offered
727
+ again.
728
+
729
+ **`/import <file.json>`** files the cards of a JSON file (`card-import.mjs`,
730
+ over `POST /api/projects/{slug}/roadmap/import`): a list of `{title, body,
731
+ severity, tags, …}` or `{"cards": [...]}`. The project is `@project`, else
732
+ advanced mode narrowed to one, else the one project served; with several it is
733
+ asked for by name. `--dry-run` only checks. A card whose title is taken (on the
734
+ board, or earlier in the file) is skipped and listed with what it repeats;
735
+ `--allow-duplicates` files it anyway. From the shell, `cawdev import
736
+ <file.json>` checks first, prints what would be filed and refused, and asks
737
+ (`--yes` does not; `--project`, `--status`, `--dry-run` as above).
738
+
574
739
  **Across the top, the roadmap** (`roadmapStrip`): every project this machine
575
740
  serves as a small board — Considering, Planned and In development side by
576
741
  side, one line per card, `●` on a card with a session running now; Merged,
@@ -978,7 +1143,13 @@ files at all. R47 removes the need for this by giving each run a workspace.
978
1143
  and leaves the run exactly as the platform has it; if it is QUEUED, the next
979
1144
  poll offers it again and it is claimed properly. Only 400, 404, 409 and 410
980
1145
  count as a refusal; any other status (401, 403, 408, 429), a network error or
981
- a 5xx still fails the run.
1146
+ a 5xx still fails the run. For a MERGE run (R621), the merge the daemon
1147
+ prepared is undone before it lets go, on a refusal and on a failure alike
1148
+ (`git merge --abort`, or a `reset --keep` past its own merge commit), so the
1149
+ checkout is offered again as it was; the FAILED summary says so. A checkout
1150
+ found mid-merge that the daemon did not start is refused with a sentence
1151
+ naming `git commit` and `git merge --abort`, and is not touched; a MERGE run
1152
+ carrying on its own branch is the exception.
982
1153
  3. **Spawns the agent** in that directory, in its own process group, with the
983
1154
  run token in its environment and an `.mcp.json` pointing at cawdev's MCP
984
1155
  server. **Your own token never reaches the child.**
@@ -1214,6 +1385,20 @@ Bitbucket project's pull request or merge to it: the button says "No machine of
1214
1385
  yours runs a cawdev runner that speaks Bitbucket. Restart the daemon to update
1215
1386
  it."
1216
1387
 
1388
+ **The fix proves itself (R318).** When the run's card was filed from a
1389
+ SonarQube finding, the claim carries it (`findingsToProve`) and the scan then
1390
+ asks the server whether it is still reported on the tree just scanned, and
1391
+ reports `fixedKeys` / `stillOpenKeys` with the reading. SonarQube gives an issue
1392
+ a *new key* when it copies it onto a branch, so on a `BRANCH` or `PROJECT`
1393
+ reading the match is the rule in the file — narrowed to the line's hash when the
1394
+ finding has one, since lines move. Without a hash, another issue of the same rule
1395
+ in that file reads as "still reported": the check can err toward blocking, never
1396
+ toward calling an unfixed finding fixed. On a `MAIN` reading the key itself is
1397
+ asked for. A reading is taken after TEST, so commits from a later stage, or
1398
+ pushed by hand, are not seen. **Restart the daemon** to read `findingsToProve`: a
1399
+ daemon started before R318 sends neither list, and the board then says *Not
1400
+ checked*.
1401
+
1217
1402
  ### What the agent may push
1218
1403
 
1219
1404
  A coding session may commit on its card's branch and push **that branch and
@@ -1233,6 +1418,82 @@ shell and your credentials can get round a pattern match (`git -c alias.x='!…'
1233
1418
  a host CLI called through a script). **The real wall is branch protection on the
1234
1419
  host: protect the default branch and require a pull request.** Do that.
1235
1420
 
1421
+ ## Showing a card before its pull request (R604)
1422
+
1423
+ A card with *Show me before the PR* on walks **IMPLEMENT → TEST → SHOW → MEMORY**.
1424
+ SHOW is the agent's chance to show a person what it built, before anything is proposed.
1425
+
1426
+ - **The folder.** The session writes 1–8 files into `.cawdev/shots/` — a PNG or JPEG of
1427
+ the real screen (the repository's own Playwright, or Claude in Chrome), or a *static*
1428
+ self-contained HTML mock — and `.cawdev/shots/shots.json`, `[{"file", "caption"}]`.
1429
+ Each file is 2 MB or smaller. The daemon adds the folder to `.git/info/exclude`, so it
1430
+ is never committed, and deletes it once the round is uploaded.
1431
+ - **The upload is the daemon's**, with the machine's token on `runner:operate`. The
1432
+ session holds the run token and cannot upload what it is judged by.
1433
+ - **The tree check.** SHOW is spawned with a tool list that allows `Edit` only under
1434
+ `.cawdev/shots/`, but its Bash can write anywhere, so the list is not the guard:
1435
+ after the stage the daemon compares the tree with how it began. A commit, or any path
1436
+ changed outside the folder (build output that is not gitignored counts), fails the
1437
+ stage, names the paths, and raises no gate.
1438
+ - **No permission mode.** SHOW is spawned without `--permission-mode` (never
1439
+ `acceptEdits`, never "allow everything") and with the permission prompt kept: a Bash
1440
+ command that is not on the allowed list becomes a question for a person. On a machine
1441
+ with few Bash patterns SHOW is chatty; the answer is a project rule for the app's start
1442
+ command, not a mode. Codex and Antigravity cannot be narrowed this way, so for them
1443
+ the tree check is the only guard.
1444
+ - **The gate.** The daemon raises `stage:SHOW` with the round and its screenshot ids.
1445
+ `attach` shows it as a wait to look at (below); `/open` opens the run page. SHOW is reported DONE only after *Accept*, so a daemon that dies while the
1446
+ gate waits resumes at SHOW. A gate that cannot be raised fails the stage.
1447
+ - **Comments** send the walk back to IMPLEMENT, with the comments leading its prompt,
1448
+ then TEST and SHOW again. There is no cap on rounds.
1449
+
1450
+ The daemon must be restarted to learn the SHOW stage.
1451
+
1452
+ ### Looking and deciding from the terminal (R605)
1453
+
1454
+ A run stopped at SHOW is not a permission request, and `attach` does not ask for one.
1455
+ The window's title says `waiting for you` and its subtitle, in amber, reads
1456
+ `waiting for you — 3 screenshots, round 2 · a to look and decide`. The banner says
1457
+ ` show ` and offers `a`, `/accept`, `/comments …` and `/open` instead of `y / s / n`.
1458
+
1459
+ - **`a`** (or `/view`) opens one picker: the round's screenshots, numbered, with their
1460
+ captions (control characters stripped — a caption comes from the session); *Open all*;
1461
+ *Accept — open the pull request*; one row per earlier round, with the comments sent on
1462
+ it; and *Send comments…*. Enter on a numbered screenshot opens that one.
1463
+ - **Commands** act on the focused session and say `is not waiting at SHOW` and do
1464
+ nothing when it is not at SHOW: `/shots` (the round listed), `/shots 2`, `/shots all`,
1465
+ `/shots round 1` (an earlier round and its comments), `/shots round 1 all`,
1466
+ `/accept`, and `/comments <text>`. In comments a line starting `#2` is a note on
1467
+ screenshot 2 and every other line is the round's note; on the one-line command, a `#2`
1468
+ anywhere starts the note on screenshot 2, which runs to the next `#n` or the end. An
1469
+ unknown `#n` or an empty comment is refused before anything is sent. In the picker's
1470
+ *Send comments…* an empty line sends; Esc goes back to the picker and keeps the lines.
1471
+ - **`y`, `s`, `Y`, `M` and `n` do nothing at SHOW** and say to use `a`, `/accept` or
1472
+ `/comments`: `s` would otherwise have accepted the round, and opened the pull request,
1473
+ without anybody looking.
1474
+ - **`--show` / `--no-show`** on `/new dev` and `/develop` override the card's switch for
1475
+ one run (on a plan or a question they are refused in words); `/card <idea> --show`
1476
+ writes a card with the switch on.
1477
+ - **Only the screenshots the platform sealed are shown.** A gate's list is the session's
1478
+ own claim, so the picker joins it to `GET …/attachments` for that round; a gate that
1479
+ names an id that was never sealed offers no Accept.
1480
+
1481
+ **The cache.** Images open in the OS viewer (`open` with every path on macOS, so Preview
1482
+ pages through them in one window; `xdg-open` once per file elsewhere) from
1483
+ `~/.cawdev/shots/<runId>/<round>/` (directories 0700, files 0600; `CAWDEV_SHOTS_DIR`
1484
+ moves it). Each file is named by its SHA-256 and an extension taken from the platform's
1485
+ content type, is downloaded the first time and not again while its bytes still match, and
1486
+ is checked against the checksum the list carries. **The terminal is the only writer** —
1487
+ the daemon deletes the checkout's `.cawdev/shots/` once a round is sealed and never
1488
+ writes the cache, because a session could plant a link there. A link at any level is
1489
+ refused.
1490
+
1491
+ **HTML is never opened from disk.** It opens at its sandboxed URL on the platform in the
1492
+ browser (which must be signed in to cawdev), because a `file://` page is a trusted page.
1493
+
1494
+ **Thumbnails.** In iTerm2, WezTerm and kitty, `/shots` also prints each image small into
1495
+ the scrollback — not in advanced mode, not when `plain`, and never to any other terminal.
1496
+
1236
1497
  ## What a project's rules can ask of it (R40)
1237
1498
 
1238
1499
  A project may decide that a finished run **pushes its branch**, **opens a pull