runcastle 1.5.3 → 1.5.5

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 (36) hide show
  1. package/bin/runcastle.js +2047 -2825
  2. package/drizzle/0052_friendly_black_tarantula.sql +1 -0
  3. package/drizzle/0053_soft_karma.sql +12 -0
  4. package/drizzle/0054_careless_stellaris.sql +3 -0
  5. package/drizzle/meta/0052_snapshot.json +1364 -0
  6. package/drizzle/meta/0053_snapshot.json +1283 -0
  7. package/drizzle/meta/0054_snapshot.json +1268 -0
  8. package/drizzle/meta/_journal.json +21 -0
  9. package/index.js +2045 -2823
  10. package/package.json +1 -1
  11. package/skills/packs/README.md +24 -29
  12. package/skills/packs/runcastle/.claude-plugin/plugin.json +1 -1
  13. package/skills/packs/runcastle/skills/feature/SKILL.md +72 -0
  14. package/skills/packs/runcastle/skills/feature/references/design.md +158 -0
  15. package/skills/packs/runcastle/skills/feature/references/grilling.md +101 -0
  16. package/skills/packs/runcastle/skills/feature/references/planning-alone.md +120 -0
  17. package/skills/packs/runcastle/skills/{ideate → feature}/references/preview-starter.html +11 -16
  18. package/skills/packs/runcastle/skills/{ideate → feature}/references/preview.md +33 -8
  19. package/skills/packs/runcastle/skills/feature/references/rounds.md +93 -0
  20. package/skills/packs/runcastle/skills/feature/references/spec.md +54 -0
  21. package/skills/packs/runcastle/skills/feature/references/tickets.md +229 -0
  22. package/skills/packs/runcastle/skills/project/SKILL.md +106 -63
  23. package/skills/packs/runcastle/skills/project/references/health-sweeps.md +11 -10
  24. package/skills/packs/runcastle/skills/project/references/triage.md +32 -30
  25. package/skills/packs/runcastle/skills/qa/SKILL.md +1 -2
  26. package/web/assets/index-B1MyomR6.css +1 -0
  27. package/web/assets/index-CPgKzYyE.js +186 -0
  28. package/web/index.html +2 -2
  29. package/skills/packs/runcastle/skills/design/SKILL.md +0 -73
  30. package/skills/packs/runcastle/skills/ideate/SKILL.md +0 -131
  31. package/skills/packs/runcastle/skills/lead/SKILL.md +0 -104
  32. package/skills/packs/runcastle/skills/revisit/SKILL.md +0 -55
  33. package/skills/packs/runcastle/skills/spec/SKILL.md +0 -47
  34. package/skills/packs/runcastle/skills/tickets/SKILL.md +0 -147
  35. package/web/assets/index-BYSs5Hdy.js +0 -186
  36. package/web/assets/index-bpL_iO_C.css +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcastle",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "description": "Burn tickets into shipped features with Claude Code.",
5
5
  "license": "FSL-1.1-ALv2",
6
6
  "type": "module",
@@ -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; `revisit` and `prepare` are 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. 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.
4
4
 
5
5
  ## The `runcastle` pack
6
6
 
@@ -8,13 +8,10 @@ Scope-specific skills, each namespaced `/runcastle:<skill>`:
8
8
 
9
9
  | Skill | Invoked | Does |
10
10
  |---|---|---|
