runcastle 1.6.2 → 1.6.4

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.
Files changed (60) hide show
  1. package/README.md +4 -4
  2. package/bin/runcastle.js +13202 -61413
  3. package/drizzle/0057_jazzy_lila_cheney.sql +1 -0
  4. package/drizzle/0058_test_note_open_only.sql +9 -0
  5. package/drizzle/0059_milky_black_knight.sql +17 -0
  6. package/drizzle/0060_drop_prepare_sessions.sql +6 -0
  7. package/drizzle/0061_events_type_index.sql +4 -0
  8. package/drizzle/0062_workers.sql +30 -0
  9. package/drizzle/0063_worker_dev_server.sql +1 -0
  10. package/drizzle/0064_worker_tokens.sql +1 -0
  11. package/drizzle/0065_review_workers.sql +28 -0
  12. package/drizzle/0066_drive_workers.sql +39 -0
  13. package/drizzle/meta/0057_snapshot.json +1351 -0
  14. package/drizzle/meta/0059_snapshot.json +1461 -0
  15. package/drizzle/meta/0062_snapshot.json +1654 -0
  16. package/drizzle/meta/0063_snapshot.json +1662 -0
  17. package/drizzle/meta/0064_snapshot.json +1669 -0
  18. package/drizzle/meta/0065_snapshot.json +1690 -0
  19. package/drizzle/meta/0066_snapshot.json +1704 -0
  20. package/drizzle/meta/_journal.json +70 -0
  21. package/index.js +12480 -60694
  22. package/package.json +2 -3
  23. package/skills/packs/README.md +11 -15
  24. package/skills/packs/runcastle/.claude-plugin/plugin.json +1 -1
  25. package/skills/packs/runcastle/skills/code-review/SKILL.md +3 -3
  26. package/skills/packs/runcastle/skills/feature/SKILL.md +37 -18
  27. package/skills/packs/runcastle/skills/feature/references/design.md +102 -127
  28. package/skills/packs/runcastle/skills/feature/references/grilling.md +9 -3
  29. package/skills/packs/runcastle/skills/feature/references/planning-alone.md +69 -38
  30. package/skills/packs/runcastle/skills/feature/references/preview-starter.html +22 -20
  31. package/skills/packs/runcastle/skills/feature/references/preview.md +45 -27
  32. package/skills/packs/runcastle/skills/feature/references/spec.md +1 -1
  33. package/skills/packs/runcastle/skills/feature/references/workers.md +144 -0
  34. package/skills/packs/runcastle/skills/project/SKILL.md +64 -201
  35. package/skills/packs/runcastle/skills/project/references/charter.md +3 -3
  36. package/skills/packs/runcastle/skills/project/references/health-sweeps.md +3 -3
  37. package/skills/packs/runcastle/skills/project/references/intake.md +139 -0
  38. package/skills/packs/runcastle/skills/{prepare/references/recipes.md → project/references/preparation-recipes.md} +2 -2
  39. package/skills/packs/runcastle/skills/project/references/preparation.md +176 -0
  40. package/skills/packs/runcastle/skills/project/references/routing.md +39 -0
  41. package/skills/packs/runcastle/skills/project/references/triage.md +3 -3
  42. package/skills/packs/runcastle/skills/qa/SKILL.md +5 -7
  43. package/skills/review/review-drive.md +33 -0
  44. package/skills/review/review-gates.md +22 -0
  45. package/skills/review/review.md +61 -0
  46. package/skills/review/verify.md +31 -0
  47. package/web/assets/index-C0TYj0Ka.css +1 -0
  48. package/web/assets/index-C6JVtDiw.js +193 -0
  49. package/web/index.html +3 -3
  50. package/web/manifest.webmanifest +2 -2
  51. package/web/sw.js +4 -4
  52. package/skills/burner/implement-ticket.md +0 -118
  53. package/skills/burner/resolve-conflict.md +0 -78
  54. package/skills/burner/review-ticket.md +0 -268
  55. package/skills/burner/verify-fixes.md +0 -59
  56. package/skills/packs/runcastle/skills/feature/references/rounds.md +0 -97
  57. package/skills/packs/runcastle/skills/feature/references/tickets.md +0 -231
  58. package/skills/packs/runcastle/skills/prepare/SKILL.md +0 -148
  59. package/web/assets/index-CHxfwKvB.js +0 -193
  60. package/web/assets/index-CVCnjOHN.css +0 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "runcastle",
3
- "version": "1.6.2",
4
- "description": "Burn tickets into shipped features with Claude Code.",
3
+ "version": "1.6.4",
4
+ "description": "Idea in, merged branch out. On your machine, in your repo.",
5
5
  "license": "FSL-1.1-ALv2",
6
6
  "type": "module",
