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/lib/finish-check.mjs +9 -1
- package/lib/gate-condition.mjs +11 -0
- package/lib/sonar-analysis.mjs +55 -9
- package/lib/stage-tools.mjs +33 -2
- package/mcp/server.mjs +44 -12
- package/package.json +1 -1
- package/runner/README.md +294 -33
- package/runner/attach.mjs +1927 -123
- package/runner/card-import.mjs +115 -0
- package/runner/cawdev.mjs +70 -1
- package/runner/diff-view.mjs +252 -0
- package/runner/git-lock.mjs +73 -0
- package/runner/runner.mjs +508 -39
- package/runner/session-cards.mjs +660 -0
- package/runner/shots.mjs +214 -0
- package/runner/sign-in.mjs +29 -2
- package/runner/split.mjs +307 -74
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
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
the
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
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
|
-
**
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
|
406
|
-
|
|
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:
|
|
518
|
-
|
|
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
|