11
- | `/runcastle:ideate` | entry for `kind=ideation` | grills the human, locks decisions incrementally, drives spec + tickets out of one unbroken window |
12
- | `/runcastle:spec` | by ideate | synthesizes `spec.md`, completes the `spec` phase |
13
- | `/runcastle:tickets` | by ideate | emits session-sized vertical-slice tickets via MCP, completes the `tickets` phase |
14
- | `/runcastle:qa` | entry for `kind=qa` | read-only Q&A over an existing feature; never advances phases |
11
+ | `/runcastle:feature` | entry for `kind=chat` | the feature's lead from its first message to merge: grills when the intent is unclear, 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/` |
12
+ | `/runcastle:qa` | entry for `kind=qa` | read-only Q&A over an existing feature; never changes it |
15
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` |
16
- | `/runcastle:revisit` | entry for `kind=revisit` | *original* — folds late information into a finished feature; on an Iterate from review, runs the whole front half of a lap |
17
- | `/runcastle:design` | by the feature chat's entry skills | *original* — live UI design beside the chat: preview pages, the design server and panel, Tweaks, `design:` commits; not an entry skill |
14
+ | `/runcastle:prepare` | entry for `kind=prepare` | *original* — establishes the project's prepared settings and drive machinery with the human |
18
15
  | `/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 |
19
16
 
20
17
  Layout (the verified plugin format — only `plugin.json` lives inside `.claude-plugin/`; `skills/` is a sibling at the plugin root):
@@ -26,16 +23,17 @@ packs/
26
23
  ├── .claude-plugin/
27
24
  │ └── plugin.json # name: "runcastle" → sets the /runcastle: namespace
28
25
  └── skills/
29
- ├── ideate/SKILL.md
30
- ├── spec/SKILL.md
31
- ├── tickets/SKILL.md
26
+ ├── feature/
27
+ │ ├── SKILL.md
28
+ │ └── references/ # grilling, spec, tickets, rounds, planning-alone, preview, design
32
29
  ├── qa/SKILL.md
33
30
  ├── project/
34
31
  │ ├── SKILL.md
35
32
  │ └── references/ # loaded on demand by SKILL.md, never up front
36
33
  │ ├── charter.md
37
- │ └── health-sweeps.md
38
- ├── revisit/SKILL.md
34
+ │ ├── health-sweeps.md
35
+ │ └── triage.md
36
+ ├── prepare/SKILL.md
39
37
  └── code-review/SKILL.md
40
38
  ```
41
39
 
@@ -68,7 +66,7 @@ The session launcher spawns Claude Code with the pack's **root** directory (the
68
66
  claude ... --plugin-dir "<abs path>/packages/skills/packs/runcastle" ...
69
67
  ```
70
68
 
71
- The `name` field in `plugin.json` becomes the invocation namespace, so the skills resolve as `/runcastle:ideate` and friends. The injected system prompt tells each session which entry skill to invoke for its kind (`/runcastle:ideate` for ideation, `/runcastle:qa` for Q&A).
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).
72
70
 
73
71
  ### Entry-skill isolation — settings deny rules, not `disable-model-invocation`
74
72
 
@@ -76,11 +74,11 @@ Every skill's `description` is loaded into every session in the pack, whether or
76
74
  not that session can use it. That is cheap for a skill the model might genuinely
77
75
  need and risky for one it must not run: a session carrying the descriptions of
78
76
  every other kind's entry skill is one description-match away from running
79
- another session's procedure — `project/SKILL.md` says "**Never run an ideation
80
- grilling**" while `ideate`'s description sits in the same list offering exactly
77
+ another session's procedure — `project/SKILL.md` says "**Never run a design
78
+ grilling**" while `feature`'s description sits in the same list offering exactly
81
79
  that.
82
80
 
83
- The five **session-entry** skills — `ideate`, `qa`, `revisit`, `project`,
81
+ The **session-entry** skills — today `feature`, `qa`, `project` and
84
82
  `prepare` — used to carry `disable-model-invocation:
85
83
  true` for that reason, on the build-era understanding that explicit invocation
86
84
  kept working (CC-INTEGRATION-NOTES §1). It no longer does: Claude Code now
@@ -98,13 +96,11 @@ live: **per-session settings**. The launcher launches each session with
98
96
  — for every entry skill that is not that kind's own (`entrySkillsFor` /
99
97
  `entrySkillDenyRules` in `packages/server/src/launcher`), and each injected
100
98
  prompt states the policy in one line. Same layering as the edit guard: the
