@lovek4d/kickflip 0.5.0 → 0.6.0
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/CONTEXT.md +105 -68
- package/README.md +1 -1
- package/SKILL.md +27 -21
- package/bin/kickflip.mjs +27 -18
- package/bin/wait-events.mjs +2 -2
- package/board/agents.mjs +2 -0
- package/board/arch-review.mjs +4 -4
- package/board/bin/board.mjs +199 -79
- package/board/build-script.mjs +2 -1
- package/board/domain.mjs +9 -7
- package/board/finish.mjs +4 -4
- package/board/headless.mjs +9 -4
- package/board/on-host.mjs +1 -1
- package/board/onboarding.mjs +11 -0
- package/board/prototype-base.mjs +1 -0
- package/board/prototype-page.mjs +1 -0
- package/board/public/app-arch.js +1 -1
- package/board/public/app-asks.js +6 -6
- package/board/public/app-banner.js +7 -13
- package/board/public/app-cards.js +75 -37
- package/board/public/app-core.js +26 -8
- package/board/public/app-header.js +8 -8
- package/board/public/app-lanes.js +67 -58
- package/board/public/app-needs.js +140 -10
- package/board/public/app-reader.js +1 -1
- package/board/public/app-snapshot.js +46 -72
- package/board/public/app-threads.js +78 -75
- package/board/public/app.html +9 -4
- package/board/public/app.js +114 -38
- package/board/public/attach.js +2 -2
- package/board/public/dialogs.js +9 -39
- package/board/public/hub-kit.js +66 -4
- package/board/public/hub.css +2 -0
- package/board/public/linear-key.js +46 -35
- package/board/public/new-task.js +20 -39
- package/board/public/progress-review.html +46 -0
- package/board/public/progress-review.js +158 -0
- package/board/public/prototype-kit.js +137 -7
- package/board/public/prototype-switcher.js +152 -123
- package/board/public/prototype.html +57 -3
- package/board/public/router.js +7 -6
- package/board/public/shell.js +68 -26
- package/board/public/sidebar.css +1 -0
- package/board/public/sidebar.js +16 -30
- package/board/public/style.css +205 -83
- package/board/public/ui-cards.js +91 -65
- package/board/public/ui-enums.js +1 -1
- package/board/public/ui-header.js +27 -18
- package/board/public/ui-hub.js +12 -1
- package/board/public/ui-links.js +7 -7
- package/board/public/ui-order.js +12 -10
- package/board/public/ui-page-header.js +19 -7
- package/board/public/ui-patch.js +7 -33
- package/board/public/ui-progress-bar.js +28 -0
- package/board/public/ui-questions.js +47 -52
- package/board/public/ui-sidebar.js +34 -26
- package/board/public/ui-snapshot.js +43 -52
- package/board/public/ui-threads.js +59 -30
- package/board/public/ui.js +125 -18
- package/board/public/view-hub-settings.js +22 -67
- package/board/public/view-hub.js +19 -4
- package/board/public/view-notes.js +27 -7
- package/board/public/view-questions.js +205 -240
- package/board/public/view-settings.js +313 -76
- package/board/render-check.mjs +10 -0
- package/board/review.mjs +1 -1
- package/board/server.mjs +19 -20
- package/board/stop.mjs +1 -0
- package/board/store.mjs +29 -15
- package/board/sync.mjs +2 -0
- package/board/tickets.mjs +3 -3
- package/board/transcript.mjs +2 -0
- package/board/worktree.mjs +25 -20
- package/hooks-plugin/hooks/board-data-gate.mjs +50 -0
- package/hooks-plugin/hooks/hooks.json +9 -0
- package/hooks-plugin/hooks/usage-gate.mjs +20 -3
- package/hub/board-repo.mjs +1 -1
- package/hub/boards.mjs +4 -4
- package/hub/front-door.mjs +5 -5
- package/hub/github.mjs +3 -3
- package/hub/hub.mjs +11 -11
- package/hub/incoming.mjs +2 -2
- package/hub/linear.mjs +1 -2
- package/hub/live.mjs +2 -2
- package/hub/locks.mjs +1 -1
- package/hub/owner-checks.mjs +1 -1
- package/hub/pr-report.mjs +2 -2
- package/hub/presence.mjs +1 -1
- package/hub/push.mjs +2 -2
- package/hub/readiness.mjs +1 -2
- package/hub/review-send.mjs +1 -0
- package/hub/secrets.mjs +2 -0
- package/hub/self-restart.mjs +2 -0
- package/hub/sessions.mjs +2 -2
- package/hub/share.mjs +1 -0
- package/hub/slack.mjs +2 -2
- package/hub/stream.mjs +10 -13
- package/hub/try.mjs +7 -7
- package/hub/upgrade.mjs +1 -1
- package/hub/usage.mjs +3 -3
- package/hub/views.mjs +1 -1
- package/package.json +2 -1
- package/shared/audit.mjs +4 -0
- package/shared/card-prs.mjs +1 -1
- package/shared/fake-gh.mjs +17 -4
- package/shared/machine-gate.mjs +2 -0
- package/shared/prototype-frame.js +1 -0
- package/shared/service.mjs +4 -4
- package/shared/usage-gate.mjs +1 -1
- package/board/public/ui-phase-bars.js +0 -17
package/CONTEXT.md
CHANGED
|
@@ -31,7 +31,7 @@ The machine the hub and its sessions run on, a Mac or a Linux machine. Its **hub
|
|
|
31
31
|
_Avoid_: the Mac, server (for the machine)
|
|
32
32
|
|
|
33
33
|
**Sidebar**:
|
|
34
|
-
The list of every site beside each board and hub page: New version with Reload when the hub’s code changed since the app loaded
|
|
34
|
+
The list of every site beside each board and hub page: New version with Reload, only when the hub’s code changed since the app loaded (the hub pulls and restarts itself, and a failed pull or restart shows nothing; [the update row shows only New version and Reload](docs/adr/2026-11-06-0800-the-update-row-shows-only-new-version-and-reload.md)), then Hub, then Turn on notifications when needed, then Pages (sites that aren't boards), then Boards with their status words, lane chips, waiting counts and **context window** (its owner session's last reported percent, e.g. “62% ctx”, from `~/.claude/kickflip/context/<session>.json`, which the status line writes; dimmed with its age once ten minutes old; none on cards or for subagents; a board not listening at 95% or more reads **context full**, and the hub board's session gets `/compact` typed into its tmux pane once ([a board session compacts before its context fills](docs/adr/2026-11-03-1823-a-board-session-compacts-before-its-context-fills.md))). The last row of Boards is **New board**, a + tile opening a sheet that chooses a GitHub repo from the list or a pasted GitHub link or `owner/name`, then its branch, Name, optional What it’s for and Tickets (Internal · INT by default); a line under the repo field points a repo already on the host at `kickflip join` in its folder. Start is the confirm: the hub starts the board’s session itself once the request passes its checks; a muted, non-link row shows its name, its three start steps (**cloning**, **starting orchestrator**, **landing it**) on the board's phase bars, and the step with its seconds, cloning with git's percent, until its route joins and the row turns into the board's ([a new board shows its start steps and live clone progress](docs/adr/2026-11-04-1914-a-new-board-shows-its-start-steps-and-clone-progress.md)). When claude fails to start, or after 15 minutes without a join, it keeps the board's name in red with **failed to start** under it ([the hub starts a new board's session itself](docs/adr/2026-10-31-0137-the-hub-starts-a-new-boards-session.md)); tapping it opens a sheet with the clone or session error line, what the start used, Dismiss and **Retry**, which starts it again from the same record ([a failed start retries from its sheet](docs/adr/2026-11-02-2006-a-failed-start-retries-from-its-sheet.md)). Hub carries notification problems and the tools’ 5-hour usage bars under its sub line, and a moon after its name while pushes are held or snoozed, whose tooltip says until when; the whole row opens the hub page and stays selected on the hub page and its settings modals. Boards and Pages stay apart wherever sites are listed. The header's logo toggles it at every width; it carries no count, and shows a plain accent dot while a new version waits. From 900px it is a rail, which its own logo collapses out of sight until the header's logo brings it back; narrower, it is a drawer. Its header reads Kickflip. Below 900px every page header is a bottom bar, and the drawer header sits at its foot under New board; desktop headers stay at the top ([phone headers sit at the bottom, with boards nearest the thumb](docs/adr/2026-10-31-1532-phone-headers-sit-at-the-bottom.md)). In the **app shell** it is mounted once, beside every view and framed page, and a site's row swaps the view in place. `/` opens this device's **last board**, which the app shell stores as each board opens, never a page ([a sidebar of every board replaces the hub home](docs/adr/2026-10-29-1639-a-sidebar-of-every-board-replaces-the-hub-home.md), [one app for the whole hub](docs/adr/2026-10-29-2005-one-app-for-the-whole-hub.md)).
|
|
35
35
|
_Avoid_: hub home, switcher, nav
|
|
36
36
|
|
|
37
37
|
**Switch mode**:
|
|
@@ -47,11 +47,11 @@ The one page a browser's load of `/`, a hub page or any site's page gets, `board
|
|
|
47
47
|
_Avoid_: SPA, wrapper, frame
|
|
48
48
|
|
|
49
49
|
**View**:
|
|
50
|
-
One page's content in the app shell, mounted when its URL opens and unmounted, with every listener, timer and stream it added, when another takes its place. A board is a view, and so are its Waiting on you and Notes, and the **hub page**; hub settings open over Hub and Board Settings opens over its board as modals; a board left and opened again paints from its **last visit**, live
|
|
50
|
+
One page's content in the app shell, mounted when its URL opens and unmounted, with every listener, timer and stream it added, when another takes its place. A board is a view, and so are its Waiting on you and Notes, and the **hub page**; hub settings open over Hub and Board Settings opens over its board as modals; a board left and opened again paints from its **last visit**, live, and catches up from its **change number**. Opened again in the same page, unless its link names a card, it also returns to where the owner left it: the page's scroll, its open threads' windows and edit boxes, and, with a mouse or trackpad, the box being typed in with its caret or selection; a phone keeps the keyboard shut. A reload starts fresh. Any other page, another site's or a board's prototype, is a **frame view**: the page in a frame beside the board header, or its own when it draws that header, with Open alone ↗ to load it by itself.
|
|
51
51
|
_Avoid_: screen, tab, page (a page is its own document)
|
|
52
52
|
|
|
53
53
|
**Page tree**:
|
|
54
|
-
The levels back climbs in the app shell: a board, its Waiting on you, then a separately opened prototype page tied to one of its questions by `?q=`. On each, the back arrow, the browser's back and a swipe all go up one level: from a prototype to Waiting on you on its question, from there to the board, with the card still open when the owner left the board from that card's thread. However the owner arrives, by a push, a link or a reload, the levels above are written into history under the page first ([Back follows the page tree](docs/adr/2026-10-30-1125-back-follows-the-page-tree.md)).
|
|
54
|
+
The levels back climbs in the app shell: a board, its Waiting on you, then a separately opened prototype page tied to one of its questions by `?q=`. On each, the back arrow, the browser's back and a swipe all go up one level: from a prototype to Waiting on you on its question, from there to the board, with the card still open when the owner left the board from that card's thread. However the owner arrives, by a push, a link or a reload, the levels above are written into history under the page first ([Back follows the page tree](docs/adr/2026-10-30-1125-back-follows-the-page-tree.md)). From 900px Waiting on you is no page of its own: every URL of it shows the board at the board's URL with its topic open in the pane, so the tree is the board and a prototype ([Board and Open questions are two pages](docs/adr/2026-11-07-1300-board-and-open-questions-are-two-pages.md)).
|
|
55
55
|
_Avoid_: nav stack, breadcrumbs
|
|
56
56
|
|
|
57
57
|
**Hub page**:
|
|
@@ -63,7 +63,7 @@ The word on the Hub row of the sidebar and the hub page's Health card: **healthy
|
|
|
63
63
|
_Avoid_: broken, hub health
|
|
64
64
|
|
|
65
65
|
**Integration readiness**:
|
|
66
|
-
What each integration needs before its features can run: the Hub page’s Integrations section between Health and Boards lists GitHub, Codex, Linear, Slack, Tailscale and Notifications in that order. A row reading ready says what passed; one reading not ready is orange and says what is missing, how to fix it and which features wait.
|
|
66
|
+
What each integration needs before its features can run: the Hub page’s Integrations section between Health and Boards lists GitHub, Codex, Linear, Slack, Tailscale and Notifications in that order. A row reading ready says what passed; one reading not ready is orange and says what is missing, how to fix it and which features wait. Slack is ready while Hub’s Slack token is saved and Slack hasn’t refused it; the hub shares the same readiness and words with feature gates ([integrations show readiness, and features wait until theirs is ready](docs/adr/2026-11-02-1118-integrations-show-readiness-and-features-wait.md)).
|
|
67
67
|
_Avoid_: integration health, availability
|
|
68
68
|
|
|
69
69
|
**Usage reading**:
|
|
@@ -74,10 +74,22 @@ _Avoid_: quota, live usage
|
|
|
74
74
|
The Usage card's “Pause work at”, last in the group below Codex: `pauseAt` in `~/.claude/kickflip/settings.json`, 50–100 in steps of 5, default 90 (10% buffer); 100 reads Off. Either live Claude window at or over it pauses new work until that window resets. Running steps finish; builders and new agents wait, watchers hold the hub's work events, and owner messages get a brief “paused until <time>”. Keep going lifts that window's pause until its reset; Stop restores it. Codex hands work to Opus builders at the same line, without pausing. The Hub banner and sidebar and board header status slots show the pause, never the logo. `shared/usage-gate.mjs` owns it; `kickflip usage-gate` prints it ([work pauses at the pause line](docs/adr/2026-11-01-1710-work-pauses-at-the-pause-line.md)).
|
|
75
75
|
_Avoid_: buffer threshold, quota guard
|
|
76
76
|
|
|
77
|
+
**Pause hub** and **Pause board**:
|
|
78
|
+
The owner's manual pause, first in Hub settings and Board settings, with the snooze picker's chips, Forever included, and Custom: until its end (Forever's lasts until Resume) it pauses new work exactly as the **pause line** does, Codex builders included, on every board for Pause hub (settings.json's `paused_until`) and on that board alone for Pause board (board.json's `paused_until`, no board setting). It outranks the usage pause and Keep going, Pause hub first. Resume ends it, and the end wakes the boards with `usage-resumed {window: "manual"}`. It reads paused in gray wherever the usage pause shows: Pause hub on the Hub banner and row and every board, Pause board on its own sidebar row, header and cards ([Pause board and Pause hub pause new work by hand](docs/adr/2026-11-05-1849-pause-board-and-pause-hub-pause-new-work-by-hand.md)).
|
|
79
|
+
_Avoid_: snooze (pushes only), hold (one card)
|
|
80
|
+
|
|
81
|
+
**Busy Mac**:
|
|
82
|
+
This Mac at memory pressure critical or a 1-minute load of 4× its cores or more, until pressure is warn or lower and load is under 3× its cores. While busy every board holds all new work as the **pause line** does, Codex builders, landers and bumped cards included, and running work finishes. The hub's tick keeps the state in `~/.claude/kickflip/machine-state.json` (`shared/machine-gate.mjs`), which the one gate carries as `machine`. It reads busy, in words only, on the Hub row, every board row, the board header and Health's Machine row, and a card whose launch it holds gets a thread line ([a busy Mac holds new work](docs/adr/2026-11-06-0106-a-busy-mac-holds-new-work.md)).
|
|
83
|
+
_Avoid_: resources low, overload
|
|
84
|
+
|
|
77
85
|
**Claude model**:
|
|
78
86
|
The Usage card's Opus · Auto · Sonnet control, opening Claude's block: `claudeModel` in `~/.claude/kickflip/settings.json`, default Auto. It decides which model builds a card Claude builds: Opus or Sonnet always, or under Auto the card's own `--model`, else Sonnet for a card `--size small` and Opus for the rest. `builder pick` prints it with why, and a build's `builder start` refuses a `--model` it rules out. Codex builds, prototypes and grills don't read it ([usage picks Opus, Auto or Sonnet for Claude builders, and builder pick says which and why](docs/adr/2026-11-03-1526-usage-picks-opus-auto-or-sonnet-for-claude-builders.md)).
|
|
79
87
|
_Avoid_: Opus builders, allow Opus
|
|
80
88
|
|
|
89
|
+
**Audit log**:
|
|
90
|
+
One JSON line for each call the code makes on its own, with when, the call, the card, its result, the reason and the inputs it read: a board's in its `data/audit.jsonl`, such as the pick a build started on, a pull, a relaunch or an auto-merge, and the hub's own (usage pauses and resumes, Linear moves) in `~/.claude/kickflip/audit.jsonl`. Each keeps the last 30 days. `board.mjs audit [<card>]` and `kickflip audit` print them ([the hub and each board keep an audit log of the calls their code makes](docs/adr/2026-11-05-0913-the-hub-and-each-board-keep-an-audit-log-of-the-calls-their-code-makes.md)).
|
|
91
|
+
_Avoid_: hub.log (the hub's free-text stderr), history
|
|
92
|
+
|
|
81
93
|
**Board registry**:
|
|
82
94
|
`hub/boards.mjs`, the only hub code that reads a board's `board.json` and wave files. Every hub feature that serves boards (the GitHub check, wakes, rules, the handshake, the not-listening push) takes its boards from it, so a board over the waves and a board over its own file get the same links ([one board registry for every hub feature](docs/adr/2026-10-29-1639-one-board-registry-for-every-hub-feature.md)).
|
|
83
95
|
_Avoid_: board list, wave boards and file boards (as separate code paths)
|
|
@@ -125,11 +137,11 @@ The hub resuming a board session as soon as an event lands while that session is
|
|
|
125
137
|
_Avoid_: auto-resume, respawn, wake (a daily wake is the morning `check-github`)
|
|
126
138
|
|
|
127
139
|
**Push**:
|
|
128
|
-
A notification from the hub, on the phone or a desktop browser, that opens a page. Each push has a kind, and `hub/push.mjs` `deliver()` refuses any other: `action` when a card's **Action needed** appears or changes, `prompt` for a **pending prompt**, `fault` for what only the owner can fix (a board not listening, a session that didn't come back, an urgent production problem) ([a push goes out only when something waits on the owner, on the hub's schedule](docs/adr/2026-10-29-1639-pushes-only-when-something-waits-on-the-owner.md)). Answers, merges, Stale and other news never push; the threads' unread marks and the board carry them. The board server sends each action push itself, under the card's tag or `topic-<id>` for a Needs you topic, when Action needed appears, changes kind or gains a question ([the board records what it knows, and commands make the rule calls](docs/adr/2026-11-03-0003-the-board-records-what-it-knows-and-commands-make-the-rule-calls.md)). Questions, steps and prototypes go at once; drafts on Ready and Merge go when their tick ends, and one under a card's tag replaces the last and alerts again ([pushes go out by kind, and each arrives on its own](docs/adr/2026-10-29-1639-pushes-go-by-kind-and-each-arrives-on-its-own.md)). When the queue goes out, a board with one queued push gets it as it is, and a board with several gets one summary of what waits on its Needs you then, tagged `summary:<route>` so the newest replaces the last, or nothing when nothing waits ([queued pushes go as one summary per board](docs/adr/2026-11-02-1733-queued-pushes-go-as-one-summary-per-board.md)). Replies don't push; a push that goes out anyway says how many came since the last one. With notifications off every push is dropped; a snooze and Off on weekends hold pushes until they end, and urgent ones go through those holds ([notifications can be off, snoozed, or off on weekends](docs/adr/2026-10-29-1639-notifications-can-be-off-snoozed-or-off-on-weekends.md)).
|
|
140
|
+
A notification from the hub, on the phone or a desktop browser, that opens a page. Each push has a kind, and `hub/push.mjs` `deliver()` refuses any other: `action` when a card's **Action needed** appears or changes, `prompt` for a **pending prompt**, `fault` for what only the owner can fix (a board not listening, a session that didn't come back, an urgent production problem) ([a push goes out only when something waits on the owner, on the hub's schedule](docs/adr/2026-10-29-1639-pushes-only-when-something-waits-on-the-owner.md)). Answers, merges, Stale and other news never push; the threads' unread marks and the board carry them. The board server sends each action push itself, under the card's tag or `topic-<id>` for a Needs you topic, when Action needed appears, changes kind or gains a question ([the board records what it knows, and commands make the rule calls](docs/adr/2026-11-03-0003-the-board-records-what-it-knows-and-commands-make-the-rule-calls.md)). Questions, steps and prototypes go at once; drafts on Ready and Merge go when their tick ends, and one under a card's tag replaces the last and alerts again ([pushes go out by kind, and each arrives on its own](docs/adr/2026-10-29-1639-pushes-go-by-kind-and-each-arrives-on-its-own.md)). When the queue goes out, a board with one queued push gets it as it is, and a board with several gets one summary of what waits on its Needs you then, tagged `summary:<route>` so the newest replaces the last, or nothing when nothing waits ([queued pushes go as one summary per board](docs/adr/2026-11-02-1733-queued-pushes-go-as-one-summary-per-board.md)). Replies don't push; a push that goes out anyway says how many came since the last one. With notifications off every push is dropped; a snooze and Off on weekends hold pushes until they end, and urgent ones go through those holds ([notifications can be off, snoozed, or off on weekends](docs/adr/2026-10-29-1639-notifications-can-be-off-snoozed-or-off-on-weekends.md)). Every push goes to every subscribed device ([every push goes to every device](docs/adr/2026-11-05-2230-every-push-goes-to-every-device.md)).
|
|
129
141
|
_Avoid_: alert, notification (for the act of sending)
|
|
130
142
|
|
|
131
143
|
**At the host**:
|
|
132
|
-
The owner's presence
|
|
144
|
+
The owner's presence, which sets the **Check cadence** and the moon: the host's screen is unlocked and a key or the pointer was used in the last 3 minutes, whatever app is in front (`hub/presence.mjs`). It is read from macOS `ioreg`, so on a Linux host the owner always reads away.
|
|
133
145
|
_Avoid_: at the Mac, active, online, desktop app active
|
|
134
146
|
|
|
135
147
|
**Check cadence**:
|
|
@@ -141,11 +153,15 @@ A start and end time, 10:00pm to 8:00am by default. With its hold on, pushes que
|
|
|
141
153
|
_Avoid_: overnight window, wake times
|
|
142
154
|
|
|
143
155
|
**Hub settings**:
|
|
144
|
-
The
|
|
156
|
+
The summary rows below the **hub page**’s health and status: **Pause hub** first, then Notifications, Quiet hours, Keep awake, Linear, Slack, Rules for every board and Closed boards. Each opens its controls in a centred modal with its own scroll area. Snooze and Keep awake share one duration picker: 1h, 3h, 6h, 1d, Forever and Custom. Keep awake has the hub run `caffeinate -ims` until its end, and is disabled on hosts other than macOS ([snooze and Keep awake share one duration picker](docs/adr/2026-11-02-1402-snooze-and-keep-awake-share-one-duration-picker.md)). Old Hub Settings links open the matching modal over Hub ([hub settings open as modals](docs/adr/2026-11-01-1221-hub-settings-open-as-modals.md)).
|
|
145
157
|
_Avoid_: Hub Settings page, preferences, hub config
|
|
146
158
|
|
|
159
|
+
**Shared person**:
|
|
160
|
+
Someone else signed in to Tailscale whose login a board's Sharing lists: they see that board in a shell whose sidebar lists only the boards shared with them, and open its Visit links; the rest of the hub refuses them ([a board is shared view only with a Tailscale login](docs/adr/2026-11-05-2215-a-board-is-shared-view-only-with-a-tailscale-login.md)). Each is **View**, looking only, or **Full**, also answering, writing in threads, attaching files, tapping card buttons and adding New tasks, named in the thread; Merge and Board settings stay the owner's at both ([a shared person is View or Full](docs/adr/2026-11-05-1912-a-shared-person-is-view-or-full.md)).
|
|
161
|
+
_Avoid_: guest, viewer, collaborator
|
|
162
|
+
|
|
147
163
|
**Board Settings**:
|
|
148
|
-
The centred modal opened from a board header’s gear, at every width, which scrolls inside on a phone. It contains only that board’s settings: repo and branch (Change uses the same list and GitHub link search as New board), ticket source, auto-merge, auto-build, auto-pull (Auto implement Todo cards) with Maximum parallel implementers, auto-triage, reviewers, rules and Close board with typed-name confirmation. Closing returns to the same board and open card without another history entry ([hub settings expand in place and board settings open in a modal](docs/adr/2026-10-31-1721-hub-settings-expand-in-place-and-board-settings-open-in-a-modal.md)).
|
|
164
|
+
The centred modal opened from a board header’s gear, at every width, which scrolls inside on a phone. It contains only that board’s settings: **Pause board** first, then repo and branch (Change uses the same list and GitHub link search as New board), ticket source, auto-merge, auto-build, auto-pull (Auto implement Todo cards) with Maximum parallel implementers and planners, auto-triage, reviewers, sharing, rules and Close board with typed-name confirmation. Closing returns to the same board and open card without another history entry ([hub settings expand in place and board settings open in a modal](docs/adr/2026-10-31-1721-hub-settings-expand-in-place-and-board-settings-open-in-a-modal.md)).
|
|
149
165
|
_Avoid_: Settings page
|
|
150
166
|
|
|
151
167
|
**Codex setting**:
|
|
@@ -171,11 +187,11 @@ A board whose session and server have stopped and whose sidebar row is gone, wit
|
|
|
171
187
|
_Avoid_: deleted board, archived board
|
|
172
188
|
|
|
173
189
|
**Hub links**:
|
|
174
|
-
What the hub owes a board, each passing or broken: GitHub polling (not on a board on a plain git remote), the repo fetch (on a board with a repo, the hub's last `git fetch` of it worked; when it failed, git's error line and the fix, such as `gh auth setup-git`, or `git ls-remote <link>` on a plain git remote), events (the board is **listening**), daily wakes and reviewer links; whether a device gets pushes is the Notifications integration, not a hub link ([the hub reads Healthy, Degraded or a site down, and notifications leave the board links](docs/adr/2026-11-03-0501-the-hub-reads-healthy-degraded-or-a-site-down.md)). The hub link (the hub runs the code in its files) is the hub's own, shown in amber only on the sidebar's Hub row and the hub page's Health card ([every builder works in a worktree, and the hub's own fault shows once](docs/adr/2026-10-30-1654-every-builder-works-in-a-worktree.md)). The In Review header's GitHub mark, or on a plain git remote the branch mark beside its host/path, opens them as a sheet, red-dotted only while one stays broken past its grace period; until then it is **settling** ([hub links turn red only after a grace period](docs/adr/2026-10-29-1639-hub-links-turn-red-only-after-a-grace-period.md)). A new board tests them with a **handshake**: a `
|
|
190
|
+
What the hub owes a board, each passing or broken: GitHub polling (not on a board on a plain git remote), the repo fetch (on a board with a repo, the hub's last `git fetch` of it worked; when it failed, git's error line and the fix, such as `gh auth setup-git`, or `git ls-remote <link>` on a plain git remote), events (the board is **listening**), daily wakes and reviewer links; whether a device gets pushes is the Notifications integration, not a hub link ([the hub reads Healthy, Degraded or a site down, and notifications leave the board links](docs/adr/2026-11-03-0501-the-hub-reads-healthy-degraded-or-a-site-down.md)). The hub link (the hub runs the code in its files) is the hub's own, shown in amber only on the sidebar's Hub row and the hub page's Health card ([every builder works in a worktree, and the hub's own fault shows once](docs/adr/2026-10-30-1654-every-builder-works-in-a-worktree.md)). The In Review header's GitHub mark, or on a plain git remote the branch mark beside its host/path, opens them as a sheet, red-dotted only while one stays broken past its grace period; until then it is **settling** ([hub links turn red only after a grace period](docs/adr/2026-10-29-1639-hub-links-turn-red-only-after-a-grace-period.md)). A new board tests them with a **handshake**: a `ping` event the session's watcher answers itself, with a Connecting checklist on the board until the watcher answered and GitHub checks reach it, the GitHub step left out on a plain git remote ([one board registry for every hub feature](docs/adr/2026-10-29-1639-one-board-registry-for-every-hub-feature.md)).
|
|
175
191
|
_Avoid_: health, status, integrations
|
|
176
192
|
|
|
177
193
|
**Change signal**:
|
|
178
|
-
The board server's note on its `api/stream` that a file the board reads changed; the hub passes it on as `change {route}` on its one stream, and an open board reloads at once, naming the
|
|
194
|
+
The board server's note on its `api/stream` that a file the board reads changed; the hub passes it on as `change {route}` on its one stream, and an open board reloads at once, naming the **change number** it shows, so a changed board comes as a patch of the cards, questions and topics that changed after it ([the board sends per-card patches](docs/adr/2026-11-04-0332-the-board-sends-per-card-patches.md), [the board syncs by change number](docs/adr/2026-11-05-1819-the-board-syncs-by-change-number.md)). The header's time counts from the last one that brought something new, or the last ↻ tap ([the board reloads on a change signal](docs/adr/2026-10-29-1639-the-board-reloads-on-a-change-signal.md)).
|
|
179
195
|
_Avoid_: push (a push is a notification from the hub), live update
|
|
180
196
|
|
|
181
197
|
**Owner tap**:
|
|
@@ -195,7 +211,7 @@ One step of a **lineup**: a set of its cards that build side by side, each block
|
|
|
195
211
|
_Avoid_: stage, batch; a builder's phase (reading, building, …) is its progress, not this
|
|
196
212
|
|
|
197
213
|
**Wave band**:
|
|
198
|
-
A wave shown inside Todo: one band per open **lineup**, then on a board over `~/.claude/waves` one per unfinished wave file, above Todo's cards in no wave ("
|
|
214
|
+
A wave shown inside Todo: one band per open **lineup**, then on a board over `~/.claude/waves` one per unfinished wave file, above Todo's cards in no wave ("No wave"; every other lane groups its cards by wave too, a header per wave with cards there and its x/y/k/z counts across lanes, [docs/adr/2026-11-05-0215-every-lane-groups-its-cards-by-wave.md](docs/adr/2026-11-05-0215-every-lane-groups-its-cards-by-wave.md)). Its head reads its name (the goal as its tooltip, or a long-press popover), its Todo count and its started cards, then "Notes ↗" (a wave file has none), then Implement for a lineup's next card when it is ready, else "next: #N <why not>". Open, it lists its Todo cards in wave order with step numbers, one per phase, and a ⋯ menu that swaps a card with the Todo card above or below, each taking the other's phase, after one "N done" line. A lineup's next card is its first ready Todo card, so a phase's ready cards take Implement in turn. Only the first band with a ready next card starts open ([waves are bands in Todo, each with its next card's Implement](docs/adr/2026-11-03-1840-waves-are-bands-in-todo.md)).
|
|
199
215
|
_Avoid_: Waves section, wave bars, wave filter, pills
|
|
200
216
|
|
|
201
217
|
**Wave triage**:
|
|
@@ -203,15 +219,15 @@ Claude reading the code for a lineup's unstarted cards and proposing to split, m
|
|
|
203
219
|
_Avoid_: grooming, refinement
|
|
204
220
|
|
|
205
221
|
**Architecture review**:
|
|
206
|
-
Claude reviewing a board's repo, chosen by `hub/board-repo.mjs` `boardRepo`, with the mattpocock skills: the bulb
|
|
222
|
+
Claude reviewing a board's repo, chosen by `hub/board-repo.mjs` `boardRepo`, with the mattpocock skills: the bulb at the foot of the board, beside the gear, opens a sheet with the last review and Run, which confirms. The board server makes a **lineup** "Architecture <date>", or on a board over `~/.claude/waves` a wave file of its own, whose first card is its audit card, and wakes the session with `arch-review`. The bulb glows orange while the audit card is open with no question yet. The audit card's Notes are the report, and it asks one question per finding, with possible solutions and Skip; each finding not skipped becomes a card after it. One review is open at a time, so Run while one is open opens its audit card. A board on the running kickflip clone, as the hub board is, has its review cover kickflip's code, the board template and the model, reading the live data only for its shapes. It waits, saying why, while a skill it follows isn't installed ([the bulb runs an architecture review of the board's repo](docs/adr/2026-11-02-1813-the-bulb-runs-an-architecture-review-of-the-boards-repo.md)).
|
|
207
223
|
_Avoid_: improvements round, audit (for the whole review), bulb round
|
|
208
224
|
|
|
209
225
|
**Reviewers**:
|
|
210
|
-
The people who get a board's PR links once they are ready, and the weekday digest. Each board keeps its own in `board.json`, which its Settings modal lists, and a new wave copies them into its own `reviewers`.
|
|
226
|
+
The people who get a board's PR links once they are ready, and the weekday digest. Each board keeps its own in `board.json`, which its Settings modal lists, and a new wave copies them into its own `reviewers`. The board server writes both an add and a remove: an add picks a Slack member and a GitHub login from lists it fetches with the hub's Slack token and `gh`, and the server opens the DM ([the server adds reviewers from fetched lists](docs/adr/2026-11-05-2100-the-server-adds-reviewers-from-fetched-lists.md), extending [the board server removes reviewers itself](docs/adr/2026-11-04-0119-the-board-server-removes-reviewers-itself.md)). Kickflip owns the sent messages per PR, not per card, in each board's `data/pr-slack.json` `{<owner/repo#n>: {head, links: {<name>: {channel, ts, reactions}}, replies}}`: a card holds 1:m PRs, and each PR has 1:m reviewer DMs sharing one thread and one set of reactions. The card, Stale age, hub Slack link and digest read each reviewer's first link across the card's PRs, with an item's older `review_link_ts` and slack-bridge topic files only as a fallback ([Slack sends hang off PRs and go out from the hub tick](docs/adr/2026-11-07-0300-slack-sends-hang-off-prs-and-go-out-from-the-hub-tick.md)). The hub sends them as the owner, through the Slack user token pasted on Hub settings › Slack and kept in `~/.claude/kickflip/secrets.json` beside Linear's key, opening the owner's DM with each reviewer, and records each message as it posts, so a failed one goes again next poll and a posted one never twice ([the hub sends reviewer Slack messages with its own token](docs/adr/2026-11-05-0141-the-hub-sends-reviewer-slack-messages-with-its-own-token.md)). Hub Slack identity lives in `~/.claude/kickflip/slack.json`, read or set by `board.mjs slack`; its timezone sets the weekday 09:00 to 17:00 digest window ([kickflip owns the reviewer record](docs/adr/2026-11-01-2347-kickflip-owns-the-reviewer-record.md)).
|
|
211
227
|
_Avoid_: approvers, watchers
|
|
212
228
|
|
|
213
229
|
**Finished wave**:
|
|
214
|
-
A wave with work items that are all
|
|
230
|
+
A wave with work items that are all in Done. Done shows it as one row that opens to its cards, and its **wave band** leaves Todo ([lists never cut silently](docs/adr/2026-10-29-1639-lists-never-cut-silently.md)).
|
|
215
231
|
_Avoid_: closed wave, archived wave
|
|
216
232
|
|
|
217
233
|
**Work item**:
|
|
@@ -239,7 +255,7 @@ A chip on a card or page that shows a status, such as Install or a PR's state. I
|
|
|
239
255
|
_Avoid_: chip (in what the owner reads), tag, label
|
|
240
256
|
|
|
241
257
|
**Button**:
|
|
242
|
-
A control that acts: it sends something to the board, such as Merge, Hold or Grill, or opens a place to act, such as
|
|
258
|
+
A control that acts: it sends something to the board, such as Merge, Hold or Grill, or opens a place to act, such as Questions. The open card's workflow row holds Merge, Hold or Unhold, the **action button**, Serve or Build when the card has a build script and branch changes and Auto-build is off, and last **Implement** on a Todo card that can start (a held Todo card's Implement takes the place of its Unhold), below the details list whose final line holds Notes, Install and Review on GitHub links in that order ([a card's external links share the last details line](docs/adr/2026-10-30-2008-a-cards-external-links-share-the-last-details-line.md)). A card that can be bumped, every Todo card (held or waiting on the owner included) and a running In Progress one that isn't held, carries its bump as an icon at its top right instead, closed or open, as a New card does (the empty icon always shows on a touch screen and with a mouse only while the card is hovered or has focus; a bumped card's filled one always shows) ([a card that hasn't started, or is running, can be bumped](docs/adr/2026-10-29-1639-a-card-that-hasnt-started-can-be-bumped.md)). It sends with no confirm, and on a bumped card it is filled orange and unbumps (`card-unbump {key}`) ([Build on a blocked card queues it, and blocked, bumped and Action needed leave the badges](docs/adr/2026-11-03-0301-build-on-a-blocked-card-queues-it.md)). The control that clears the card's **Action needed** is orange.
|
|
243
259
|
_Avoid_: badge, pill (a pill is only a look)
|
|
244
260
|
|
|
245
261
|
**Badge tone**:
|
|
@@ -263,7 +279,7 @@ The one card a work item was spun out of, or none: set when a card is created fr
|
|
|
263
279
|
_Avoid_: filed from, origin, epic
|
|
264
280
|
|
|
265
281
|
**Related to**:
|
|
266
|
-
Similar cards that should be cross-referenced,
|
|
282
|
+
Similar cards that should be cross-referenced, shown on both cards. The session links a new card in the call that files it: `item set --relate` adds links, `--unrelate` takes them off on both cards, and `--related` replaces the list. Planner and builder briefs list a card's Related to, Parent and deps with their notes, for context ([the orchestrator links a new card when it files it](docs/adr/2026-11-05-0130-the-orchestrator-links-a-new-card-when-it-files-it.md)). It neither blocks nor orders anything; Blocked by does that ([cards wait on explicit blocked-by links](docs/adr/2026-10-29-1639-cards-wait-on-explicit-blocked-by-links.md)).
|
|
267
283
|
_Avoid_: sibling, link (alone)
|
|
268
284
|
|
|
269
285
|
**Plan waves**:
|
|
@@ -275,11 +291,11 @@ _Avoid_: backlog item, todo
|
|
|
275
291
|
_Avoid_: history, old cards
|
|
276
292
|
|
|
277
293
|
**Lane**:
|
|
278
|
-
Where a card sits (In Review, Stale, In Progress, Todo, Done, Asks), set by who acts next ([the lane follows who acts next, and a card waiting on the owner says Action needed](docs/adr/2026-10-29-1639-the-lane-follows-who-acts-next.md)). In Progress means a card is building: a running build agent, a **checking** item, or a ready PR whose CI is red, or a red draft on a board that **skips the draft**. A work card
|
|
294
|
+
Where a card sits (In Review, Stale, In Progress, Todo, Done, Asks), set by who acts next ([the lane follows who acts next, and a card waiting on the owner says Action needed](docs/adr/2026-10-29-1639-the-lane-follows-who-acts-next.md)). In Progress means a card is building: a running build agent, a **checking** item, or a ready PR whose CI is red, or a red draft on a board that **skips the draft**. A work card stores its **lane** (todo, progress, review, done, with `lane_at`), which one writer moves with a "Moved to <lane>: <why>" thread line; a card has no status, and held, blocked, merged and dropped are facts beside the lane ([a card stores its lane, and facts replace statuses](docs/adr/2026-11-07-1400-a-card-stores-its-lane-and-facts-replace-statuses.md)). A work card that has left Todo never drops back to it unless held or blocked ([a card moves to In Progress only once building starts](docs/adr/2026-11-03-0202-a-card-moves-to-in-progress-only-once-building-starts.md)). A running grill or prototype agent shows its status line but leaves the card where it is. In Review means finished work waits on a person: the reviewers, or the owner's review of a draft ("Review draft PR #n", whatever its CI), Merge, manual steps or the Done of an ask (see **Action needed**), or of a reopened card. An owner message or a new question on a Done card, merged or not, reopens it: In Progress until Claude answers, then In Review until the owner's Done, its next step "Tap Done once it is settled" ([a message or question on a Done card reopens it until the owner's Done](docs/adr/2026-11-02-1952-a-message-or-question-on-a-done-card-reopens-it.md), [a merged card reopens on a message, and its PR badge shows the PR's state](docs/adr/2026-11-03-1843-a-merged-card-reopens-and-its-pr-badge-shows-the-prs-state.md), [a card waiting only to be closed has no Action needed](docs/adr/2026-11-03-0137-a-card-waiting-only-to-be-closed-has-no-action-needed.md)). A card waiting only on those moves there from In Progress; one Claude still works on stays in In Progress. A card with several PRs, in any repos, sits where its least-ready PR puts it, shows a PR badge for each, and is Done once every PR has merged or closed with at least one merged ([a card holds several PRs across repos](docs/adr/2026-11-03-1904-a-card-holds-several-prs-across-repos.md)). Todo holds work that hasn't started building: the New cards, which wait on Claude ([the + makes a New card, which Claude files, folds or answers](docs/adr/2026-10-29-1639-the-plus-makes-a-new-card.md)), and every work card with no build yet, where its **Implement** shows. Discussion keeps a card there: open questions or a prototype pick, with Action needed, answered or resolved questions, grill and prototype agents, a working mark on a message in its thread and a prototype recorded for it ([a card moves to In Progress only once building starts](docs/adr/2026-11-03-0202-a-card-moves-to-in-progress-only-once-building-starts.md)). A started card that gets a question keeps its lane ([an unstarted card waits on its questions in Todo, and its one action button follows what it waits on](docs/adr/2026-10-30-1309-an-unstarted-card-waits-on-its-questions-in-todo.md)). Each lane has one fixed order, with no sort menu ([each lane has one fixed order](docs/adr/2026-11-03-0223-each-lane-has-one-fixed-order.md)): Todo lists its New cards first, oldest first, then its bumped cards, the latest bump on top ([a card that hasn't started, or is running, can be bumped](docs/adr/2026-10-29-1639-a-card-that-hasnt-started-can-be-bumped.md)), then the rest oldest made first, so a new card joins the bottom ([new Todo cards join the bottom, so old ones leave first](docs/adr/2026-11-05-2345-new-todo-cards-join-the-bottom.md)); In Progress, its bumped cards first, then by when each came into the lane, its reopening or its latest build agent's start, the newest arrival on top; In Review and Stale by when the PR was first sent to a reviewer, the newest on top; Done by when each card closed, the most recent on top; Asks, the answered asks in their own lane below Done, by when Claude answered, the newest on top. Done and Asks each show 10 cards, then a Show more, the thread's, that adds 10 and says how many are left; a card the owner has open stays shown ([answered asks have their own section below Done, and Done and Asks show 10 cards at a time](docs/adr/2026-11-03-0259-answered-asks-have-their-own-section-below-done.md)). Every card, a New card included, ends with one muted line holding the time its lane sorts by: the time only today, the day too before today ("10/31, 2:49 PM"), and the year too past 365 days. A card with no such time has no time on that line.
|
|
279
295
|
_Avoid_: column, status (status is the item's own field)
|
|
280
296
|
|
|
281
297
|
**Checking**:
|
|
282
|
-
The item status a builder's `builder done` sets when it hands back finished work with unverified judgment calls, including one naming why it couldn't finish. The card sits in In Progress reading "Orchestrator review" while the owning session verifies the calls; its `builder verified` **finishes** the card ([finishing a build is one step](docs/adr/2026-11-04-1611-finishing-a-build-is-one-step.md)). Only
|
|
298
|
+
The item status a builder's `builder done` sets when it hands back finished work with unverified judgment calls, including one naming why it couldn't finish. The card sits in In Progress reading "Orchestrator review" while the owning session verifies the calls; its `builder verified` **finishes** the card ([finishing a build is one step](docs/adr/2026-11-04-1611-finishing-a-build-is-one-step.md)). Only a card in Done unblocks dependents ([site cards build in parallel when their files don't overlap](docs/adr/2026-10-29-1639-site-cards-build-in-parallel-when-their-files-dont-overlap.md), [the board records what it knows, and commands make the rule calls](docs/adr/2026-11-03-0003-the-board-records-what-it-knows-and-commands-make-the-rule-calls.md)).
|
|
283
299
|
_Avoid_: verifying, in QA, review (review is the reviewers' part)
|
|
284
300
|
|
|
285
301
|
**Stale**:
|
|
@@ -295,7 +311,7 @@ Who the card is waiting for: the owning session's check, the owner's Ready, the
|
|
|
295
311
|
_Avoid_: blocked by, assignee
|
|
296
312
|
|
|
297
313
|
**Card state**:
|
|
298
|
-
What a card made from a **New task** does next,
|
|
314
|
+
What a card made from a **New task** does next: **grilling** (questions on the card), **prototyping** (takes on the card), **staging** (the owner has acted: a Send that left it nothing open, an Implement, or a Reply on a ready card, whose words the board wrote into its notes; the orchestrator judges it) or **ready** (its notes leave the owner nothing to decide, so it can be built; the plan lives only in the notes). Only the board sets staging; the session sets the others with `item set --state`, and ready only from staging, or on an Implement ask it files. A question added on a ready or staging card moves it to grilling. Moving a staging or ready card back to grilling or prototyping starts that round from code ([staging, then ready](docs/adr/2026-11-07-0700-staging-then-ready.md)). The board enforces the four: `--state` refuses any other, and ready while the card has an open question. Until it has one, the card reads New beside its ticket id and is never pulled. So does a card an agent added with `item add` and no `--state`, which a `card-added` event hands the session to link and file ([the orchestrator links a new card when it files it](docs/adr/2026-11-05-0130-the-orchestrator-links-a-new-card-when-it-files-it.md)). A Ready card's time line reads a green "ready" in Action needed's place ("10:26 · held · ready · 2 new messages") while nothing blocks it and nothing waits on the owner, and the idle pull takes it like any settled card; a staging card reads an orange "staging" there and is never pulled ([a new card is ready, grilling or prototyping, and reads ready in green when it is](docs/adr/2026-11-03-0516-a-new-card-is-ready-grilling-or-prototyping.md)).
|
|
299
315
|
_Avoid_: triage state, status (the wave entry's `status` is a different field)
|
|
300
316
|
|
|
301
317
|
**Action needed**:
|
|
@@ -303,12 +319,16 @@ The orange words last among the orange ones on a card's time line ("10:26 · hel
|
|
|
303
319
|
_Avoid_: open items, needs you (Needs you is the box at the top of the board)
|
|
304
320
|
|
|
305
321
|
**Request**:
|
|
306
|
-
The owner's ask for a grill or a
|
|
322
|
+
The owner's ask for a grill, a prototype or a **visual** on a card: the thread composer's fire, eye or image, each sending at once, or /grill, /prototype or /visual typed in the box on Reply, sending `grill-more`, `prototype-request` or `visual-request` with whatever was typed; a question's own eye on Waiting on you asks for a prototype of that question. A request with nothing typed is one gray **status line** in the thread, "Grill requested", "Prototype requested" or "Visual requested", keyed `grill`, `prototype` or `visual` as every button without a text box keys its line ([a button without a text box posts a keyed status line](docs/adr/2026-11-06-0021-a-button-without-a-text-box-posts-a-keyed-status-line.md)); one with text is the owner's message carrying it, with that status in the message's footer, and "Waiting for Claude…" to its right until Claude picks it up. An answer submitted from Waiting on you is likewise a message whose footer reads "answers submitted". A question asked for a prototype reads "prototype requested", locked, until a question naming it in `round_of` resolves it, and `question resolve` refuses it; a prototype request still waiting 30 minutes on with no prototype agent running comes back to the session as `prototype-overdue` ([a button tap is a status line or a message footer](docs/adr/2026-11-04-2130-a-button-tap-is-a-status-line-or-a-message-footer.md), [a prototype request waits for its prototype](docs/adr/2026-11-04-2130-a-prototype-request-waits-for-its-prototype.md)).
|
|
307
323
|
_Avoid_: Grill button, Prototype button (on a card)
|
|
308
324
|
|
|
325
|
+
**Visual**:
|
|
326
|
+
A one-off HTML page that answers the owner in a card's thread visually, such as a diagram, a flow or a comparison. It is not a prototype or a grill: it asks no question, has no takes and leaves the card as it was. The thread's image or /visual (a **request**) has the board launch a headless visual agent on Sonnet. The agent runs beside any other agent on the card, as its own record `visual-<request id>`. Its page goes in with `visual add`, to `public/visuals/<card id>/<slug>.html`, a new page each time. The page shows in the thread as a link line, "<title> →", that opens it full page. A card's visual requests are drawn one after another ([a visual is a page an agent draws for a thread](docs/adr/2026-11-05-1921-a-visual-is-a-page-an-agent-draws-for-a-thread.md)).
|
|
327
|
+
_Avoid_: diagram (one kind of visual), prototype (takes for a decision)
|
|
328
|
+
|
|
309
329
|
**Action button**:
|
|
310
|
-
The open card's one workflow button, which `board/domain.mjs` picks as the card's `actionButton`: **
|
|
311
|
-
While the card carries **Action needed**, the button that clears it is orange, in the notice color: the card's `resolvedBy` from `board/domain.mjs`, by the action's kind. A question or a pick makes
|
|
330
|
+
The open card's one workflow button, which `board/domain.mjs` picks as the card's `actionButton`: **Questions** (`openQuestions`) while it has open questions or a prototype pick, opening the first; otherwise none; an ask waiting on the owner's Done has it in its thread box, beside Reply. A grill or prototype is asked for from the thread's fire and eye (**request**), and the card reads a grey "preheating" while a grill or prototype request waits for its planner (not yet replied to, no questions posted on the card after it, and no planner of its kind started after it finished), then a planner line "grilling" or "prototyping" in its lane's colour once that planner runs ([a card's status word comes from a signal the board checks](docs/adr/2026-11-05-0410-a-card-status-word-comes-from-a-signal-the-board-checks.md)) ([a new card is ready, grilling or prototyping, and reads ready in green when it is](docs/adr/2026-11-03-0516-a-new-card-is-ready-grilling-or-prototyping.md)). A Done card has none ([an unstarted card waits on its questions in Todo, and its one action button follows what it waits on](docs/adr/2026-10-30-1309-an-unstarted-card-waits-on-its-questions-in-todo.md)). **Prototypes** follows it on any card with a question on a prototype page, Done cards too, opening the viewer on its latest round: solid orange while one of those questions is open, plain otherwise ([prototypes have their own button and a full-bleed viewer](docs/adr/2026-11-07-0300-prototypes-have-their-own-button-and-viewer.md)).
|
|
331
|
+
While the card carries **Action needed**, the button that clears it is orange, in the notice color: the card's `resolvedBy` from `board/domain.mjs`, by the action's kind. A question or a pick makes Questions orange (a pick makes Prototypes orange too), the Done of an ask makes the thread's Done orange (`BUTTON.done`), a green draft's Ready or manual steps make Review on GitHub orange, and an approved PR's Merge makes Merge orange. A held card's Questions stay plain. A reopened card waiting only on the owner's Done has its thread's Done primary, in the accent color ([a card waiting only to be closed has no Action needed](docs/adr/2026-11-03-0137-a-card-waiting-only-to-be-closed-has-no-action-needed.md)).
|
|
312
332
|
The button names (`BUTTON`: the action buttons, `github` and `merge`) and the action kinds (`ACTION_KIND`) are two frozen enums in `board/public/ui-enums.js`, which the page loads as a script and `board/domain.mjs` runs in a vm context; code compares against their members, never a bare string.
|
|
313
333
|
_Avoid_: Open items, Action needed (the badge)
|
|
314
334
|
|
|
@@ -321,13 +341,18 @@ _Avoid_: merge rule, merge policy
|
|
|
321
341
|
|
|
322
342
|
A card with no PR lands the same way: with Auto-merge off its builder's `done` stops after the tests, and the card waits in In Review with a Merge button; the tap makes the board server rebase it onto main as it is now, rerun the tests and land it, sending a conflict or a failing test to a headless lander ([a land waits for your Merge](docs/adr/2026-11-04-2100-a-land-waits-for-your-merge.md)).
|
|
323
343
|
|
|
324
|
-
**
|
|
325
|
-
|
|
326
|
-
_Avoid_:
|
|
344
|
+
**Rebase run**:
|
|
345
|
+
The headless run the board server starts on a card whose open PR, draft or ready, GitHub reads CONFLICTING, once per head and base: in the card's worktree, or one made from the PR's branch, it rebases onto the board's branch, reruns the suite and finishes with `builder done`, which force-pushes the PR's branch with a lease and leaves the PR as it is. The card stays In Review, its status line the run's; one it can't resolve hands the card back with a judgment call, to the orchestrator before the owner. A merge counts the run's push after an approval as trivial when it only replayed the PR's commits, and says so. The GitHub tick no longer rebases ([the board rebases a conflicting PR with a headless run](docs/adr/2026-11-06-0200-the-board-rebases-a-conflicting-pr-with-a-headless-run.md)).
|
|
346
|
+
_Avoid_: rebase lander, conflict fix
|
|
347
|
+
|
|
348
|
+
**Orchestrator stop**:
|
|
349
|
+
The orchestrator's stop of a run the board launched on a card, with every process under it: `board.mjs builder stop` for its headless builder, lander or rebase run, `board.mjs land stop` for its land, the suite included. A stopped build stays In Progress, waiting on the orchestrator, and nothing relaunches it; a stopped Merge land leaves the land queue and the card's Merge shows again. The card's status line and thread line read the stop in one pattern, "build stopped by orchestrator" or "land stopped by orchestrator". A bump, the owner's or the orchestrator's `item bump`, puts the card's land ahead in the land queue without stopping the one running ([the orchestrator stops the board's own runs](docs/adr/2026-11-05-1809-the-orchestrator-stops-the-boards-own-runs.md)).
|
|
350
|
+
_Avoid_: kill, cancel, Stopped (the status), land first
|
|
327
351
|
|
|
328
|
-
**
|
|
329
|
-
A board
|
|
330
|
-
|
|
352
|
+
**Landing**:
|
|
353
|
+
A board's one choice of how a card lands, a section above Auto in Board settings, shown on a GitHub board that builds in its own clone and on the hub board, which starts on Merge (no other local board shows it): **Draft PR** (each card opens a draft PR and waits for the owner to mark it ready), **Ready PR** (the hub's GitHub check marks the draft ready for review once its CI passes) or **Merge** (no PR opens; each card lands on the board's base branch, which is pushed, and turning it on needs Push main granted, except on the hub board). On a PR mode the hub board's builders branch from origin's base branch in its folder and each finish opens a PR; on Merge they branch from the folder's own base branch and land there, pushing it only with Push main granted. Reviewers show only while cards open PRs. The words never say "main", whatever the base branch. **Auto-merge** stays its own switch and covers both: merging an approved PR, and landing a build that waits to merge into the base branch ([Landing is one choice](docs/adr/2026-11-05-0200-landing-is-one-choice-draft-pr-ready-pr-or-merge.md), [the hub board shows Landing](docs/adr/2026-11-05-1100-the-hub-board-shows-landing-and-defaults-to-merge.md)).
|
|
354
|
+
It is stored as two `board.json` settings, read together: `prs`, on unless set (off is Merge), and `skip_draft`, off unless set (on is Ready PR); `board.mjs settings set prs|skip-draft` sets each. With no reviewers on the board a PR merges once it is green and clean, with no approval ([a land waits for your Merge](docs/adr/2026-11-04-2100-a-land-waits-for-your-merge.md), [a board can skip the draft](docs/adr/2026-11-04-1913-a-board-can-skip-the-draft.md)).
|
|
355
|
+
_Avoid_: PRs switch, Skip the draft, PR mode, no-PR mode, auto-ready
|
|
331
356
|
|
|
332
357
|
**Review on GitHub**:
|
|
333
358
|
The open card's link to its PR, on every card with an open PR, last on the details list's final line after Notes and Install when present. It reads "Review draft on GitHub ↗" on a draft and "Review on GitHub ↗" once ready, with no PR number, and is orange while a green draft's Ready or manual steps wait on the owner ([a card's external links share the last details line](docs/adr/2026-10-30-2008-a-cards-external-links-share-the-last-details-line.md)).
|
|
@@ -338,7 +363,7 @@ The app card's one badge that opens its build on the owner's phone, or the badge
|
|
|
338
363
|
_Avoid_: download, TestFlight (a different channel), older build
|
|
339
364
|
|
|
340
365
|
**Build script**:
|
|
341
|
-
The repo's reviewed, executable `.kickflip/build`, run by the hub from each card's worktree and main's hub-owned detached worktree. The hub passes the key (or `main`) and worktree, plus `KICKFLIP_BOARD`. Websites serve at their root on their own Tailscale HTTPS port, without a path prefix or `KICKFLIP_BASE` ([a try build serves on its own Tailscale port](docs/adr/2026-11-01-2254-a-try-build-serves-on-its-own-tailscale-port.md)). Printing `port <n>` and staying alive serves a website; exiting 0 without a port finishes an app build that publishes an install through the board CLI. The last finished run decides the board's kind. The hub writes try state and logs; failed card runs append one thread line, and successful runs none. There is no script path setting ([a board's build script serves or builds each card and main](docs/adr/2026-11-01-1846-a-boards-build-script-serves-or-builds-each-card-and-main.md)).
|
|
366
|
+
The repo's reviewed, executable `.kickflip/build`, or `.kickflip/build-<target>` when Board Settings' Build target names one, run by the hub from each card's worktree and main's hub-owned detached worktree. One repo can hold several targets, such as `build-web` and `build-ios`; each board runs one, and main builds the same target as its cards. The hub passes the key (or `main`) and worktree, plus `KICKFLIP_BOARD`. Websites serve at their root on their own Tailscale HTTPS port, without a path prefix or `KICKFLIP_BASE` ([a try build serves on its own Tailscale port](docs/adr/2026-11-01-2254-a-try-build-serves-on-its-own-tailscale-port.md)). Printing `port <n>` and staying alive serves a website; exiting 0 without a port finishes an app build that publishes an install through the board CLI. The last finished run decides the board's kind. The hub writes try state and logs; failed card runs append one thread line, and successful runs none. There is no script path setting: the board's `build_target` picks among the repo's `.kickflip/build-*` scripts, and with none the hub runs `.kickflip/build` ([a board's build script serves or builds each card and main](docs/adr/2026-11-01-1846-a-boards-build-script-serves-or-builds-each-card-and-main.md), [Board Settings picks which build script a board runs](docs/adr/2026-11-05-1823-board-settings-picks-which-build-script-a-board-runs.md)).
|
|
342
367
|
_Avoid_: install script, session install runner
|
|
343
368
|
|
|
344
369
|
**Serve**:
|
|
@@ -350,23 +375,15 @@ The board's `auto_build` setting (the key keeps its name), labelled "Auto serve"
|
|
|
350
375
|
_Avoid_: Auto-build, build rule
|
|
351
376
|
|
|
352
377
|
**Implement**:
|
|
353
|
-
The orange Implement last in the open card's workflow row, on a work card still unstarted in Todo, held or not, blocked or not, that has no **Action needed**: the card's `buildable` from `board/domain.mjs`. Its confirm reads "Implement #92? Claude starts its implementer now with the notes as they stand." Owner-facing words call a card's agent an implementer and its `building` status implementing, so Build, Serve and Install only mean the package of a worktree or main; the code keeps `buildable`, `card-build`, the `building` status and builder records ([a Todo card's button reads Implement, and Build and Serve only mean the package](docs/adr/2026-11-03-1549-a-todo-cards-button-reads-implement.md)). On a blocked card it
|
|
378
|
+
The orange Implement last in the open card's workflow row, on a work card still unstarted in Todo, held or not, blocked or not, that has no **Action needed**: the card's `buildable` from `board/domain.mjs`. Its confirm reads "Implement #92? Claude starts its implementer now with the notes as they stand." Owner-facing words call a card's agent an implementer and its `building` status implementing, so Build, Serve and Install only mean the package of a worktree or main; the code keeps `buildable`, `card-build`, the `building` status and builder records ([a Todo card's button reads Implement, and Build and Serve only mean the package](docs/adr/2026-11-03-1549-a-todo-cards-button-reads-implement.md)). On a blocked card it bumps the card, which stays in Todo reading "waits on #53" with the thread line "Can’t start yet: waits on #53. Bumped to the top of Todo.", its confirm "Implement #92 once #53 is done? It is bumped to the top of Todo until then." ([Todo has no queue](docs/adr/2026-11-05-0802-todo-has-no-queue.md)). The tap starts its build whatever runs: **Maximum parallel implementers** limits only **Auto-pull** ([Todo has no queue](docs/adr/2026-11-05-0802-todo-has-no-queue.md)). On a held card it reads "Unhold and implement" in its confirm and the board server clears the hold as Unhold does before the start; a held card outside Todo keeps Unhold ([a held Todo card shows Build in place of Unhold](docs/adr/2026-11-03-0234-a-held-todo-card-shows-build-in-place-of-unhold.md)). It confirms, sends `card-build {key}` and reads "Starting…" while the board server starts the build: the refusals, the builder pick, the worktree and the building mark that `builder start --kind build --worktree` makes. Started, the card is in In Progress reading "starting" until its implementer's first status line, its Next cleared, and the server launches the builder itself, Claude or Codex, from the card's notes, with the thread line "Builder launched on <model> in <worktree>, session <id>." linking its log; no event wakes the session ([the hub launches every agent from the card](docs/adr/2026-11-04-2130-the-hub-launches-every-agent-from-the-card.md)). Every builder, lander and planner starts through one adapter, which records the agent's session id on the card's builder record ([one adapter launches Claude or Codex](docs/adr/2026-11-05-0128-one-adapter-launches-claude-or-codex.md)). A launch that fails puts the card back in Todo showing **Couldn't start implementing**. Refused, the card stays in Todo showing **Couldn't start implementing** ([a Todo card that nothing blocks has Build](docs/adr/2026-11-02-1745-a-todo-card-that-nothing-blocks-has-build.md), [a Build tap starts the build in the board server](docs/adr/2026-11-03-0219-a-build-tap-starts-the-build-in-the-board-server.md), [a card reads starting from its tap, with one dispatched mark](docs/adr/2026-11-03-1718-a-card-reads-starting-from-its-tap-with-one-dispatched-mark.md)). It isn't an app's Build, which runs the **build script**.
|
|
354
379
|
_Avoid_: card Build, go button, start button
|
|
355
380
|
|
|
356
|
-
**Queued section**:
|
|
357
|
-
The one section at the top of Todo that holds the cards waiting for an **implementer slot**: each **Queued build**, and while **Auto-pull** is on every pullable card, ready ones waiting over the cap included. Bumped cards lead it, the latest bump on top; the rest follow oldest first, by the tap's time or else when the card was made, so a card's unbump returns it to that place. Whenever In Progress is under Maximum parallel implementers the board server takes the queue from its top: it starts a Queued build nothing blocks, and starts and launches the build of a ready card. Queued cards take no slot ([In Progress has a Queued section, and the pull takes its top under the cap](docs/adr/2026-11-04-0121-in-progress-has-a-queued-section.md); [Queued sits at the top of Todo](docs/adr/2026-11-04-0150-queued-sits-at-the-top-of-todo.md)).
|
|
358
|
-
_Avoid_: backlog, waiting lane
|
|
359
|
-
|
|
360
|
-
**Queued build**:
|
|
361
|
-
An Implement the owner tapped on a card an unfinished dep blocks: `queued_at` on its wave entry, with no builder record or worktree, and the thread line "Implement queued: it starts once #53 is done." The card sits in Todo's **Queued section**, its time line reading "blocked by #53" in place of a builder line, and once nothing holds or blocks it and it reaches the queue's top with an **implementer slot** free the board server starts the build as the tap would, from the newest main, and launches its builder. `item set` prints `queued build starts: <key>` for it and sends no `card-unblocked`. A start that is refused or fails sends the card back to Todo with **Couldn't start implementing** ([Build on a blocked card queues it, and blocked, bumped and Action needed leave the badges](docs/adr/2026-11-03-0301-build-on-a-blocked-card-queues-it.md)).
|
|
362
|
-
_Avoid_: pending build, waiting build
|
|
363
|
-
|
|
364
381
|
**Couldn't start implementing**:
|
|
365
|
-
The thread line, of kind `build-refused`, the board server writes when it refuses an Implement tap, with the reason in the owner's words: paused, or a noted prototype pick that waits on its confirm, or why a
|
|
382
|
+
The thread line, of kind `build-refused`, the board server writes when it refuses an Implement tap, with the reason in the owner's words: paused, or a noted prototype pick that waits on its confirm, or why a build ready released couldn't start, or a builder launch that failed ("the launch failed (<reason>). Tap Implement to try again."). The Todo card shows it in its status line while it is the card's newest line other than a status line ([a Build tap starts the build in the board server](docs/adr/2026-11-03-0219-a-build-tap-starts-the-build-in-the-board-server.md)).
|
|
366
383
|
_Avoid_: Couldn't start the build, build error, failed start
|
|
367
384
|
|
|
368
385
|
**Auto-pull**:
|
|
369
|
-
The board's `auto_pull` setting, off by default, which reads "Auto implement Todo cards" in Board settings' Auto section and turns on or off with no confirmation. On, the board server starts and launches the build of the top **pullable** cards in board order, one per **implementer slot** free, on every board change and at start ([auto implement fills In Progress up to Maximum parallel implementers, on every board change](docs/adr/2026-11-04-0057-auto-implement-fills-in-progress-up-to-a-cap.md)): a pullable card is a Ready, unstarted work card that nothing blocks or holds, with no question open or waiting on Claude, no grill under way and no message a session is working on,
|
|
386
|
+
The board's `auto_pull` setting, off by default, which reads "Auto implement Todo cards" in Board settings' Auto section and turns on or off with no confirmation. On, the board server starts and launches the build of the top **pullable** cards in board order, one per **implementer slot** free, on every board change and at start ([auto implement fills In Progress up to Maximum parallel implementers, on every board change](docs/adr/2026-11-04-0057-auto-implement-fills-in-progress-up-to-a-cap.md)): a pullable card is a Ready, unstarted work card that nothing blocks or holds, with no question open or waiting on Claude, no grill under way and no message a session is working on, taken in Todo's order, bumped first and then oldest first ([the idle pull takes ready cards first, and plans the top card when none is ready](docs/adr/2026-11-03-1631-the-idle-pull-takes-ready-cards-first.md), [a card moves to In Progress only once building starts](docs/adr/2026-11-03-0202-a-card-moves-to-in-progress-only-once-building-starts.md)). The slots are the board's **Maximum parallel implementers** (`max_implementers`, 10 by default, the number beside the switch), less the running implementer agents, one each (a build, a rebase run, a lander, a **helper** that writes), less the pulled cards whose build hasn't started; a running grill or prototype, a read-only helper, an agent blocked on its own helper, and a card waiting in Orchestrator review or on the owner take none ([planners and implementers are two kinds of agent](docs/adr/2026-11-03-1551-planners-and-implementers-are-two-kinds-of-agent.md), [the implementer limit counts agents, and any agent on a card can ask the board for helpers](docs/adr/2026-11-06-0425-the-implementer-limit-counts-agents-and-a-card-spawns-helpers.md)). A helper that writes and is waiting for a slot takes it before the pull, the topmost card's first. New cards are never pulled, nor a card from an ask still New, grilling or prototyping; a Ready one is ([a new card is ready, grilling or prototyping, and reads ready in green when it is](docs/adr/2026-11-03-0516-a-new-card-is-ready-grilling-or-prototyping.md)). It writes "Pulled in: an implementer slot was free." in the card's thread ([an idle board pulls in its top Todo card](docs/adr/2026-11-02-1754-an-idle-board-pulls-in-its-top-todo-card.md)). Busy board or idle, it also launches a grill on each card that **arrives in Todo**: an open work card in Todo not set Ready or held, with no planner record, no grill or prototype asked for and no questions yet, however it was filed. Up to **Maximum parallel planners** (`max_planners`, 3 by default, the number under the implementers) run at once, less the grills and prototypes running; the rest wait in board order. Each gets one grill, never a prototype straight away, and the card's thread reads "Landed in Todo, so the board started its grill." ([every card arriving in Todo is grilled by the board](docs/adr/2026-11-04-2359-every-card-arriving-in-todo-is-grilled-by-the-board.md), [the hub launches every agent from the card](docs/adr/2026-11-04-2130-the-hub-launches-every-agent-from-the-card.md)).
|
|
370
387
|
_Avoid_: auto-start, idle pickup
|
|
371
388
|
|
|
372
389
|
**Auto-triage**:
|
|
@@ -386,19 +403,27 @@ The owning session's understanding of a work item so far: what was asked, what i
|
|
|
386
403
|
_Avoid_: full plan, plan, spec
|
|
387
404
|
|
|
388
405
|
**Held**:
|
|
389
|
-
A work card the owner paused with its Hold button, which opens the shared duration picker: Forever, until the owner taps Unhold, or until a time, its **pick-up time**. Hold and Unhold apply on the board at once, and the board server writes them to the wave file with the owner's thread line ([the CLI and board server do the board's housekeeping](docs/adr/2026-11-02-2044-the-cli-and-board-server-do-the-boards-housekeeping.md)). It doesn't start, and the session stops work on a running one, until it is resumed (a held Todo card's Build resumes and starts it, [a held Todo card shows Build in place of Unhold](docs/adr/2026-11-03-0234-a-held-todo-card-shows-build-in-place-of-unhold.md)) ([the board applies the owner's Hold, Resume and Done at once](docs/adr/2026-11-02-0009-the-board-applies-the-owners-hold-resume-and-done-at-once.md)). The card's last line reads "held" or "held until Wed 9:00 am" after its time. A card that leaves Todo is never still held: any write that takes it out (
|
|
406
|
+
A work card the owner paused with its Hold button, which opens the shared duration picker: Forever, until the owner taps Unhold, or until a time, its **pick-up time**. Hold and Unhold apply on the board at once, and the board server writes them to the wave file with the owner's thread line ([the CLI and board server do the board's housekeeping](docs/adr/2026-11-02-2044-the-cli-and-board-server-do-the-boards-housekeeping.md)). It doesn't start, and the session stops work on a running one, until it is resumed (a held Todo card's Build resumes and starts it, [a held Todo card shows Build in place of Unhold](docs/adr/2026-11-03-0234-a-held-todo-card-shows-build-in-place-of-unhold.md)) ([the board applies the owner's Hold, Resume and Done at once](docs/adr/2026-11-02-0009-the-board-applies-the-owners-hold-resume-and-done-at-once.md)). The card's last line reads "held" or "held until Wed 9:00 am" after its time. A card that leaves Todo is never still held: any write that takes it out (a build's start, a hand-back, `--done`, `--pr`, `--pushed`) clears the hold and its pick-up time, and the board shows held only on a Todo card. Every other action-row button, Unhold included, asks to confirm first, through `B.confirm` (`dialogs.js`).
|
|
390
407
|
_Avoid_: paused, frozen, on hold (as a status name)
|
|
391
408
|
|
|
409
|
+
**Blocked**:
|
|
410
|
+
A work card that waits on something concrete before it can start: other cards (its deps, until each reaches Done), or a condition an agent can check, which the orchestrator clears with `item set --blocked-until ""` once it holds, either with a reason. Its time line reads "blocked by #53" or "blocked until <condition>", then ", <reason>". A time is a hold, never a block ([nothing waiting on the orchestrator is missed](docs/adr/2026-11-05-2358-nothing-waiting-on-the-orchestrator-is-missed.md)). Blocked In Progress, a card goes back to Todo with its builder stopped; blocked In Review, it stays but can't land, its Merge disabled ([a block past Todo bumps a build and holds a land](docs/adr/2026-11-06-0102-a-block-past-todo-bumps-a-build-and-holds-a-land.md)).
|
|
411
|
+
_Avoid_: held (a pause, not a dependency), waits on (who the card waits for)
|
|
412
|
+
|
|
392
413
|
**Pick-up time**:
|
|
393
414
|
When a card held until a time resumes itself: `pick_up_at` in its wave file (`board.mjs item set --pick-up-at`), or the `until` of the owner's newer `card-hold`. Within a minute of it the board server resumes the card, writes a thread line, and sends `card-unblocked {key, until}` unless a dep is unfinished, so it starts on its own once nothing else blocks it ([a card can be held until a time](docs/adr/2026-11-02-1727-a-card-can-be-held-until-a-time.md)). A bump doesn't skip it; resume the card or change the time to start early. It is separate from a Linear due date.
|
|
394
415
|
_Avoid_: due date, reminder, snooze (for a card)
|
|
395
416
|
|
|
396
417
|
**Builder**:
|
|
397
|
-
An agent (Claude Opus, Claude Sonnet, Codex…) working on a work item, which owner-facing words call an implementer ([a Todo card's button reads Implement, and Build and Serve only mean the package](docs/adr/2026-11-03-1549-a-todo-cards-button-reads-implement.md)), with one builder record each (`board.mjs builder … --agent <name>`; the first is `main`). The record holds its label, kind (claude or codex; a record written as opus or sonnet reads as claude with that model), model (opus or sonnet for claude, set by `builder start --model`, which prints "model: Claude Sonnet"), start, ETA and finish, not its progress. Each progress line (`builder progress --phase <phase> "<detail>"`, which needs `--site`) goes only to the card's thread, as a **status line**: a phase, Reading, Building, Testing, Checking or Landing, and a detail of at most 80 characters, refused when longer ("Testing: fix for the scroll jump"; another agent's reads "Codex testing: …"), shown as one line with no bubble. Status lines written before phases stay as written ([a builder status line is a phase and a short detail](docs/adr/2026-11-03-0128-a-builder-status-line-is-a-phase-and-a-short-detail.md)). The card's status line under its title is the thread's newest status line since its earliest running agent started, its phase first ("Testing · fix for the scroll jump · 3m ago"), or "Starting" before the first, with its age, behind a pulsing dot as Orchestrator review and Working on it have, and, once a status line has a phase, five bars at the end of the card's time row, after its unread count, finished phases filled and the current one pulsing, only on an In Progress card while a builder runs ([a building card's phase bars end its time row](docs/adr/2026-11-03-1519-a-building-cards-phase-bars-end-its-time-row.md)), and an optional "ETA about 4:30 pm" line under that (owner ask on INT-76). In the thread every implementer's status line stays orange, dot included, whether its agent is working or done (owner, card INT-77). `builder done` marks the record done and keeps it;
|
|
418
|
+
An agent (Claude Opus, Claude Sonnet, Codex…) working on a work item, which owner-facing words call an implementer ([a Todo card's button reads Implement, and Build and Serve only mean the package](docs/adr/2026-11-03-1549-a-todo-cards-button-reads-implement.md)), with one builder record each (`board.mjs builder … --agent <name>`; the first is `main`). The record holds its label, kind (claude or codex; a record written as opus or sonnet reads as claude with that model), model (opus or sonnet for claude, set by `builder start --model`, which prints "model: Claude Sonnet"), start, ETA and finish, not its progress. Each progress line (`builder progress --phase <phase> "<detail>"`, which needs `--site`) goes only to the card's thread, as a **status line**: a phase, Reading, Building, Testing, Checking or Landing, and a detail of at most 80 characters, refused when longer ("Testing: fix for the scroll jump"; another agent's reads "Codex testing: …"), shown as one line with no bubble. Status lines written before phases stay as written ([a builder status line is a phase and a short detail](docs/adr/2026-11-03-0128-a-builder-status-line-is-a-phase-and-a-short-detail.md)). The card's status line under its title is the thread's newest status line since its earliest running agent started, its phase first ("Testing · fix for the scroll jump · 3m ago"), or "Starting" before the first, with its age, behind a pulsing dot as Orchestrator review and Working on it have, and, once a status line has a phase, five bars at the end of the card's time row, after its unread count, finished phases filled and the current one pulsing, only on an In Progress card while a builder runs ([a building card's phase bars end its time row](docs/adr/2026-11-03-1519-a-building-cards-phase-bars-end-its-time-row.md)), and an optional "ETA about 4:30 pm" line under that (owner ask on INT-76). In the thread every implementer's status line stays orange, dot included, whether its agent is working or done (owner, card INT-77). `builder done` marks the record done and keeps it; with judgment calls on it the record is marked `handed_back`, the fact that replaces the old checking status, until a handover or a close. The thread shows each record as **agent lines** among its messages, with no bubble: "Claude Opus implementer started" (or "Claude Sonnet implementer", "Codex implementer"; the model, not the label, names it, a label's builder reading implementer) at its start, always orange and with its ETA while the agent runs, and "Claude Opus implementer finished" at its finish, the only green one (owner, question `int42-agents-look`, option C; owner ask on INT-63). The session's own thread summary closes the work. A builder is a **planner** or an **implementer**: planners are the grill and prototype agents, which write no output code; every other kind is an implementer. A planner's model defaults to Sonnet for a prototype and Opus for a grill ("Claude Sonnet prototype started"); its status and started lines in the thread are the owner's blue (`--accent`, the one human blue, [one human blue](docs/adr/2026-11-03-1627-one-human-blue.md)), and on the card take the card's lane colour, Todo's grey with grey dashes ([every run takes its lane's colour](docs/adr/2026-11-06-0145-every-run-takes-its-lanes-colour.md)); while a build runs, the build's line wins on the card; and a running planner takes no implementer slot and leaves the board idle ([planners and implementers are two kinds of agent](docs/adr/2026-11-03-1551-planners-and-implementers-are-two-kinds-of-agent.md)). The kind words are for code and ADRs; the screen says what each agent does.
|
|
398
419
|
_Avoid_: worker, bot
|
|
399
420
|
|
|
421
|
+
**Helper**:
|
|
422
|
+
An agent that another agent on a card, or the orchestrator, asks the board for with `board.mjs agent launch <key> --name <n> --task "<t>" [--writes]`. It runs beside the card's build under its own name, and its status lines carry that name ("Tests building: …"). The board server launches it headless on Claude. A read-only one launches at once and takes no implementer slot. One that writes takes a slot, waits for one ahead of the pull, and works in its own worktree off the card's branch, which the card's builder brings in with `agent merge`. It hands back with `builder done --agent <n> --text`, which its spawner reads with `agent wait`; while the spawner waits, it takes no slot ([the implementer limit counts agents, and any agent on a card can ask the board for helpers](docs/adr/2026-11-06-0425-the-implementer-limit-counts-agents-and-a-card-spawns-helpers.md)).
|
|
423
|
+
_Avoid_: subagent (for one the board runs), sub-builder
|
|
424
|
+
|
|
400
425
|
**Dispatched record**:
|
|
401
|
-
A builder record open before its agent runs, marked with who opened it: `dispatched: 'tap'` when the owner's Implement tap (or a
|
|
426
|
+
A builder record open before its agent runs, marked with who opened it: `dispatched: 'tap'` when the owner's Implement tap (or the start of a build ready released) opened it, `dispatched: 'hub'` when the board server opened it to launch a pulled build or a planner (a grill or a prototype) itself, `dispatched: 'session'` when the session ran `builder start --dispatch` right before it launches some other agent. Either way the card's builder line reads "starting" from then until the agent's first status line. The agent's own `builder start` takes it up: the kind, a Claude model and the worktree stay, the record starts again at now and is no longer dispatched. A `--dispatch` on a record the tap opened changes nothing and prints "already open"; a `builder start --agent <other name>` refuses while the tap's main record is open and not taken up. The session never posts "a builder is working" itself ([the session opens the builder record when it dispatches an agent](docs/adr/2026-11-03-0513-the-session-opens-the-builder-record-when-it-dispatches-an-agent.md), [a card reads starting from its tap, with one dispatched mark](docs/adr/2026-11-03-1718-a-card-reads-starting-from-its-tap-with-one-dispatched-mark.md)).
|
|
402
427
|
|
|
403
428
|
**Judgment call**:
|
|
404
429
|
A decision a builder makes that its brief didn't settle, recorded on its builder record as it makes it (`builder call <key> "<call>"`, one plain line), or a "Question: …" it asks the session before building. The thread shows a record's calls as one collapsed entry under its agent lines. The session checks them against the owner's words and the other cards and marks the record **verified** (`builder verified`), which finishes a handed-back build in the same step; finishing refuses while a record on the card has a call after that mark. A builder start on a record with unverified calls resumes that build, calls and worktree kept ([a builder records its judgment calls and the session verifies them before land](docs/adr/2026-11-03-0514-a-builder-records-its-judgment-calls-and-the-session-verifies-them.md)).
|
|
@@ -409,7 +434,7 @@ A question a running builder puts to the board's session, the **orchestrator**,
|
|
|
409
434
|
_Avoid_: builder question, check-in
|
|
410
435
|
|
|
411
436
|
**Stalled**:
|
|
412
|
-
A builder still recorded as running
|
|
437
|
+
A builder still recorded as running with no progress line, and no change to its Claude transcript, for at least 10 minutes (counted from its start before its first progress). Its card's status line turns the needs-you red, and a tap on it nudges Claude, until fresh progress or completion; silence calls for a check, without establishing that the process has failed.
|
|
413
438
|
_Avoid_: stuck, hung, failed
|
|
414
439
|
|
|
415
440
|
**Worktree**:
|
|
@@ -419,25 +444,37 @@ _Avoid_: copy, checkout, live folder (for the builder's)
|
|
|
419
444
|
### Talking with the owner
|
|
420
445
|
|
|
421
446
|
**New task**:
|
|
422
|
-
A free-form request or question the owner sends from the board's + button (or by pressing n twice). Code and events call it an **ask**: an `ask` event whose thread is `ask:<event id>`. It is a **New card** at the top of Todo, with no wave and no Action needed, until Claude sorts it one of three ways ([the + makes a New card, which Claude files, folds or answers](docs/adr/2026-10-29-1639-the-plus-makes-a-new-card.md)): files it under a wave as a work item, whose thread opens with it (`item set --from-ask`), and sets its **card state**; folds it into the card it's about, whose thread then holds the message marked Moved (`item relate-ask`, undone by `ask unfold`); or answers it, which puts it in the Asks lane below Done, named by when it was asked, whose thread takes the owner's later replies ([answered asks have their own section below Done, and Done and Asks show 10 cards at a time](docs/adr/2026-11-03-0259-answered-asks-have-their-own-section-below-done.md)). An answer that leaves a question open on it keeps it in Todo with Action needed, never in Asks, until the owner answers and Claude replies, or it is closed; it stays in Todo while Claude takes up the answer ([an unstarted card waits on its questions in Todo, and its one action button follows what it waits on](docs/adr/2026-10-30-1309-an-unstarted-card-waits-on-its-questions-in-todo.md)). When another board fits it better, the owner can have it **moved there** (`ask move`): it becomes a New card on that board reading "Moved from <this board>", and here a Done card whose thread links to it. Folding is within one board; a move is between boards. An answer that waits on the owner, such as a choice only the owner can settle, keeps it in In Review with Action needed until the owner taps
|
|
447
|
+
A free-form request or question the owner sends from the board's + button (or by pressing n twice). Code and events call it an **ask**: an `ask` event whose thread is `ask:<event id>`. It is a **New card** at the top of Todo, with no wave and no Action needed, until Claude sorts it one of three ways ([the + makes a New card, which Claude files, folds or answers](docs/adr/2026-10-29-1639-the-plus-makes-a-new-card.md)): files it under a wave as a work item, whose thread opens with it (`item set --from-ask`), and sets its **card state**; folds it into the card it's about, whose thread then holds the message marked Moved (`item relate-ask`, undone by `ask unfold`); or answers it, which puts it in the Asks lane below Done, named by when it was asked, whose thread takes the owner's later replies ([answered asks have their own section below Done, and Done and Asks show 10 cards at a time](docs/adr/2026-11-03-0259-answered-asks-have-their-own-section-below-done.md)). An answer that leaves a question open on it keeps it in Todo with Action needed, never in Asks, until the owner answers and Claude replies, or it is closed; it stays in Todo while Claude takes up the answer ([an unstarted card waits on its questions in Todo, and its one action button follows what it waits on](docs/adr/2026-10-30-1309-an-unstarted-card-waits-on-its-questions-in-todo.md)). When another board fits it better, the owner can have it **moved there** (`ask move`): it becomes a New card on that board reading "Moved from <this board>", and here a Done card whose thread links to it. Folding is within one board; a move is between boards. An answer that waits on the owner, such as a choice only the owner can settle, keeps it in In Review with Action needed until the owner taps the Done beside Reply in its thread ([an ask can wait on the owner before Done, and the owner closes any open card from its thread](docs/adr/2026-10-29-1639-an-ask-can-wait-in-progress-until-the-owner-marks-it-done.md)).
|
|
423
448
|
_Avoid_: ask (in what the owner reads), message, prompt, Waiting for Claude strip
|
|
424
449
|
|
|
425
450
|
**Thread**:
|
|
426
|
-
The conversation on one work item: Claude's reports, builders' status lines, the owner's messages, mirrored GitHub comments, and answers to the item's questions.
|
|
451
|
+
The conversation on one work item: Claude's reports, builders' status lines, the owner's messages, mirrored GitHub comments, and answers to the item's questions. An In Review card's reply form sends with Reply then Done, which closes the card; a Todo card closes from Close, right of Hold in its actions, and an In Progress card has neither, only Send ([Done shows only in In Review, beside Reply](docs/adr/2026-11-05-1918-done-shows-only-in-in-review-beside-reply.md)).
|
|
427
452
|
An open card shows its thread's newest 3 messages as it opens, or from its oldest **unread message** when more than 3 messages follow it, at most 10, unread as of when the card opened. Messages that arrive while it is open add below, hiding none. Messages are the owner's, Claude's (replies included) and other people's; builder, status and ask-link lines show among the messages they sit between and don't count. "Show more · N previous messages" at the top adds the next 3 older messages each tap and goes when nothing older is left. The expansion lasts while the card stays open, through repaints and new messages, and closing the card puts it back to 3. A message being edited always shows, with every line after it; one waiting on Claude shows only where the window reaches it.
|
|
428
453
|
An owner message Claude hasn't answered yet ends with **Waiting for Claude…**, or Working on it while Claude is on it. An answer to a question stops waiting once it's acted on: its question resolved after it, a later prototype round on it, or a build started on the card after it ([an answer stops waiting once it's acted on, and a Next set during the card's questions clears](docs/adr/2026-11-03-1313-an-answer-stops-waiting-once-its-acted-on.md)). A batch of the owner's answers in a row in the same state carries it once, under the last answer.
|
|
429
454
|
_Avoid_: comments, chat
|
|
430
455
|
|
|
431
456
|
**Unread message**:
|
|
432
|
-
A message in a card's thread from Claude (replies included) or GitHub, newer than
|
|
457
|
+
A message in a card's thread from Claude (replies included) or GitHub, newer than the card's **read mark**. The owner's own lines, their copied-in answers included, other people's Slack lines, and builder, status and ask-link lines are never unread. The card's last line ends with their count in the accent colour, after any hold, as "3:00 PM · held until Wed 9:00 am · 3 new messages", until it is opened.
|
|
433
458
|
_Avoid_: inbox, notification. "New" names it only in that count's "N new messages"; a New card is an unsorted ask.
|
|
434
459
|
|
|
460
|
+
**Read mark**:
|
|
461
|
+
How far the owner has read a card: the time of the newest message, question or answer it showed when they last opened it, kept on the board in `data/read.json`, one set for every device, so a card opened on the phone reads on the Mac too. A card new to the board is read up to when the server first sees it, so it badges only what comes after; a card leaving the board, dropped or past the newest 100 Done, loses its mark ([read marks live on the board](docs/adr/2026-11-05-0910-read-marks-live-on-the-board.md)). Every board answer carries it as the card's `readAt`.
|
|
462
|
+
_Avoid_: seen mark, last seen
|
|
463
|
+
|
|
435
464
|
**Last visit**:
|
|
436
|
-
The board and threads this device last showed, kept in its browser
|
|
465
|
+
The board and threads this device last showed, with the board's **change number**, kept in its browser's IndexedDB. The next visit paints it live at first paint, readable at any age, and asks the board only for what changed after its number; the lines that catch-up changes flash a fading blue border round each lane count, Needs you line or thread message ([the board opens on the last visit](docs/adr/2026-10-29-1639-the-board-opens-on-the-last-visit.md), [the board syncs by change number](docs/adr/2026-11-05-1819-the-board-syncs-by-change-number.md)); a card that changed shows its own sign ([an updated card takes a brief tint](docs/adr/2026-11-02-2354-an-updated-card-takes-a-brief-tint.md)). It paints only under the build that saved it, a hash of the shell's file versions (`hub/shell.mjs` `shellHtml`), so code that changed since never reads it, except while the board is out of reach, when the page paints another build's copy inside a guard; where there is none, or IndexedDB refuses, the page paints nothing until the whole board lands, and shows the **down landing** if the load fails. Out of reach, the copy stays undimmed and readable, with only the header time red and the buttons that send held, each labelled one saying "Waits for the board"; Waiting on you shows the same copy, and Notes and Settings keep their own, Settings read only ([a board out of reach keeps its copy or shows a landing](docs/adr/2026-11-06-0135-a-board-out-of-reach-keeps-its-copy-or-shows-a-landing.md)). In code it is the copy.
|
|
437
466
|
_Avoid_: cache, offline copy, stale board
|
|
438
467
|
|
|
468
|
+
**Down landing**:
|
|
469
|
+
What a board's view shows in place of the board when the board can't be reached and the device has no copy to show: the kickflip mark, one bold line and one muted hint, the look of the no-access page. The line and hint name one of six states, read from what the hub marks on its answer (`x-kickflip-down`, `x-kickflip-hub`): Board restarting (its code changed, it's starting, or it crashed and the hub is relaunching it), Board stopped, This board is gone, You no longer have access, Board restarting (it answers with errors) and Board offline (nothing answers). It retries every 5 s while the board can come back by itself ([a board out of reach keeps its copy or shows a landing](docs/adr/2026-11-06-0135-a-board-out-of-reach-keeps-its-copy-or-shows-a-landing.md)).
|
|
470
|
+
_Avoid_: offline page, error page, landing (alone: a card lands)
|
|
471
|
+
|
|
472
|
+
**Change number**:
|
|
473
|
+
The board server's one counter, which steps once for each built board that differs from the one before and is the board's version. Each card, question and topic carries the number of its last change, and a removal leaves a tombstone with its number, all kept in `data/sync.json` so a restart carries on counting. A page naming the number it holds gets only what changed after it, answered from the current board; one older than the oldest tombstone kept gets the whole board ([the board syncs by change number](docs/adr/2026-11-05-1819-the-board-syncs-by-change-number.md)).
|
|
474
|
+
_Avoid_: sync id, version hash
|
|
475
|
+
|
|
439
476
|
**Answer banner**:
|
|
440
|
-
The one line at the top of a board, above Needs you, naming new tasks Claude answered without making work whose answer
|
|
477
|
+
The one line at the top of a board, above Needs you, naming new tasks Claude answered without making work whose answer came after the card's read mark: "1 answer · <ask>" or "2 answers · <newest> and 1 more". A tap opens the newest one's card; opening a card anywhere takes its answer off at once, and ✕ marks every answer shown read, on every device. No push goes for an answer ([a push goes out only when something waits on the owner, on the hub's schedule](docs/adr/2026-10-29-1639-pushes-only-when-something-waits-on-the-owner.md)).
|
|
441
478
|
_Avoid_: notification, toast
|
|
442
479
|
|
|
443
480
|
**Owner question**:
|
|
@@ -453,7 +490,7 @@ The group an owner question belongs to; an item's questions use the topic `item:
|
|
|
453
490
|
_Avoid_: category, section
|
|
454
491
|
|
|
455
492
|
**Needs you**:
|
|
456
|
-
|
|
493
|
+
What waits on the owner on a board, led by the board session's **pending prompts** ([Needs you gathers what waits on the owner, and a topic's questions are answered on one page](docs/adr/2026-10-29-1639-needs-you-gathers-what-waits-and-questions-answer-on-one-page.md)). On a phone it is the **deck** at the top of the board: one thing at a time, a tap on a question's option drafting its answer, which Send on Waiting on you sends with its notes, a prompt's buttons answering it on the tap, Skip, a dot per thing waiting, View prototypes on a question with prototypes, and All open questions at its foot. From 900px it is a pane beside the lanes, one orange line per work item over Waiting on you, which arrivals update in place ([Needs you is a deck on a phone and a pane on a desktop](docs/adr/2026-11-05-0408-needs-you-is-a-deck-on-a-phone-and-a-pane-on-a-desktop.md)). The board and Waiting on you are a board's two pages: side by side from 900px, and narrower one at a time, the board header's ? (with the open-question count as its badge) opening Waiting on you, whose check goes back to the board ([Board and Open questions are two pages](docs/adr/2026-11-07-1300-board-and-open-questions-are-two-pages.md)).
|
|
457
494
|
_Avoid_: inbox, digest
|
|
458
495
|
|
|
459
496
|
**Pending prompt**:
|
|
@@ -461,7 +498,7 @@ A permission prompt or `AskUserQuestion` from a background board session, which
|
|
|
461
498
|
_Avoid_: permission request, approval, dialog
|
|
462
499
|
|
|
463
500
|
**Event**:
|
|
464
|
-
A signal that wakes the owning session: something the owner did on a page (an ask, an answer, a button), or a board change such as `card-unblocked {key}` when a waiting card’s last unfinished dependency finishes ([cards wait on explicit blocked-by links](docs/adr/2026-10-29-1639-cards-wait-on-explicit-blocked-by-links.md))
|
|
501
|
+
A signal that wakes the owning session: something the owner did on a page (an ask, an answer, a button), or a board change such as `card-unblocked {key}` when a waiting card’s last unfinished dependency finishes ([cards wait on explicit blocked-by links](docs/adr/2026-10-29-1639-cards-wait-on-explicit-blocked-by-links.md)).
|
|
465
502
|
_Avoid_: action, request
|
|
466
503
|
|
|
467
504
|
**Rule**:
|
|
@@ -478,7 +515,7 @@ _Avoid_: unread, queued
|
|
|
478
515
|
|
|
479
516
|
|
|
480
517
|
**Prototype**:
|
|
481
|
-
A page that shows each option of one owner question as it would ship, built from the board's real components fed fake data. An agent records it with `board.mjs prototype add <topic>` in the site's `data/prototypes.json`, with its title, card and takes, and writes only the take files; the board serves `prototype-<topic>.html` from its one template, `board/public/prototype.html`. `question add` accepts a prototype url only for a recorded topic, with option ids a non-empty subset of its take keys in order, without repeats, and every take file written ([the board serves every prototype from one template](docs/adr/2026-11-01-1448-the-board-serves-every-prototype-from-one-template.md)).
|
|
518
|
+
A page that shows each option of one owner question as it would ship, built from the board's real components fed fake data. An agent records it with `board.mjs prototype add <topic>` in the site's `data/prototypes.json`, with its title, card and takes, and writes only the take files; the board serves `prototype-<topic>.html` from its one template, `board/public/prototype.html`. `question add` accepts a prototype url only for a recorded topic, with option ids a non-empty subset of its take keys in order, without repeats, and every take file written ([the board serves every prototype from one template](docs/adr/2026-11-01-1448-the-board-serves-every-prototype-from-one-template.md)). A **served round** is recorded with `--served <path>`: it has no take files, its page lives in the board's **base prototype worktree** (`~/.claude/kickflip/worktrees/<route>-prototypes`, on main), and its named **states** show as chips in the viewer's bar ([a prototype round is a page in the board's base prototype worktree](docs/adr/2026-11-06-1500-a-prototype-round-is-a-page-in-the-boards-base-worktree.md)). The page is the **viewer**: full bleed with no header, a ✕ that goes back, one take at a time switched by the floating bar's ‹ › pager, ←/→ or a swipe, Choose this on the bar's second row, and on a card with earlier rounds a Round pill opening a sheet of them ([prototypes have their own button and a full-bleed viewer](docs/adr/2026-11-07-0300-prototypes-have-their-own-button-and-viewer.md)).
|
|
482
519
|
_Avoid_: mockup, demo page
|
|
483
520
|
|
|
484
521
|
**Prototype round**:
|
|
@@ -494,7 +531,7 @@ The owner asking, from a card's thread or with a question's eye on Waiting on yo
|
|
|
494
531
|
_Avoid_: mockup request, preview
|
|
495
532
|
|
|
496
533
|
**Take**:
|
|
497
|
-
One option of an owner question shown as what it would be: a
|
|
534
|
+
One option of an owner question shown as what it would be: a take of a prototype, or a diagram of boxes and arrows with what it means in practice. A prototype's take is a key (one capital letter), a label and a file, `public/prototypes/<topic>/<KEY>.js`, whose `render(stage, kit)` draws it into the page's stage. Waiting on you shows a prototype question's options with a View prototypes button to the prototype page, the full-page viewer that shows one take at a time and drafts a pick for the question's Send; a diagram take draws in the question ([a question's prototypes open in a full-page viewer](docs/adr/2026-11-05-1302-a-questions-prototypes-open-in-a-full-page-viewer.md), [the board serves every prototype from one template](docs/adr/2026-11-01-1448-the-board-serves-every-prototype-from-one-template.md)).
|
|
498
535
|
_Avoid_: variant (the switcher's URL parameter, not the word), mockup
|
|
499
536
|
|
|
500
537
|
**Kit**:
|
|
@@ -516,17 +553,17 @@ Refs in text that Claude or the owner wrote are linked by the renderer, never by
|
|
|
516
553
|
| `ui.js` | Shared helpers: escaping, times, reply bodies, attachments, icons and message buttons, badges by tone, `setHTML`, which patches a region in place and keeps the focused field's focus when it moves, and `fetchJSON`, through which the side pages read the API and wait out a board restart |
|
|
517
554
|
| `ui-links.js` | Linking refs, Linear ids, PRs and URLs in written text; load it right after `ui.js` |
|
|
518
555
|
| `ui-enums.js` | `BoardUI.BUTTON` and `BoardUI.ACTION_KIND`, the **action button**'s enums, shared with `board/domain.mjs`, which runs it in a vm context; load it before `ui-threads.js` and `ui-cards.js`. `view.test.mjs` checks that every action kind makes one button orange and every action button draws |
|
|
519
|
-
| `ui-patch.js` | `BoardUI.
|
|
556
|
+
| `ui-patch.js` | `BoardUI.applyPatch`, applying the board's patches on the page: cards by key, questions and topics by id, every other part whole when it changed, onHost beside the board ([the board sends per-card patches](docs/adr/2026-11-04-0332-the-board-sends-per-card-patches.md), [the board syncs by change number](docs/adr/2026-11-05-1819-the-board-syncs-by-change-number.md)) |
|
|
520
557
|
| `ui-order.js` | `BoardUI.laneOrder`, the board's order of its items ([each lane has one fixed order](docs/adr/2026-11-03-0223-each-lane-has-one-fixed-order.md)), shared with `board/domain.mjs`, which runs it in a vm context, so a tap the page draws at once lands where the server puts it |
|
|
521
558
|
| `ui-cards.js` | A card's lines, in order: title with its ticket badge, or New chip on an unsorted ask (none once sorted); status with its ETA, red and a nudge when the builder is silent; then PR, review and other chips, then the try badge (Visit or Install, with running, failed and stale states); its lineup's grey wave chip; last the time its lane sorts by, its hold, blocked by, Action needed, an In Progress card's phase bars and its unread count; the Hold sheet's picker; and at its top right a New card's bump, edit and delete icons, or another bumpable card's bump icon, filled orange once bumped; and the action row's Merge and Serve/Build buttons, main's bar and build wording |
|
|
522
|
-
| `ui-
|
|
523
|
-
| `ui-sidebar.js` | `BoardUI.sidebar`, the sidebar's markup from `/_hub/sidebar.json`, with the New version row from `updateRow`, Reload or the npm update's Upgrade, headed by `BoardUI.header` itself, with each row's key in **switch mode**; `switchKeys`, which row each key opens; `othersWaiting`, for the logo's label; `shortcuts`, the **shortcuts sheet**'s content from the one list of shortcuts; and `startCaption`, a starting board's step and seconds. Needs `ui-
|
|
559
|
+
| `ui-progress-bar.js` | `BoardUI.progressBar({count, done, now, percent, dim, tone, label})`, the one progress bar every bar draws from: an In Progress card's five build phases and a Todo card's planner dashes (`ui-cards.js`), and a starting board's three start steps (`ui-sidebar.js`); done steps filled, the one step at index `now` pulsing (none when dim), a `percent` filling the next. `BoardUI.onePulse`, listening for `animationstart`, puts every pulse on the page, bars and status dots, on one clock ([a progress bar pulses one step at a time](docs/adr/2026-11-06-0038-a-progress-bar-pulses-one-step-at-a-time.md)). Needs nothing else: `hub/hub.mjs` renders the app shell's first sidebar with it in a vm context; load it before `ui-cards.js` and `ui-sidebar.js` |
|
|
560
|
+
| `ui-sidebar.js` | `BoardUI.sidebar`, the sidebar's markup from `/_hub/sidebar.json`, with the New version row from `updateRow`, Reload or the npm update's Upgrade, headed by `BoardUI.header` itself, with each row's key in **switch mode**; `switchKeys`, which row each key opens; `othersWaiting`, for the logo's label; `shortcuts`, the **shortcuts sheet**'s content from the one list of shortcuts; and `startCaption`, a starting board's step and seconds. Needs `ui-progress-bar.js` and `ui-page-header.js` loaded before it: `hub/hub.mjs` renders the app shell's first sidebar with all three in a vm context |
|
|
524
561
|
| `sidebar.js` | Painting the sidebar from the copy written into the shell, else this device's last copy, then from each copy the hub's stream sends; this device's push subscription for its Turn on row; the logo's toggle, the drawer and its swipes, the rail's collapse, which this device keeps, and the logo's label; **switch mode**'s keys, from the document and a framed page, each row opened through the shell; the **shortcuts sheet**'s h h and Escape |
|
|
525
562
|
| `app.html` | The app shell: the sidebar, the view's slot, and its scripts and CSS from `/_hub/app/`, with a board's loads started in its `<head>`; the hub serves it for a browser's load of `/` or a site's page outside try URLs, and every load of a hub page, with the sidebar and its data written in (`hub/shell.mjs` `pageOf`), and the board server for a board's four view paths without them (`shellHtml`) |
|
|
526
563
|
| `router.js` | `AppRouter`: every hub URL as a view and each view as its URL (`ui.test.mjs` tests both), the views the shell mounts in place, framed pages included, and catching taps on links to them and back and forward, with `{idx}` in each history entry and `pushed` on one a push opened; a back arrow goes one step back by them. On the **page tree** each entry also carries `up`, how many of its parents sit under it, which the router writes on every way in, and the arrow goes up a level. It frames the paths `hub/shell.mjs` `pageOf` answers with the shell, which `hub/shell.test.mjs` checks |
|
|
527
564
|
| `shell.js` | `AppShell`: the hub code check that shows New version with an owner-tapped Reload, the sidebar mounted once, one view at a time, asking before leaving an unsaved edit, `/`'s pick of a board, the hub's one stream and which left boards are unchanged, a framed page's URL and title copied to the top, a push tap from `hub/sw.js` or a framed page's view URL (`AppShell.open`) routed in place, and registering `hub/sw.js`, which opens the shell while the host is asleep |
|
|
528
|
-
| `view-settings.js` | Board Settings as a modal over its board, which shell.js mounts: repo and branch (Change uses the same list and GitHub link search as New board), | `view-settings.js` | Board Settings as a modal over its board, which shell.js mounts: repo and branch (Change uses the same list and GitHub link search as New board), ticket source, auto-merge, auto-build, auto-pull (Auto implement Todo cards) with Maximum parallel implementers, auto-triage, reviewers, rules and Close board with its typed-name sheet |
|
|
529
|
-
| `view-questions.js` | Waiting on you as a view: a topic's questions,
|
|
565
|
+
| `view-settings.js` | Board Settings as a modal over its board, which shell.js mounts: repo and branch (Change uses the same list and GitHub link search as New board), | `view-settings.js` | Board Settings as a modal over its board, which shell.js mounts: repo and branch (Change uses the same list and GitHub link search as New board), ticket source, auto-merge, auto-build, auto-pull (Auto implement Todo cards) with Maximum parallel implementers and planners, auto-triage, reviewers, rules and Close board with its typed-name sheet |
|
|
566
|
+
| `view-questions.js` | Waiting on you as a view: a topic's questions, a prototype question's View prototypes link to its viewer, each question's eye, which asks for a prototype of that question, and one Send, which stays while the topic has a question open and otherwise opens the next topic with one, or goes back to the board |
|
|
530
567
|
| `view-notes.js` | One item's notes, or with `?wave=` a lineup's goal, order and note, as a view, from `GET /api/notes`; the server redirects `plan.html` to `notes.html` |
|
|
531
568
|
| `view-hub.js` | The **hub page** as a view, from `/_hub/api/hub`, refreshed every 30 seconds while it shows; the Usage card, whose Claude model posts `/_hub/settings/claude-model`, Codex share posts `/_hub/settings/codex` and pause line posts `/_hub/settings/pause-at`, with Keep going and Stop banners posting `/_hub/settings/keep-going`, pending prompts of sessions with no board, Send now, then `view-hub-settings.js` below its status |
|
|
532
569
|
| `view-hub-settings.js` | Summary rows opening **hub settings** modals over the hub page, from `/_hub/api/settings`: Notifications with Snooze and Keep awake with their one duration picker (`durationPicker`: chips and a native Custom picker), Quiet hours, Linear (`linear-key.js`’s slot), Rules for every board and Closed boards with Reopen |
|
|
@@ -536,20 +573,20 @@ Refs in text that Claude or the owner wrote are linked by the renderer, never by
|
|
|
536
573
|
| `view-frame.js` | Any other page as a frame view: the frame beside the board header with Open alone ↗, hiding that header for a page that draws its own, whose logo then toggles the sidebar; each load's URL and title to the shell, and taps on links to other views sent to it, a prototype's back arrow included, which the shell takes up the **page tree** before the page's own script can |
|
|
537
574
|
| `sidebar.css` | The sidebar's rail, its collapse, the drawer and switch mode, plus the shared New board dialog and the shortcuts sheet; linked after `colors.css` |
|
|
538
575
|
| `hub.css` | The hub views' CSS and the hub's down page's, every rule under `.hub-view`, the class on a hub view's root, on the down page's `<html>` and on the board's Hold sheet picker, which shares the duration picker's rules; the shell links it after `style.css`, whose header the hub views share, and the down page as `/_hub/hub.css` |
|
|
539
|
-
| `ui-page-header.js` | `BoardUI.header`, every page's header: the logo (which toggles the sidebar), a back arrow where needed (beside a phone-only logo), the title, then the time and ↻, a
|
|
576
|
+
| `ui-page-header.js` | `BoardUI.header`, every page's header: the logo (which toggles the sidebar), a back arrow where needed (beside a phone-only logo), the title, then the time and ↻, or a page's own trail, and on a board's two pages the switch between them below 900px (the board's ? with the open-question count, Waiting on you's check); `BoardUI.boardFoot`, the bulb and gear at the foot of the board. On a page of its own, the back arrow's own script goes one step back, or to its href after a push; in the app shell `router.js` does that. Needs nothing else: `server.mjs` renders each page's `<!--header {…}-->` with it, such as a prototype's, and `hub/hub.mjs` the shell's first sidebar, whose head is one too (`ui-sidebar.js`), each in a vm context |
|
|
540
577
|
| `ui-header.js` | The header's time, or paused until from the shell's pause state, and when it moves, the GitHub status line and its Hub links mark, the Hub links list, the setup checklist, when a refresh asks for a GitHub check, and which board header controls take taps |
|
|
541
578
|
| `ui-threads.js` | Thread messages, with link, status and agent lines, the open card's window over them with its Show more, and the reply form's Done |
|
|
542
|
-
| `ui-questions.js` | Owner question cards with their
|
|
579
|
+
| `ui-questions.js` | Owner question cards with their View prototypes button and drawn takes, answer history, prototype status, a confirm's line, the topic head's round chip and the Waiting on you topic row; `cardTopics`, which names a card's question topic from its card; `BoardUI.nextQuestion`, the pure move-on rule after a Send, and `sentNotice`, the Sent line the board reads on return |
|
|
543
580
|
| `ui-markdown.js` | The Markdown subset `view-notes.js` renders a card's notes with |
|
|
544
|
-
| `ui-snapshot.js` | The last visit's stored shape and
|
|
581
|
+
| `ui-snapshot.js` | The last visit's stored shape and what reads as one, which threads preload, which lines flash, and what counts as a card's update |
|
|
545
582
|
| `attach.js` | Picking and uploading attachments, each to the site of the board view around its composer |
|
|
546
583
|
| `prototype.html` | The one prototype page: the server fills in a recorded topic's title, header and takes; the stage that contains each take, and the pill's room below it |
|
|
547
|
-
| `prototype-kit.js` | The **kit** and the take loader: each switch ends the last take's cleanup, listeners and timers, renders the next into a fresh stage at the same scroll position, and turns links and forms in the stage into toasts; `prototype-kit.test.mjs` tests it |
|
|
548
|
-
| `prototype-switcher.js` |
|
|
549
|
-
| `app-core.js` | The view's shared helpers: drafts,
|
|
584
|
+
| `prototype-kit.js` | The **kit** and the take loader: each switch ends the last take's cleanup, listeners and timers, renders the next into a fresh stage at the same scroll position, with each box scrolled inside the take scrolled back where the new take draws it, and turns links and forms in the stage into toasts; `prototype-kit.test.mjs` tests it |
|
|
585
|
+
| `prototype-switcher.js` | The full-page viewer's ‹ take › pill, its keys and `?variant=`, and with `?q=` the pick and note drafted for the card's question, then back to that question for its Send, handed to the app shell when the page is framed in it; `prototype-switcher.test.mjs` tests its controls and a pick through `mount` |
|
|
586
|
+
| `app-core.js` | The view's shared helpers: drafts, read marks, hiding, and `steady`, which runs a repaint keeping the box being typed in, else the open card's title row, still on screen, and its focus and cursor; where the owner left the board, its scroll and box, kept through `B.keep` and restored after its next first render in the page; re-exports `dialogs.js` as `B.confirm` and `notice` |
|
|
550
587
|
| `dialogs.js` | `BoardDialogs.confirm` and `notice`, which every board page's dialogs go through, and `fitSheet`, the sheets’ shared phone keyboard handling, `repoSheet` for New board and Repo → Change, and `ticketsControl`, shared by New board and Board Settings, which opens `linear-key.js`’s modal for Linear without a working key; loaded on every page |
|
|
551
588
|
| `rules-editor.js` | `RulesEditor`, the rules list on Board Settings and the Hub page, with its own CSS; `ui.test.mjs` tests its pure parts |
|
|
552
|
-
| `app-threads.js` | Loading a thread, once at a time per card; an open card's thread, its reply box, quick replies and
|
|
589
|
+
| `app-threads.js` | Loading a thread, once at a time per card; an open card's thread, its reply box, quick replies and its send buttons |
|
|
553
590
|
| `app-cards.js` | Cards, their open detail with the details list ending in Notes ↗ · Visit/Install ↗ · Review on GitHub ↗ when present, and the workflow row: Merge, Hold, the **action button**, Serve/Build and rightmost **Implement**, each confirming but Hold, which opens its sheet with the duration picker; try requests, failure-thread links and main’s failed-build log and Retry sheet; the bump icon's bump and unbump, with no confirmation; an ask's detail shows only its action button; the thread's Done confirmation and send |
|
|
554
591
|
| `app-lanes.js` | Lanes, Done's and Asks' Show more, Done's finished-wave folds, Todo's **wave bands** with their Implement, Triage and ⋯ moves, and Plan waves |
|
|
555
592
|
| `new-task.js` | The + button, its new-task sheet and press-n-twice shortcut, on every page of a board |
|
|
@@ -557,9 +594,9 @@ Refs in text that Claude or the owner wrote are linked by the renderer, never by
|
|
|
557
594
|
| `app-needs.js` | The Needs you box, led by the board session's pending prompts |
|
|
558
595
|
| `ui-prompts.js` | A pending prompt's Needs you line: its details, Allow once, Always allow and Deny, or a question's options, Skip and Send |
|
|
559
596
|
| `prompts.js` | `PromptAnswers`, answering pending prompts from their lines on a board and the hub page: which taps send at once, Always allow's confirmation, and the picks a Send waits on |
|
|
560
|
-
| `app-arch.js` | The
|
|
597
|
+
| `app-arch.js` | The bulb at the foot of the board and its **architecture review** sheet: the last review, Run with its confirm, what a review waits on, and the bulb's glow while one runs |
|
|
561
598
|
| `app-reader.js` | The **reader sheet**: a builder's log (readable or raw, following it as it grows) and a card's or lineup's Notes, opened over the board from their links, closing on ✕, Escape, the dim area or Back |
|
|
562
599
|
| `app-banner.js` | The answer banner, its tap and its ✕ |
|
|
563
600
|
| `app-header.js` | The board's header controls and time, refresh, the offline state, the In Review header's GitHub line, the Hub links sheet and the setup checklist |
|
|
564
|
-
| `app-snapshot.js` | Reading and saving the last visit, also as the view unmounts,
|
|
565
|
-
| `app.js` | `BoardView`: each board's `B`, its state and per-board store, mount and unmount, what each part keeps through `B.keep` for the board's next mount in the page (`B.place`), and the view's markup for the app shell; rendering main's slim bar and the view from its parts, painting the last visit
|
|
601
|
+
| `app-snapshot.js` | Reading and saving the last visit in IndexedDB, also as the view unmounts, with its change number for `app.html`'s first board request, the flash when the catch-up lands, and each card's sign: the flash on a card that changed lanes or took a New task's place, and the tint on a card otherwise updated, unless the owner changed it from this page |
|
|
602
|
+
| `app.js` | `BoardView`: each board's `B`, its state and per-board store, mount and unmount, what each part keeps through `B.keep` for the board's next mount in the page (`B.place`), and the view's markup for the app shell; rendering main's slim bar and the view from its parts, painting the last visit live, loading the board with its open threads (taking over the loads `app.html` starts), `B.send`, which sends an **owner tap**, draws it at once and lands the board the POST answers with, and the bump icon's fade, preloading active cards' threads, the reload timers, and the change signal from the shell |
|