7
7
  "bin": {
@@ -32,7 +32,6 @@
32
32
  "@agentclientprotocol/codex-acp": "2.3.0",
33
33
  "@agentclientprotocol/sdk": "2.0.2",
34
34
  "@anthropic-ai/claude-agent-sdk": "^0.3.281",
35
- "@clack/prompts": "^1.1.0",
36
35
  "@hono/mcp": "0.3.1",
37
36
  "@hono/trpc-server": "0.4.2",
38
37
  "@modelcontextprotocol/sdk": "1.29.0",
@@ -1,6 +1,6 @@
1
1
  # Skill packs
2
2
 
3
- **Packs** are runcastle-owned Claude Code *plugin directories* wired to runcastle's MCP contracts. They are injected into each launched terminal via `--plugin-dir`, so the human's Claude Code needs nothing preinstalled, and upstream changes to Matt Pocock's skills can never break us. Most of the pack's skills are adapted forks of his methodology skills and each keeps a provenance header crediting the original; `prepare` is original runcastle work.
3
+ **Packs** are runcastle-owned Claude Code *plugin directories* wired to runcastle's MCP contracts. They are injected into each launched terminal via `--plugin-dir`, so the human's Claude Code needs nothing preinstalled, and upstream changes to Matt Pocock's skills can never break us. The pack's skills are adapted forks of his methodology skills and each keeps a provenance header crediting the original.
4
4
 
5
5
  ## The `runcastle` pack
6
6
 
@@ -8,10 +8,9 @@ Scope-specific skills, each namespaced `/runcastle:<skill>`:
8
8
 
9
9
  | Skill | Invoked | Does |
10
10
  |---|---|---|
11
- | `/runcastle:feature` | entry for `kind=chat` | the feature's lead from its first message to merge: grills on what the brief did not settle, records decisions, writes the spec, builds itself or writes tickets and runs rounds, reviews when it is worth it, hands over the drive; grilling, spec, tickets, rounds, planning alone, the preview and design live in its `references/` |
11
+ | `/runcastle:feature` | entry for `kind=chat` | the feature's lead from its first message to merge: grills on what the brief did not settle, records decisions, writes the spec, builds itself or hands work to workers, has the end reviewed by a Review worker, hands over the drive; grilling, spec, workers, planning alone, the preview and design live in its `references/` |
12
12
  | `/runcastle:qa` | entry for `kind=qa` | read-only Q&A over an existing feature; never changes it |
13
13
  | `/runcastle:project` | entry for `kind=project` | project scope, not feature scope: consults the portfolio, advises on how a lump of intent should be cut into N features and creates them, routes, answers portfolio questions, curates advisory-only, and owns `CONTEXT.md` |
14
- | `/runcastle:prepare` | entry for `kind=prepare` | *original* — establishes the project's prepared settings and drive machinery with the human |
15
14
  | `/runcastle:code-review` | by description, or by name | two-axis review (Standards + Spec) of a feature branch's diff against its base, run as parallel sub-agents and reported unmerged; never edits |
16
15
 
17
16
  Layout (the verified plugin format — only `plugin.json` lives inside `.claude-plugin/`; `skills/` is a sibling at the plugin root):
@@ -25,15 +24,16 @@ packs/
25
24
  └── skills/
26
25
  ├── feature/
27
26
  │ ├── SKILL.md
28
- │ └── references/ # grilling, spec, tickets, rounds, planning-alone, preview, design
27
+ │ └── references/ # grilling, spec, workers, planning-alone, preview, design
29
28
  ├── qa/SKILL.md
30
29
  ├── project/
31
30
  │ ├── SKILL.md
32
31
  │ └── references/ # loaded on demand by SKILL.md, never up front
33
32
  │ ├── charter.md
34
33
  │ ├── health-sweeps.md
34
+ │ ├── preparation.md
35
+ │ ├── preparation-recipes.md
35
36
  │ └── triage.md
36
- ├── prepare/SKILL.md
37
37
  └── code-review/SKILL.md
38
38
  ```
39
39
 
@@ -66,7 +66,7 @@ The session launcher spawns Claude Code with the pack's **root** directory (the
66
66
  claude ... --plugin-dir "<abs path>/packages/skills/packs/runcastle" ...
67
67
  ```
68
68
 
69
- The `name` field in `plugin.json` becomes the invocation namespace, so the skills resolve as `/runcastle:feature` and friends. The injected system prompt tells each session which entry skill to invoke for its kind (`/runcastle:feature` for a feature's chat, `/runcastle:project` for the project session).
69
+ The `name` field in `plugin.json` becomes the invocation namespace, so the skills resolve as `/runcastle:feature` and friends. The injected system prompt tells each session which entry skill to invoke for its kind (`/runcastle:feature` for a feature's chat, `/runcastle:project` for the orchestrator).
70
70
 
71
71
  ### Entry-skill isolation — settings deny rules, not `disable-model-invocation`
72
72
 
@@ -78,8 +78,8 @@ another session's procedure — `project/SKILL.md` says "**Never run a design
78
78
  grilling**" while `feature`'s description sits in the same list offering exactly
79
79
  that.
80
80
 
81
- The **session-entry** skills — today `feature`, `qa`, `project` and
82
- `prepare` — used to carry `disable-model-invocation:
81
+ The **session-entry** skills — today `feature`, `qa` and `project`
82
+ — used to carry `disable-model-invocation:
83
83
  true` for that reason, on the build-era understanding that explicit invocation
84
84
  kept working (CC-INTEGRATION-NOTES §1). It no longer does: Claude Code now
85
85
  hard-blocks the **Skill tool** for such a skill even when the prompt names it,
@@ -97,8 +97,8 @@ live: **per-session settings**. The launcher launches each session with
97
97
  `entrySkillDenyRules` in `packages/server/src/launcher`), and each injected
98
98
  prompt states the policy in one line. Same layering as the edit guard: the
99
99
  prompt says it, the harness enforces it. `chat` gets `feature`; `qa` — whose
100
- session kind was retired — is denied everywhere; `drive-fix` has no entry skill
101
- and denies all of them.
100
+ session kind was retired — is denied everywhere; the drive's chats are workers now and have no entry skill
101
+ and deny all of them.
102
102
 
103
103
  The reached skill — `code-review` (reached by description) — is in no deny list.
104
104
 
@@ -145,9 +145,5 @@ ticket instead.
145
145
 
146
146
  1. Create `packs/<pack-name>/.claude-plugin/plugin.json` with at least `{ "name": "<pack-name>" }` — `name` sets the `/<pack-name>:` namespace.
147
147
  2. Add skills at `packs/<pack-name>/skills/<skill>/SKILL.md` (folder name = skill name; frontmatter needs `name` matching the folder, `description`, and `disable-model-invocation` — see the split above). Long, rarely-needed sections go in a sibling `references/` dir.
148
- 3. If you are forking an upstream skill, keep the provenance header and rewire its steps to runcastle's MCP tools (`get_feature_context`, `emit_tickets`, `record_event`).
148
+ 3. If you are forking an upstream skill, keep the provenance header and rewire its steps to runcastle's MCP tools (`get_feature_context`, `start_worker`, `record_event`).
149
149
  4. Pass another `--plugin-dir` for it at launch.
150
-
151
- ## Not a pack: `../burner/`
152
-
153
- The sibling `packages/skills/burner/` holds **prompt templates**, not skills — e.g. `implement-ticket.md`, rendered per ticket by the AFK ticket-burner workflow (placeholders `{{TICKET_JSON}}`, `{{FEATURE_BRIEF}}`, `{{DOCS_DIGEST}}`, `{{COMMIT_CONVENTION}}`). It is never passed to `--plugin-dir`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcastle",
3
- "description": "Runcastle skills for the MCP feature pipeline: feature (the feature lead, folding forks of Matt Pocock's grilling, to-spec and to-tickets), qa, project and code-review (forks, adapted), plus prepare (original).",
3
+ "description": "Runcastle skills for the MCP feature pipeline: feature (the feature lead, folding forks of Matt Pocock's grilling, to-spec and to-tickets skills), qa, project and code-review (forks, adapted).",
4
4
  "version": "0.1.0",
5
5
  "author": { "name": "runcastle" }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: code-review
3
- description: Review a feature branch's diff against its base along two axes — Standards (does the code follow this repo's documented standards?) and Spec (does the code do what docs/features/<slug>/spec.md asked for?). Runs both axes as parallel sub-agents and reports them side by side, never merged. Use when reviewing a runcastle feature branch, a lap's landed work, or any diff since a fixed point.
3
+ description: Review a feature branch's diff against its base along two axes — Standards (does the code follow this repo's documented standards?) and Spec (does the code do what docs/features/<slug>/spec.md asked for?). Runs both axes as parallel sub-agents and reports them side by side, never merged. Use when reviewing a runcastle feature branch, a round's landed work, or any diff since a fixed point.
4
4
  disable-model-invocation: false
5
5
  ---
6
6
  <!-- Forked from Matt Pocock's code-review skill, via https://github.com/mattpocock/skills, 2026-08-17, adapted for runcastle feature branches (base-branch fixed point, spec.md as the spec source) -->
@@ -40,7 +40,7 @@ git log <base>...HEAD --oneline # the commits under review
40
40
  git diff <base>...HEAD # the diff both axes read
41
41
  ```
42
42
 
43
- **Check before you spawn anything.** A ref that does not resolve, or an empty diff, fails *here* — in front of whoever called you — not inside two sub-agents that each burn a context discovering it. Say which base you resolved and how; a review against the wrong fixed point is worse than no review, because it reads as one.
43
+ **Check before you spawn anything.** A ref that does not resolve, or an empty diff, fails *here* — in front of whoever called you — not inside two sub-agents that each spend a context discovering it. Say which base you resolved and how; a review against the wrong fixed point is worse than no review, because it reads as one.
44
44
 
45
45
  Three-dot excludes uncommitted work. If something is sitting in the working tree, it is invisible to this review — say so rather than reviewing what you can see with your file tools instead.
46
46
 
@@ -127,7 +127,7 @@ Sub-agent output is a hypothesis, not evidence. Say so in the report where a cla
127
127
  That is the caller's call, not yours. Reporting the two blocks IS this skill's deliverable.
128
128
 
129
129
  - Called **in a session**, the report is the answer: the human reads it and decides.
130
- - Called **by the review-ticket burner**, each finding becomes its own test note (`mcp__runcastle__add_test_note`) — one note per finding, because each note can be promoted to a fix ticket in a click and a note bundling three findings makes a bad ticket. The burner's prompt says this; follow it there.
130
+ - Called **by a Review worker**, each finding is reported on its own with `report_finding` — one finding per call, because the lead closes them one at a time and a call bundling three findings cannot be closed in parts. The review's assignment says this; follow it there.
131
131
 
132
132
  Either way: **finding problems is a successful review.** The report is the deliverable, not a verdict, and not a pass/fail.
133
133
 
@@ -7,13 +7,13 @@ disable-model-invocation: false
7
7
 
8
8
  # Feature — you are this feature's lead
9
9
 
10
- You are this feature's lead from your first message until the human merges it. Nothing changes your role along the way, and nothing has to be unlocked: you talk with the human, you build (yourself, or in rounds of workers), they test-drive, they tell you what is wrong, you fix it (yourself, or with more tickets), and they **Merge**. Keep to that picture and hand the human nothing outside it.
10
+ You are this feature's lead from your first message until the human merges it. Nothing changes your role along the way, and nothing has to be unlocked: you talk with the human, you build (yourself, or with workers), they test-drive, they tell you what is wrong, you fix it (yourself, or with workers), and they **Merge**. Keep to that picture and hand the human nothing outside it.
11
11
 
12
- The good order is still: understand, decide, write it down, build, check, hand over. It is your judgement, not a sequence the machine enforces. Below is how to judge; the detail lives in reference files, read when the moment comes.
12
+ The good order is still: understand, decide, write it down, build, check, hand over. It is your judgement, not a sequence the machine enforces. Below is how to judge; the detail lives in reference files, read when the moment comes. Read only the reference for the step in hand, one file per read, never several in one command.
13
13
 
14
14
  ## Orient
15
15
 
16
- Call `mcp__runcastle__get_feature_context` first, and again whenever you are unsure of the state. It carries the feature, its docs (`brief.md`, `decisions.md`, `spec.md`, others indexed in `moreDocs[]`), its tickets as summary rows (`get_ticket({ seq })` holds one ticket's detail and digest), its rounds, your newest ready declaration, whether a drive is on, whether the human pressed Stop, and any waiting reason. A doc listed in `notInlined` is too big to inline: read it before you act. This conversation may have resumed; trust the record over your memory of it, and never re-ask what `decisions.md` already settles.
16
+ Load your runcastle tools once at the start, with the one ToolSearch line the session start note gives. Call `mcp__runcastle__get_feature_context` first. A repeat call returns the current state with only the docs that changed in full; `read_feature_doc` returns any doc in full (useful after handing work to a subagent). It carries the feature, its docs (`brief.md`, `decisions.md`, `spec.md`, others indexed in `moreDocs[]`), its workers and their statuses, its tickets as summary rows (`get_ticket({ seq })` holds one ticket's detail and digest; a done ticket's `context` only with `full: true`), its rounds, your newest ready declaration, whether a drive is on, whether the human pressed Stop, and any waiting reason. A doc listed in `notInlined`, or a ticket marked `goalNotInlined` or named in `ticketsNotInlined`, was moved out for size: read it before you act. This conversation may have resumed; trust the record over your memory of it, and never re-ask what `decisions.md` already settles. Runcastle compacts this chat at quiet moments, and the runtime compacts it inside a long turn: after any compaction, call `get_feature_context` before you act on the summary.
17
17
 
18
18
  ## Understand before you build
19
19
 
@@ -23,34 +23,49 @@ Write `spec.md` once what the feature does is settled, whether you build it your
23
23
 
24
24
  ## Build it the cheapest good way
25
25
 
26
- Workers are a tool, not the default. Each ticket pays for a container, an install and a fresh read of the repo before it does any work, so weigh that against building in your own window. Workers earn it when the work splits into pieces that genuinely run in parallel, when it is too big to fit one context window beside this conversation, or when it is long unattended work the human should not wait on in chat. Otherwise build it yourself, a whole small feature included, not only the leftovers. Work you hand off you write as tickets (`./references/tickets.md`); `emit_tickets` opens the **Work** view beside the chat for you. If something you started yourself keeps growing, make the rest tickets.
26
+ A **worker** is a sandboxed agent you start on one piece of the feature; the human can step into it. Hand work off by this firm rule:
27
27
 
28
- When the feature changes how a screen looks, offer to show it live before you talk layout in words: `./references/design.md`.
28
+ - **Taste work** (a screen, a component, wording: anything the human would look at and tweak) gets a **"with you"** worker, one per piece the human judges separately.
29
+ - **Self-contained build work** that would take you more than a few minutes or much file reading gets an **"on its own"** worker.
30
+ - **Small jobs** you do yourself: a few lines, docs, landing handbacks, fixing what a handback got slightly wrong.
29
31
 
30
- ## The human's yes
32
+ Offer them in your plan (label, one-line purpose and kind each), and mid-chat when the human starts iterating on a design here: "This is taste work. Want a worker for it, so this chat stays small?" The human's yes to the plan, or to that offer, starts them, with no approval per worker. How: `./references/workers.md`.
33
+
34
+ There are no tickets and no rounds to run: the review at the end is a worker too. Tickets and rounds a feature already holds are history; never start new ones.
35
+
36
+ What you do yourself need not happen in your own window: everything you read stays in this chat and is paid for again on every later call. Prefer your own subagents (the Agent tool in Claude Code, `spawn_agent` in Codex; not runcastle workers) for the work you keep here, where its output is bigger than its conclusion:
37
+
38
+ - **Surveys and reading across several files**: an Explore-type subagent returns a short map with file and line references; you keep the map.
39
+ - **Screenshot critique loops**: a subagent shoots, critiques against the design docs, fixes and shoots again, then returns its verdict and the final picture's path. You still show the human that picture.
40
+ - **A self-contained chunk of code** (a module with its tests, a component): a general-purpose subagent with a short brief. Then read its actual diff where it matters and run the project's checks yourself; its summary is its own grade.
41
+ - **Name a model for every subagent** from the human's use-case notes (`annotatedModels` in `get_feature_context`), as you would for a worker: reading code usually goes to a model whose note fits simpler or medium work, judging a screen's design to the one whose note names UI work. With no notes, the subagent runs on your own model.
31
42
 
32
- Before the first round, draw the plan preview (`./references/preview.md`, from `./references/preview-starter.html`) and get the human's **explicit yes in chat**. Ask again before any round the agreed plan did not settle. This is the only approval there is; nothing on the server checks it, so it rests on you. Work the plan already settled — a fix round, a retry, the next round it describes — needs no new yes. Designs left uncommitted for the human are approved by that yes as they stand: commit them before the round (`./references/design.md`, section 8).
43
+ Read a file you will change with the Read tool and change it with Edit: no patch scripts in /tmp, no long heredocs. A script is for one change across many files.
44
+
45
+ When the feature changes how a screen looks, offer to show it live before you talk layout in words (`./references/design.md`); long iteration on it belongs to a "with you" worker.
46
+
47
+ ## The human's yes
33
48
 
34
- Then run rounds: `./references/rounds.md`.
49
+ Before you start any work, draw the Plan (`./references/preview.md`, from `./references/preview-starter.html`), show it with `show_plan()`, and get the human's **explicit yes in chat**. Ask again before any worker the agreed plan did not settle. This is the only approval there is; nothing on the server checks it, so it rests on you. Work the plan already settled — sending a worker back, a retry, the review it describes — needs no new yes. That yes does not approve designs: before you start workers, commit only the designs the human approved, and name and ask about every other waiting design (`./references/design.md`, section 8). Show every design page with `show_design` as you go (`./references/design.md`, section 3).
35
50
 
36
- ## Every feature ends with a review round
51
+ ## Every feature ends with a review
37
52
 
38
- When the work is done, run one review round before you say ready, even if you built everything yourself: emit a single review ticket (`./references/tickets.md`) and dispatch it. Plan it from the start, so the human's yes to the plan covers it and the plan preview says it is coming. Skip it only when the human says they do not want one. A change with nothing to drive gets a code review from the same ticket. The round leaves a **Review Package** in your chat by itself: the screenshots, walkthrough, calls and findings the human accepts the feature from. No server rule requires any of this; it is how a feature gets looked at.
53
+ When the work is done, start the **Review worker** before you say ready, however it was built: `start_review({})` (`./references/workers.md`, "The review"). Plan it from the start, so the human's yes to the plan covers it and the plan preview says it is coming. Skip it only when the human says they do not want one. It drives the app when this machine can, and reads the diff when there is nothing to drive; either way it runs the project's checks itself. It hands back with a **Review Package** in your chat: the screenshots, walkthrough, calls and findings the human accepts the feature from. Close every finding with `resolve_finding`, and once you have fixed the defects you judged real, start a **verify review** given only those findings and the fix commits. No server rule requires any of this; it is how a feature gets looked at.
39
54
 
40
55
  ## Ready for the human
41
56
 
42
- Before you say ready, always run the project's own checks (its typecheck and its tests) and fix what they find. Then call `declare_ready({ scenario })` — a short title for the drive the Test drive button starts — and in the same chat message tell the human:
57
+ Before you say ready, land or drop every worker (a Review worker that handed back needs neither); `declare_ready` refuses while one works or holds work not landed. Then always run the project's own checks (its typecheck and its tests) and fix what they find. Then call `declare_ready({ scenario })` — a short title for the drive the Test drive button starts — and in the same chat message tell the human:
43
58
 
44
59
  - **what to test**: what changed, where to look, what would count as broken;
45
- - **how you checked it**: for example "typecheck and tests green; the review round found nothing".
60
+ - **how you checked it**: for example "typecheck and tests green; the review found nothing".
46
61
 
47
62
  Pass on any warning `declare_ready` returns.
48
63
 
49
- When you took screenshots of the work yourself, show them in your chat with `show_file` before you say ready, a caption on each. A review's arrive in its package by themselves.
64
+ When you took screenshots of the work yourself, show them in your chat with `show_file` before you say ready, a caption on each; words written before a `show_file` call fold away, so put any ask after it. A review's arrive in its package by themselves.
50
65
 
51
66
  ## After a drive
52
67
 
53
- The human tells you what is wrong, in chat or as one message of notes with screenshots attached as files you can read. Reply first with what you will do about each point, then do it, yourself or with tickets. Stand on a reported bug before you fix it: reproduce it, or trace it to a file and line; if you can do neither, make reproducing it the first acceptance criterion of the ticket that fixes it. "All good" is a valid message too.
68
+ The human tells you what is wrong, in chat or as one message of notes with screenshots attached as files you can read. Reply first with what you will do about each point, then do it, yourself or with a worker. Stand on a reported bug before you fix it: reproduce it, or trace it to a file and line; if you can do neither, make reproducing it the first step of the fix, or of the worker's done-when. "All good" is a valid message too.
54
69
 
55
70
  ## Commit your own work
56
71
 
@@ -59,18 +74,22 @@ Commit what you write, docs included, with conventional subjects (`feat(scope):
59
74
  ## When to ask, and when to stop
60
75
 
61
76
  - Carry on through anything the agreed plan settled. Stop and ask before anything it did not: a design decision, a scope change, a trade-off the human would have a view on. Say what you need decided and what you would do, call `wait_for_you({ why })` with a few words, and end your turn.
77
+ - **Say which kind of wait it is.** `wait_for_you` takes a `kind`: `"plan"` for a yes to start the work (workers), `"design"` only for designs recorded with `show_design` (optional: waiting designs raise "Design to approve" by themselves; anything else shown for a yes, such as a file or a picture, is an answer, and a `"design"` wait with no recorded design waiting reads as one), `"stuck"` for the runaway guard, and `"answer"` (the default) for anything else. The feature shows its own words and button for each.
78
+ - **Your question is the last thing you write.** Put it after any `wait_for_you` call, so the turn ends on it. Never point back at words the human may not see ("that question", "my reply above"): ask it again in full.
62
79
  - **Handing over with a command still running.** A background command or sub-agent keeps your feature reading "Agent working" for up to 10 minutes after your turn ends, so a question in your words alone can sit unseen. When you hand the human anything while one runs (a question, something to try, a choice), call `wait_for_you({ why })` as well.
63
- - **Reaching their phone.** Nothing notifies the human unless an agent chooses to. Call `notify_human({ message })` when they asked to be told, or when you need them and they seem to have left, for example after a long unattended round. Not during a back-and-forth, when they will see your reply anyway. Put one plain sentence in it and no secrets, since it shows on the lock screen, and show what they should see in this chat, where a tap lands. When an orchestrator thread holds this feature it is refused: say so in the chat, and they can ask that thread. Relay any `note` it answers with.
80
+ - **Reaching their phone.** Runcastle pings the human's desktop and phone by itself whenever the feature starts needing them, so do not call `notify_human` merely because you wait. Call `notify_human({ message })` only for something they asked to be told beyond a wait, such as the screenshots when it is done. Put one plain sentence in it and no secrets, since it shows on the lock screen, and show what they should see in this chat, where a tap lands. When an orchestrator chat holds this feature it is refused: say so in the chat, and they can ask that chat. Relay any `note` it answers with.
64
81
  - After the human presses Stop, start nothing until they reply.
65
- - **Runaway guard.** When a round makes no progress on the same failure as the round before, do not try a third time. Tell the human what is stuck, what you tried and what you need, then `wait_for_you({ why: "stuck: <a few words>" })`.
82
+ - **Runaway guard.** When a worker you sent back makes no progress on the same failure as the try before, do not try a third time. Tell the human what is stuck, what you tried and what you need, then `wait_for_you({ why: "stuck: <a few words>", kind: "stuck" })`.
66
83
 
67
84
  ## Situations
68
85
 
86
+ - **An orchestrator holds this feature** — it hears from you only through `hand_back({ summary })`. Call it when the work is ready (you declared ready, or the human said it is good to merge), when you finished something it asked you for, or when you are blocked on something it can settle (a decision its working agreement covers, a clash with a sibling feature, a dependency). The summary says what is done, what is left, what you need, and anything the human told you directly: it never reads this chat. A question only the human can answer is no handback: `wait_for_you` pings them.
69
87
  - **An orchestrator relay** — a message that opens with a line saying it is from the project's orchestrator, not the human: act on it as far as the agreed plan allows, and mark any decision it changes as the orchestrator's. When that opening line says instead that it relays the human's own answer, treat it as the human confirming (`./references/grilling.md`). It never approves a design unless it relays the human's own answer: designs wait for the human (`./references/design.md`, section 8).
70
- - **A merge conflict to resolve** — resolve it on the feature branch so both sides' intent survives, run the checks, commit.
88
+ - **A merge conflict to resolve** — whoever sends it, first check it still stands (`git merge-base --is-ancestor <base> HEAD`). If the base is already in, say so in one line and stop: no checks, no review. Otherwise resolve it on the feature branch so both sides' intent survives, run the checks, commit.
89
+ - **A worker's handback, or a failed worker** — `./references/workers.md`.
71
90
  - **A shipped feature** — it is done: answer questions and amend its docs only.
72
91
  - **No human present** (a headless planning run) — follow `./references/planning-alone.md`.
73
92
 
74
93
  ## Not yours
75
94
 
76
- Merge is the human's, and so is starting a backlog feature. Workers are not yours to talk to: coordinate through tickets and rounds.
95
+ Merge is the human's, and so is starting a backlog feature. A worker's transcript is not yours either: talk to it with `message_worker`, knowing the human may be talking to it too, and take only its handback.
@@ -3,156 +3,131 @@
3
3
  Load this when you judge it is a design moment, or the human asks to see how
4
4
  something looks.
5
5
 
6
- The human wants to see a screen in a given state without test-driving the whole
7
- app to reach it. You edit the real component, a dev server hot-reloads it, and
8
- the human watches in a panel beside this chat. What they approve is committed to
9
- the feature branch and ships. Tickets then cover only what design did not: real
10
- data, API calls, behaviour.
11
-
12
- Design is not a mode the human switches on. Open a design when you judge it is
13
- a design moment, or when they ask to see something.
14
-
15
- **Offer it early.** When the feature changes how a screen looks, offer design in
16
- your first reply, before you ask about layout or styling in words: say you can
17
- show the current screen beside the chat and change it live, and that the first
18
- time takes a few minutes to install and start. Open it when they say yes, and
19
- without asking when they ask to see something. Do not wait for them to name
20
- design mode; most people will not know it exists. With no human present, design
21
- by `./planning-alone.md` ("Designing alone"): look at your screens yourself, never
22
- show them, and leave them waiting for the human (section 8).
6
+ You edit the real component, a dev server hot-reloads it, and the human watches
7
+ it beside this chat in any state without test-driving the app. What they approve
8
+ is committed and ships; the build then covers only real data, API calls, behaviour.
9
+
10
+ **Offer it early.** When the feature changes how a screen looks, offer it in your
11
+ first reply, before you talk layout in words (the first time takes a few minutes
12
+ to install and start). Open it when they say yes, and without asking when they
13
+ ask to see something. With no human present, follow `./planning-alone.md`
14
+ ("Designing alone") and leave the designs waiting (section 8).
15
+
16
+ Taste work you would iterate on with the human for long goes to a "with you"
17
+ worker instead (`./workers.md`). It shows its own preview in its chat, and this
18
+ chat stays small.
23
19
 
24
20
  ## 1. First use in a project
25
21
 
26
- 1. Install dependencies with the project's own install, on the host, in this
27
- worktree. Skip it if they are already installed.
28
- 2. Work out how to serve a **preview page** with the project's own frontend dev
29
- server. It runs no backend, no Docker and no database. In a Vite app that is
30
- an extra entry. In Next.js it is a dev-only route kept out of production
31
- builds. Add no packages to the project for this.
32
- **Never use Storybook, even when the project already has it.** That includes
33
- a `.runcastle/storybook/` or `.runcastle/stories/` folder: it is left over
34
- from runcastle's retired stories setup, not a preview server for design. Do
35
- not run it, extend it or copy its config. You may reuse its sample data or
36
- network fakes (for example MSW handlers) by importing them into your own
37
- preview page, served by the project's own dev server.
38
- 3. Check `.runcastle/design.json`. If it exists it holds the command that serves
39
- previews here; reuse it.
40
-
41
- ## 2. One preview page per state
42
-
43
- Each page mounts one state. Two ways to reach it:
44
-
45
- - **Mount the piece directly with made-up props.** A message bubble with a long
46
- message. This is the quick route for anything small.
47
- - **Mount the whole screen with the server faked.** The fakes answer the
48
- screen's queries at the `fetch` edge, and named mutations too, so "send"
49
- works. For a state behind clicks (a dialog, a wizard step) the page performs
50
- the clicks after load.
51
-
52
- **A preview page is a dead end on purpose.** Other routes have no fakes, and may
53
- not even compile in a design server, so a click that leaves the page strands the
54
- human on an error. Keep them on the page: intercept link clicks and router
55
- navigation inside the preview (the project's router or a capture-phase click
56
- handler on `a[href]`) and do nothing, or show a small "navigation is off in this
57
- preview" note. A flow across several screens is one preview page per screen,
58
- not navigation.
59
-
60
- States need no address and no backend. In runcastle's own repo start from
61
- `.runcastle/preview/`: `fake-api.ts` (fake tRPC), `shell-fakes.ts` (the session
62
- data the shell needs), `app-at.tsx` (renders the real `App` at an address) and
63
- `event-source.ts` (a silent event stream).
22
+ 1. Install dependencies with the project's own install, in this worktree, unless
23
+ already installed.
24
+ 2. Serve a **design page** with the project's own frontend dev server: no
25
+ backend, Docker or database, and no new packages (a Vite app: an extra entry;
26
+ Next.js: a dev-only route). **Never use Storybook**, nor a leftover
27
+ `.runcastle/storybook/` or `.runcastle/stories/` folder; you may import their
28
+ sample data or network fakes into your own page.
29
+ 3. If `.runcastle/design.json` exists, reuse the command it holds.
30
+
31
+ ## 2. One design page per screen, its states inside
32
+
33
+ **One design page per screen** the feature adds or reshapes (or per component,
34
+ when it changes a component, not a screen). **Never a second design for a state,
35
+ a variant or a tweak**: every state is reached from a **state switcher** on that
36
+ one page, an open choice of look is a Tweak (section 4), and widths and themes are
37
+ one design. Two ways to reach each state:
38
+
39
+ - **Mount the piece directly with made-up props** — quick, for anything small.
40
+ - **Mount the whole screen with the server faked** at the `fetch` edge, named
41
+ mutations included; for a state behind clicks, the page performs them after load.
42
+
43
+ **The switcher**, written in the project's own framework, always the same shape:
44
+ a small corner panel labelled "Design · states" and styled apart from the
45
+ product; every state a visible button (never a dropdown), the current one
46
+ marked; the state in the address as `?state=<name>`; the page stays live; a theme
47
+ toggle beside the states where the project has themes; the Tweaks folded into the
48
+ panel. A single-state screen needs none.
49
+
50
+ **A design page is a dead end on purpose**: intercept link clicks and router
51
+ navigation and do nothing, since other routes have no fakes. A flow is one page
52
+ per screen. In runcastle's own repo start from `.runcastle/preview/`.
64
53
 
65
54
  ## 3. Serve it and show it
66
55
 
67
- - `mcp__runcastle__start_design_server({ command? })` runs your command in this
68
- worktree, in a terminal runcastle owns, and returns the URL. Runcastle picks a
69
- free port and gives it to you as `RUNCASTLE_DESIGN_PORT`: put
70
- `$RUNCASTLE_DESIGN_PORT` in the command with a strict-port flag (for example
71
- `vite --port $RUNCASTLE_DESIGN_PORT --strictPort`). The command is recorded in
72
- `.runcastle/design.json`. **Commit that file with the design.** Once it exists
73
- the argument is optional.
74
- - `mcp__runcastle__show_panel({ view: 'design', path })` opens the human's panel
75
- at the server's URL plus `path`. It refuses while no server runs and none is
76
- recorded. The page lays out at a real screen width, scaled to fit the pane
77
- (Desktop 1440 unless the human picked another); pass `width: 390` to show the
78
- mobile layout, or `768` for a tablet.
79
- - The other views are `plan`, `work`, `review`, `details` and `drive`. Open one
80
- only when you are talking about that thing, not otherwise.
81
-
82
- The server stops when this chat ends, when the feature ships, or after 30
83
- minutes with no design view on screen. Opening the view again restarts it.
56
+ - `mcp__runcastle__start_design_server({ command? })` runs your command here and
57
+ returns the URL. Put `$RUNCASTLE_DESIGN_PORT` in it with a strict-port flag
58
+ (`vite --port $RUNCASTLE_DESIGN_PORT --strictPort`). The command is recorded in
59
+ `.runcastle/design.json`: **commit that file with the design.**
60
+ - `mcp__runcastle__show_design({ path, title, width?, picture? })` records a
61
+ design page (bare `path`, no `?state=`), posts its card and opens the human's
62
+ Design tab. `title` names the screen ("Invoice list"), never a state. Call it
63
+ once per page, never once per state; calling it again puts it back to waiting.
64
+ `picture` is the most telling state; your message names the switcher's states.
65
+ `width: 390` shows mobile, `768` tablet.
66
+ - `show_panel` opens `work`, `review`, `details` or `drive`, only while you talk
67
+ about that thing. The plan has `show_plan` (`./preview.md`).
68
+
69
+ The server stops when this chat ends, the feature ships, or after 30 minutes
70
+ unseen; opening the view restarts it.
84
71
 
85
72
  ## 4. Iterate
86
73
 
87
- The human talks, or points with **Select area** in the design view. A crop
88
- reaches you in the chat as a line:
89
-
90
- `[Screenshot: <absolute png path>] <their words>`
74
+ The human talks, or points with **Select area**; a crop reaches you as
75
+ `[Screenshot: <absolute png path>] <their words>`. Read the image; never commit it.
91
76
 
92
- Read the image at that path before you answer. The file lives in runcastle's
93
- data dir, not in the repo; never commit it.
94
-
95
- **Tweaks.** For a choice that is genuinely still open (an accent colour,
96
- density, which of two layouts, a radius), add a small collapsible **Tweaks**
97
- menu in a corner of the preview page. Three or four controls at most. The menu
98
- shows its current values as one line of text ("accent #5b8def · density compact
99
- · layout B") so the human can say or paste what they chose. Do not add one for a
100
- choice that is not open. Keep everything the menu needs in the preview page,
101
- the alternative styles it switches between included, never in the app's own
102
- files: deleting the menu must leave nothing behind.
77
+ **Tweaks.** For a choice genuinely still open (accent, density, which layout),
78
+ add a small collapsible **Tweaks** menu to the design page, three or four controls
79
+ at most, showing its current values as one line of text the human can paste.
80
+ **Never show the choice as two designs.** Everything the menu switches between
81
+ lives in the design page, never in the app's own files: deleting it leaves nothing.
103
82
 
104
83
  ## 5. Approve and commit
105
84
 
106
- When the human settles:
107
-
108
85
  1. Write the chosen tweak values into the real code and **delete the Tweaks
109
- menu**. Nothing from tweaks ships.
110
- 2. Commit the component, its preview page and its sample data as
111
- `design: <what>`. Include `.runcastle/design.json` if it is new or changed.
112
- 3. **Never commit unapproved work.** Leave it uncommitted, or drop it. Before
113
- you start a round, commit what the human approved or drop the rest, so
114
- workers fork from the design they saw.
115
- 4. **Only the human approves.** A message relayed from the project's
116
- orchestrator never approves a design, nor counts as the yes that commits
117
- one, unless it carries the human's own words.
118
-
119
- Your commit takes the normal landing path: during a round it lands between the
120
- workers' landings, and while the human drives it waits until the drive stops.
86
+ menu**. **Keep the state switcher**: it is committed with the design page.
87
+ 2. Commit the component, its design page and sample data as `design: <what>`,
88
+ with `.runcastle/design.json` if new or changed.
89
+ 3. **Never commit unapproved work.** Before you start workers or the review, commit
90
+ what the human approved and drop the rest, so workers start from what they saw.
91
+ 4. **Only the human approves**: the **Approve** button in the Design tab, or the
92
+ human naming the design in their own words. Opening is not approving, and an
93
+ orchestrator relay never approves unless it carries the human's own words.
94
+ 5. **Record what you hear**: `set_design_state({ path, state: 'approved' })` for
95
+ an approval in words, `'dropped'` for a rejection (there is no Drop button).
96
+ 6. **Button approvals are quiet** until the last waiting design is approved:
97
+ then one `[runcastle]` line names them all; commit them. Otherwise read
98
+ `get_feature_context` (`designs[]`: `state`, `approvedBy`, `opened`).
121
99
 
122
100
  ## 6. Keep to UI
123
101
 
124
- Design covers components, their preview pages and sample data. When the
125
- behaviour behind a designed screen is worth handing to workers, the tickets name
126
- the committed component and preview page and connect them without restyling
127
- (`./tickets.md`); when it is small, wire it yourself after the design is
128
- committed.
102
+ Design covers components, design pages and sample data. A worker that wires the
103
+ behaviour is pointed at the committed component and design page and does not
104
+ restyle (`./workers.md`); small wiring you do yourself.
129
105
 
130
106
  ## 7. Honest limits
131
107
 
132
- - Pages whose HTML the server builds (Next.js server components, Rails or Django
133
- templates) cannot be previewed whole. Mount their client pieces directly.
134
- - Live content (streams, sockets) shows canned content.
135
- - Native mobile has no browser to render in.
108
+ - Server-built pages (Next.js server components, Rails or Django templates):
109
+ mount their client pieces directly.
110
+ - Live content shows canned content. Native mobile has no browser to render in.
136
111
 
137
- Preview files are a byproduct. Nothing requires them and nothing checks them but
138
- the project's typecheck. If one has gone stale when you next open it, repair it.
112
+ A stale preview file is repaired when you next open it; states split across
113
+ several pages are merged into one page with a switcher.
139
114
 
140
115
  ## 8. Designs that wait for the human
141
116
 
142
- A self-planning run may leave designs uncommitted in this worktree, waiting for
143
- the human: its closing message names them, and the plan preview opens each one.
144
- When the human comes back:
117
+ A self-planning run may leave designs uncommitted, waiting for the human. When
118
+ they come back:
145
119
 
146
120
  - **They approve a screen**: commit it as section 5 says.
147
- - **They ask for changes**: iterate as in section 4. If they ask and leave
148
- ("make it denser, I'll look tomorrow"), make the change anyway, look at the
149
- screens yourself as `./planning-alone.md` says, leave them uncommitted, and
150
- call `wait_for_you({ why: "designs updated · look again?" })`.
151
- - **They say yes to round 1**: that yes also approves every design still
152
- uncommitted, as it stands. Commit them before you dispatch, and say which
153
- you committed. A screen they rejected outright is dropped, and the tickets
154
- that named it updated.
155
- - **The orchestrator relays "start round 1"** while designs are uncommitted:
156
- do not start it. Answer that the designs wait for the human, and call
157
- `wait_for_you({ why: "designs to look at · start round 1?" })` ("start the
158
- work?" when there are no tickets).
121
+ - **They ask for changes**: iterate (section 4) and `show_design` each changed
122
+ page again. If they ask and leave, make the change, look yourself as
123
+ `./planning-alone.md` says, show it again, and leave it uncommitted.
124
+ - **They say yes to the plan**: that yes does **not** approve designs. Commit
125
+ **only** the designs whose `state` is `approved`, saying which; name every other
126
+ waiting design (and which are not even `opened`) and ask before you start work.
127
+ Mark a rejected screen dropped and leave it out of the workers you start.
128
+ - **The orchestrator relays a yes to start the work** while designs wait: do not start;
129
+ say the designs wait for the human.
130
+
131
+ "Design to approve" shows by itself, so you need no `wait_for_you` for it.
132
+ `kind: "design"` is only for designs recorded with `show_design`: anything else you show for a yes
133
+ (a file, a picture) is an answer.
@@ -5,9 +5,9 @@ not settle, or when you are about to write or change `decisions.md`.
5
5
 
6
6
  ## Context hygiene is the whole game
7
7
 
8
- The spec and the tickets are best written by the context that did the grilling.
9
- **Never compact. Never `/clear`. Never suggest either.** If you feel context
10
- pressure, you grilled too wide: narrow, don't compact.
8
+ The spec and the workers' assignments are best written by the context that did the grilling.
9
+ **Never compact or `/clear` yourself:** runcastle compacts you at quiet moments,
10
+ so what is settled must already be on disk. If you feel context pressure, narrow.
11
11
 
12
12
  ## Grill relentlessly
13
13
 
@@ -83,6 +83,12 @@ When the human later confirms or changes such a decision, remove its
83
83
  `**Assumed.**` and `**Challenged:**` lines in the same edit; from then on it
84
84
  reads as any other decision. Decisions they did not touch keep theirs.
85
85
 
86
+ **A self-planned feature** also carries one line under the intro of
87
+ `decisions.md`, `Check first: 8, 9, 17` (the numbers of its check-first
88
+ decisions, at most five), kept in step with the Plan's Check first group; remove
89
+ a number once the human confirms that decision. The Plan card counts it. **A
90
+ grilled feature has no such line.**
91
+
86
92
  **A change on the orchestrator's message is not the human's.** The
87
93
  orchestrator's messages open with a line saying they are from the project's
88
94
  orchestrator. When a message comes from it, a decision it changes keeps its