101
- prompt says it, the harness enforces it. `chat` keeps both of its openings
102
- (`ideate` + `revisit`); `qa` — whose session kind was retired — is denied
103
- everywhere; `drive-fix` has no entry skill and denies all five.
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.
104
102
 
105
- The chained/reached skills — `spec` and `tickets` (invoked by name from inside
106
- `ideate`) and `code-review` (reached by description) — are in no
107
- deny list.
103
+ The reached skill — `code-review` (reached by description) — is in no deny list.
108
104
 
109
105
  The rule, for anything added later: **a session-entry skill goes into
110
106
  `ENTRY_SKILLS` and the per-kind table in
@@ -129,14 +125,13 @@ The standing convention across this pack:
129
125
  rule lives there, backed by `launcher/edit-guard.ts`, and is *not* restated in
130
126
  any skill).
131
127
  - **Procedures belong to the skill.** One skill owns each procedure in full;
132
- `revisit/SKILL.md` §Lap mode is the whole lap procedure, `ideate/SKILL.md` §1
133
- is the whole grilling procedure.
128
+ `feature/references/grilling.md` is the whole grilling procedure.
134
129
  - **Where a skill names a fact the prompt also names, it points instead of
135
- restating** — the shape is `ideate/SKILL.md`'s "The injected system prompt
136
- carries the slug and paths; trust `get_feature_context` for the live state."
130
+ restating** — "the injected system prompt carries the slug and paths; trust
131
+ `get_feature_context` for the live state."
137
132
  - **Where two skills need the same procedure, the second delegates by
138
- reference** — "grill the way `/runcastle:ideate` §1 does" rather than a
139
- second copy that ages differently.
133
+ reference** — "grill the way `feature/references/grilling.md` does" rather
134
+ than a second copy that ages differently.
140
135
  - **A rule the hook enforces is stated once, as enforced, not as advice.** The
141
136
  `qa` kind's write refusals are server-side; `qa/SKILL.md` says so rather than
142
137
  asking nicely.
@@ -150,7 +145,7 @@ ticket instead.
150
145
 
151
146
  1. Create `packs/<pack-name>/.claude-plugin/plugin.json` with at least `{ "name": "<pack-name>" }` — `name` sets the `/<pack-name>:` namespace.
152
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.
153
- 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`, `complete_phase`).
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`).
154
149
  4. Pass another `--plugin-dir` for it at launch.
155
150
 
156
151
  ## Not a pack: `../burner/`
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcastle",
3
- "description": "Runcastle phase-scoped skills for the MCP feature pipeline: ideate, spec, tickets, qa, project, code-review (forks of Matt Pocock's grilling, to-spec, to-tickets and code-review, adapted) plus revisit, prepare and lead (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), qa, project and code-review (forks, adapted), plus prepare (original).",
4
4
  "version": "0.1.0",
5
5
  "author": { "name": "runcastle" }
6
6
  }
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: feature
3
+ description: The runcastle feature lead's entry skill — the whole guidance for a feature's agent from its first message to merge, with the detail in reference files read when needed.
4
+ disable-model-invocation: false
5
+ ---
6
+ <!-- Folds in runcastle's former ideate, lead, spec, tickets, revisit and design skills (themselves forked from Matt Pocock's grilling, to-spec and to-tickets skills), 2026-10-24 -->
7
+
8
+ # Feature — you are this feature's lead
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.
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.
13
+
14
+ ## Orient
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.
17
+
18
+ ## Understand before you build
19
+
20
+ When the intent is unclear, grill: one question at a time, each with your recommended answer and why. Look facts up in the code rather than asking; ask the human only for decisions. Record each settled decision in `docs/features/<slug>/decisions.md` the moment it settles. When something surfaces that is plainly its own feature, offer to park it as a backlog feature with `create_feature({ title, oneLiner, brief, draft: true })` and get back to this one. When the brief is already concrete, skip the grilling. How: `./references/grilling.md`.
21
+
22
+ Write `spec.md` once what the feature does is settled, whether you build it yourself or hand it to workers: it is the record of what the feature is. How: `./references/spec.md`.
23
+
24
+ ## Build it the cheapest good way
25
+
26
+ Small work you do yourself: a few files, a change that would not split into tickets, a fix a round left behind. Work worth handing to sandboxed workers you write as tickets (`./references/tickets.md`); `emit_tickets` opens the **Work** view beside the chat for you. If a "small" change keeps growing, make it tickets.
27
+
28
+ When the feature changes how a screen looks, offer to show it live before you talk layout in words: `./references/design.md`.
29
+
30
+ ## The human's yes
31
+
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).
33
+
34
+ Then run rounds: `./references/rounds.md`.
35
+
36
+ ## Review is your call
37
+
38
+ Run a review ticket when the change is worth an independent look: it spans several areas, it has a surface a human operates, or you are not sure of it. Skip it when it is not, and say why. No rule requires one.
39
+
40
+ ## Ready for the human
41
+
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:
43
+
44
+ - **what to test**: what changed, where to look, what would count as broken;
45
+ - **how you checked it**: for example "typecheck and tests green; no review agent, since it's a one-file style change".
46
+
47
+ Pass on any warning `declare_ready` returns.
48
+
49
+ ## After a drive
50
+
51
+ 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.
52
+
53
+ ## Commit your own work
54
+
55
+ Commit what you write, docs included, with conventional subjects (`feat(scope): …`, `fix(scope): …`, `docs(scope): …`), and only once the project's checks are green for code. **Never reword a `ticket(<seq>): …` or `runcastle: …` commit**: those belong to the machinery and other branches already carry them. While the human drives, your commits wait until the drive stops.
56
+
57
+ ## When to ask, and when to stop
58
+
59
+ - 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.
60
+ - After the human presses Stop, start nothing until they reply.
61
+ - **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>" })`.
62
+
63
+ ## Situations
64
+
65
+ - **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).
66
+ - **A merge conflict to resolve** — resolve it on the feature branch so both sides' intent survives, run the checks, commit.
67
+ - **A shipped feature** — it is done: answer questions and amend its docs only.
68
+ - **No human present** (a headless planning run) — follow `./references/planning-alone.md`.
69
+
70
+ ## Not yours
71
+
72
+ Merge is the human's, and so is starting a backlog feature. Workers are not yours to talk to: coordinate through tickets and rounds.
@@ -0,0 +1,158 @@
1
+ # Design — iterate on the real screen, beside the chat
2
+
3
+ Load this when you judge it is a design moment, or the human asks to see how
4
+ something looks.
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).
23
+
24
+ ## 1. First use in a project
25
+
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).
64
+
65
+ ## 3. Serve it and show it
66
+
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.
84
+
85
+ ## 4. Iterate
86
+
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>`
91
+
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.
103
+
104
+ ## 5. Approve and commit
105
+
106
+ When the human settles:
107
+
108
+ 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.
121
+
122
+ ## 6. Keep to UI
123
+
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.
129
+
130
+ ## 7. Honest limits
131
+
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.
136
+
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.
139
+
140
+ ## 8. Designs that wait for the human
141
+
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:
145
+
146
+ - **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).
@@ -0,0 +1,101 @@
1
+ # Grilling, and recording what was decided
2
+
3
+ Load this when the human's intent is unclear and you are about to interview
4
+ them, or when you are about to write or change `decisions.md`.
5
+
6
+ ## Context hygiene is the whole game
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.
11
+
12
+ ## Grill relentlessly
13
+
14
+ Interview the human about every aspect of the feature until you reach a
15
+ genuinely shared understanding. Walk each branch of the design tree, resolving
16
+ dependencies between decisions one at a time.
17
+
18
+ - **One question at a time.** Wait for the answer before the next. Asking
19
+ several at once is bewildering.
20
+ - **Always recommend an answer.** Never ask a bare question — put your
21
+ recommended answer and say why. The human corrects or confirms.
22
+ - **Look up facts; ask only for decisions.** If a fact is discoverable in the
23
+ codebase — how something works now, what a type looks like, whether a pattern
24
+ exists — read the repo and find it. Never make the human be your grep.
25
+ *Decisions* are theirs: put each one to them and wait.
26
+ - **Model the domain as you go**: challenge terms that conflict with existing
27
+ usage, sharpen fuzzy words to one canonical meaning ("you said 'account' —
28
+ Customer or User?"), invent concrete edge cases that force precision, and
29
+ cross-check claims against the code ("your code cancels whole Orders, but you
30
+ just said partial — which is right?").
31
+ - **Offer to cut deferred scope.** When the feature turns out larger than it
32
+ first looked, or the human is unsure of part of it, say so plainly with your
33
+ recommendation: build the part they are sure of, and put the rest in the
34
+ backlog as its own feature. It is an offer; the human decides.
35
+ - **Put scope creep in the backlog instead of swallowing it.** When something
36
+ plainly its own feature surfaces, offer
37
+ `mcp__runcastle__create_feature({ title, oneLiner, brief, draft: true })`: a
38
+ backlog feature, no branch, nothing written, with the `brief` carrying why you
39
+ deferred it and what it must not swallow. When it builds on this feature, pass
40
+ `dependsOn: [<this feature's slug>]` so it cannot start before this one
41
+ merges. If the human wants it started by itself once this one ships, they can
42
+ mark it up next on its page. Then get back to this feature. Backlog features
43
+ are the only kind you create.
44
+
45
+ Grilling is done when the human agrees you share the picture. That agreement
46
+ is made on the plan preview (`./preview.md`), not in chat alone.
47
+
48
+ ## Record each decision at once
49
+
50
+ The moment a decision settles, append it to `docs/features/<slug>/decisions.md`
51
+ — **immediately, one at a time, never batched at the end.** If this session
52
+ dies mid-grill, what was settled must already be on disk.
53
+
54
+ ```markdown
55
+ ## <n>. <short decision title>
56
+ **Decision:** <the choice, in the project's domain vocabulary>
57
+ **Why:** <the reason / the trade-off chosen over the alternatives>
58
+ ```
59
+
60
+ A decision made without the human (see `./planning-alone.md`) keeps that shape
61
+ and adds a line naming the main alternative it was chosen over. A decision the
62
+ challenger disagreed with adds a further line with its reason:
63
+
64
+ ```markdown
65
+ ## <n>. <short decision title>
66
+ **Decision:** <the choice>
67
+ **Why:** <the reason>
68
+ **Assumed.** Alternative: <the main alternative>.
69
+ **Challenged:** <the challenger's reason>.
70
+ ```
71
+
72
+ For example:
73
+
74
+ ```markdown
75
+ ## 4. Tags and dates are left out of the PDF
76
+ **Decision:** The PDF carries the title and body only.
77
+ **Why:** The brief asks for the note, not its filing.
78
+ **Assumed.** Alternative: a small footer with tags and the last-edited date.
79
+ ```
80
+
81
+ When the human later confirms or changes such a decision, remove its
82
+ `**Assumed.**` and `**Challenged:**` lines in the same edit; from then on it
83
+ reads as any other decision. Decisions they did not touch keep theirs.
84
+
85
+ **A change on the orchestrator's message is not the human's.** The
86
+ orchestrator's messages open with a line saying they are from the project's
87
+ orchestrator. When a message comes from it, a decision it changes keeps its
88
+ `**Assumed.**` line, or gains one, and adds
89
+ `**Changed by the orchestrator:** <why>`. The human has not seen it, and the
90
+ record must say who decided. A message whose opening line says instead that it
91
+ relays the human's own answer is the human confirming: remove the marks, that
92
+ line included.
93
+
94
+ **Later information supersedes, it does not rewrite.** When the human comes
95
+ back with something new after decisions were written — a constraint they
96
+ remembered, a change of mind — append it as a new decision that names the one it
97
+ replaces ("Supersedes: 4"), and amend `spec.md` where it is affected.
98
+
99
+ Keep `decisions.md` free of implementation minutiae: it records what was
100
+ decided and why. Whenever it changes and a `preview.html` exists, redraw the
101
+ preview in the same move (`./preview.md`). Commit it like any other doc.
@@ -0,0 +1,120 @@
1
+ # Planning with no human present
2
+
3
+ Load this when your briefing says no human is present: a headless run that
4
+ plans the feature while the human is away. With a human in the chat, grill them
5
+ instead (`./grilling.md`); nothing here binds that conversation.
6
+
7
+ You still look facts up, model the domain and park scope creep as
8
+ `./grilling.md` says. What changes is who answers.
9
+
10
+ **This run plans; it does not build.** Whatever the plan says,
11
+ never call `dispatch_round` in this run: no round starts without the human's
12
+ yes. You write the feature's docs (`decisions.md`, `spec.md`, `preview.html`)
13
+ and, when the work is worth handing to workers, its tickets. The one exception
14
+ is designing its screens (**Designing alone**, below): for that, and only that,
15
+ you may install dependencies and write components, preview pages and sample
16
+ data. Write no other code.
17
+
18
+ - **One turn.** Do the whole plan in this one turn. Never end the turn to ask a
19
+ question or to report progress: nobody will reply, and ending the turn ends
20
+ the run.
21
+ - **Frontier rounds.** Work in question rounds. A question round is every open
22
+ question that does not depend on an unanswered one. Write each as you would
23
+ put it to the human, with your recommended answer and the main alternative,
24
+ then accept your own recommendations and record them. Then ask what those
25
+ answers opened: that is the next question round. Write each to
26
+ `decisions.md` as it is decided (`./grilling.md`, the `**Assumed.**` shape),
27
+ not at the end, so a run that dies keeps what it had.
28
+ - **Depth rule.** Record a decision only if it changes what the feature is or
29
+ does for its users, or the human might reasonably overturn it. Anything an
30
+ engineer would settle while building (wording, internal formats, test
31
+ coverage) is not a question; it goes to the spec as detail.
32
+ - **Exactly one challenger.** When a question round would be empty, run one
33
+ separate agent: the Agent tool in Claude Code, `spawn_agent` in Codex. Give it
34
+ only the brief and `decisions.md`. Ask it for (a) design branches never asked,
35
+ within the depth rule, and (b) decisions it would have made differently, with
36
+ its reason. Do not tell it what you expect to hear. Ask its branches as one
37
+ more question round and decide them, with whatever they open. A decision it
38
+ disagrees with gets a `**Challenged:**` line with its reason, and your own
39
+ answer stands. There is no second pass. If you have no tool that runs a
40
+ separate agent, challenge your own plan as a separate pass and write in
41
+ `decisions.md` that the challenge was not independent.
42
+ - **A refused tool is not a wait.** If a tool is refused, do not retry it and do
43
+ not wait: decide on what you know, and treat that decision as one to check
44
+ first.
45
+ - **A timed-out tool is not a refused one.** A timeout is no answer, and the
46
+ call may have landed anyway. Retry it once, checking first that it did not
47
+ land: before repeating `emit_tickets`, `update_ticket` or `cancel_ticket`,
48
+ read `list_tickets` and send only what is missing. If the retry times out
49
+ too, carry on and say so in the closing message.
50
+ - **Check first.** Pick at most five decisions for the human to check first:
51
+ guesses about their intent the brief did not settle, decisions that force
52
+ several others, and decisions the challenger disagreed with. They open the
53
+ preview's decisions part (`./preview.md`).
54
+ - **Design, but never show.** You may design the feature's screens
55
+ (**Designing alone**, below), but never call `show_panel`: nobody is there to
56
+ look, and the human opens the designs when they choose.
57
+
58
+ ## Designing alone
59
+
60
+ Design when the feature **adds a screen or changes a screen's layout**. A small
61
+ visual change (a colour, a label, one control) is described in the plan
62
+ instead: it would not repay the install. A feature with no screen designs
63
+ nothing.
64
+
65
+ - **When.** Once the decisions are recorded and before the spec, so the spec,
66
+ the tickets and the preview can name the designed components.
67
+ - **How.** As `./design.md` says for an attended chat: the project's own
68
+ install, the project's own frontend dev server, one preview page per state,
69
+ sample data, navigation off, real components, the project's design docs.
70
+ Design against the components on the feature's base branch; never read
71
+ another feature's worktree. If a screen needs a shared component changed, change
72
+ it here and say so in the closing message.
73
+ - **Tweaks for taste.** Where a look is genuinely open (two layouts, a density,
74
+ an accent), leave a Tweaks menu on that preview page instead of guessing
75
+ (`./design.md`, Tweaks). **At most two
76
+ open choices per screen**: past that, pick, and list your picks in the
77
+ closing message. Everything the menu needs, the alternative styles included,
78
+ lives in the preview page, never in the app's own files.
79
+ - **Look at your own screens.** Call `start_design_server({ command })`, which
80
+ also records the command so the human's Open in design starts it later. Then
81
+ check every preview page. With `agent-browser` on the PATH: `agent-browser
82
+ open <url>`, `agent-browser screenshot <path>` (a temporary path, never in the
83
+ repo), read the image, critique it against the project's design docs, fix it,
84
+ and look again; `agent-browser close` when done. Without it, check that each
85
+ page compiles and serves, and say in the closing message that you never saw
86
+ them. The design server stops by itself when this run ends.
87
+ - **A screen you cannot serve** (no frontend dev server you can work out, a
88
+ page the server builds, native mobile) is a hand mock in `preview.html`, as
89
+ any plan draws one. Say so in the closing message. Do not stop or ask.
90
+ - **Leave the designs uncommitted.** Never commit a component, preview page,
91
+ sample data or `.runcastle/design.json` you designed: only the human's
92
+ approval commits them. Commit your docs by path, so nothing designed rides
93
+ along.
94
+ - **In the preview**, each designed screen is a designed-screen entry
95
+ (`./preview.md`, Designed screens) naming its component file and preview page.
96
+ A ticket that wires one follows `./tickets.md` on designed screens.
97
+
98
+ ## Straight through, then ask
99
+
100
+ 1. Write `spec.md` (`./spec.md`) once the decisions are recorded.
101
+ 2. Write the tickets if the work is worth handing to workers (`./tickets.md`);
102
+ otherwise the plan says you will build it yourself.
103
+ 3. Draw the preview and run its self-check (`./preview.md`).
104
+ 4. Commit the docs.
105
+ 5. **End with one closing chat message** that covers the plan only: that it was
106
+ made without the human, how many decisions it holds and which are to check
107
+ first (by number and title), whether it is tickets or work you will do
108
+ yourself, and anything that stopped you doing the job (a refused or failed
109
+ tool the plan needed, and what you decided without it). Leave out the state
110
+ of tools and connectors the plan did not need. **If you designed**, also
111
+ name each designed screen, the open Tweaks choices, any shared component you
112
+ changed, and whether you saw the screens in screenshots or only checked that
113
+ they compile, and say that the yes commits the designs as they stand. Close the message by asking
114
+ the human for their yes to start round 1 (or to start the work, if there are
115
+ no tickets).
116
+ 6. Call `mcp__runcastle__wait_for_you({ why: "start round 1?" })`, or
117
+ `mcp__runcastle__wait_for_you({ why: "designs to look at · start round 1?" })`
118
+ if you designed. With no tickets, say "start the work?" in place of "start
119
+ round 1?". Then end the turn. The human answers in this chat when they
120
+ are back; their yes is what starts the work, in a later turn.