runcastle 1.4.8 → 1.5.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.
- package/bin/runcastle.js +10604 -7555
- package/drizzle/0045_nappy_adam_destine.sql +3 -0
- package/drizzle/0046_polite_nightcrawler.sql +20 -0
- package/drizzle/0046_project_scenario_runner.sql +1 -0
- package/drizzle/0047_clear_betty_brant.sql +3 -0
- package/drizzle/0048_new_northstar.sql +1 -0
- package/drizzle/0050_tan_manta.sql +1 -0
- package/drizzle/0051_ambiguous_talkback.sql +1 -0
- package/drizzle/0052_friendly_black_tarantula.sql +1 -0
- package/drizzle/0053_soft_karma.sql +12 -0
- package/drizzle/meta/0045_snapshot.json +1220 -0
- package/drizzle/meta/0046_snapshot.json +1227 -0
- package/drizzle/meta/0047_snapshot.json +1349 -0
- package/drizzle/meta/0048_snapshot.json +1356 -0
- package/drizzle/meta/0050_snapshot.json +1349 -0
- package/drizzle/meta/0051_snapshot.json +1356 -0
- package/drizzle/meta/0052_snapshot.json +1364 -0
- package/drizzle/meta/0053_snapshot.json +1283 -0
- package/drizzle/meta/_journal.json +63 -0
- package/hook-client.ts +110 -9
- package/index.js +10601 -7552
- package/package.json +1 -1
- package/skills/burner/implement-ticket.md +0 -1
- package/skills/burner/review-ticket.md +7 -5
- package/skills/burner/verify-fixes.md +4 -2
- package/skills/packs/README.md +24 -28
- package/skills/packs/runcastle/.claude-plugin/plugin.json +1 -1
- package/skills/packs/runcastle/skills/feature/SKILL.md +72 -0
- package/skills/packs/runcastle/skills/feature/references/design.md +132 -0
- package/skills/packs/runcastle/skills/feature/references/grilling.md +99 -0
- package/skills/packs/runcastle/skills/feature/references/planning-alone.md +70 -0
- package/skills/packs/runcastle/skills/{ideate → feature}/references/preview-starter.html +27 -17
- package/skills/packs/runcastle/skills/{ideate → feature}/references/preview.md +67 -8
- package/skills/packs/runcastle/skills/feature/references/rounds.md +91 -0
- package/skills/packs/runcastle/skills/feature/references/spec.md +54 -0
- package/skills/packs/runcastle/skills/feature/references/tickets.md +229 -0
- package/skills/packs/runcastle/skills/prepare/SKILL.md +19 -5
- package/skills/packs/runcastle/skills/prepare/references/recipes.md +6 -2
- package/skills/packs/runcastle/skills/project/SKILL.md +115 -14
- package/skills/packs/runcastle/skills/project/references/charter.md +3 -3
- package/skills/packs/runcastle/skills/project/references/health-sweeps.md +5 -5
- package/skills/packs/runcastle/skills/project/references/triage.md +21 -24
- package/skills/packs/runcastle/skills/qa/SKILL.md +1 -2
- package/web/assets/index-CT9k1kz0.css +1 -0
- package/web/assets/index-DVR7VbWW.js +186 -0
- package/web/index.html +2 -2
- package/skills/packs/runcastle/skills/ideate/SKILL.md +0 -128
- package/skills/packs/runcastle/skills/revisit/SKILL.md +0 -78
- package/skills/packs/runcastle/skills/spec/SKILL.md +0 -47
- package/skills/packs/runcastle/skills/tickets/SKILL.md +0 -119
- package/web/assets/index-CUoLAKY6.js +0 -188
- package/web/assets/index-bNgQedte.css +0 -1
package/package.json
CHANGED
|
@@ -87,7 +87,6 @@ Whatever the commands are, spend them well — a full suite on a monorepo is min
|
|
|
87
87
|
- **Left undone** — adjacent work you noticed and deliberately did not do, so the next agent inherits the observation instead of re-finding it.
|
|
88
88
|
|
|
89
89
|
Write it in plain prose, for a reader who does not have your context. It is read: the tickets that depend on yours are handed it verbatim, and so is the agent that reviews this whole lap. **Never commit `DIGEST.md`** — it is harvested from the workspace, not from the repo, and a committed one is diff noise. It is a **success artifact only**: if you are blocked and writing `BLOCKED.md`, write no digest — `BLOCKED.md` is your record.
|
|
90
|
-
|
|
91
90
|
## Keep the drive machinery true
|
|
92
91
|
|
|
93
92
|
{{DRIVE_NOTES}}
|
|
@@ -13,7 +13,7 @@ You review it in **exactly one of two modes**, and you pick which before you do
|
|
|
13
13
|
|
|
14
14
|
You leave two deliverables behind: the **findings** (one report per finding, typed) and the **digest** (the lap's account — see step 5; it is not an afterthought). Its first line is a standalone one-liner naming the lap, what landed, the counts and the mode you ran: that line is the one the review page renders on arrival, and the account behind it is what the human opens when they want more.
|
|
15
15
|
|
|
16
|
-
You are **not** implementing anything. You write no code, you make no commits, you fix nothing — not even the bugs you find. Every defect you report
|
|
16
|
+
You are **not** implementing anything. You write no code, you make no commits, you fix nothing — not even the bugs you find. Every defect you report goes to the feature's lead when this round ends, and the lead decides how it is fixed; fixing one yourself would collide with that. Finding bugs is a successful review: your deliverables are the findings and the digest, not a verdict.
|
|
17
17
|
|
|
18
18
|
There is **no human to ask** — everything you need is in this prompt and in the repo.
|
|
19
19
|
|
|
@@ -33,7 +33,7 @@ You run **non-interactively** — your agent CLI in print/exec mode, no terminal
|
|
|
33
33
|
|
|
34
34
|
Its `goal` says what to verify and its `acceptanceCriteria` say how you will know. Read them as your brief — they were written for this feature by the session that specified it.
|
|
35
35
|
|
|
36
|
-
**The ticket prescribes the drive, not the mode.** What it can tell you is whether there is something to walk and what to walk: usually a browser walkthrough of a UI surface, sometimes "there is nothing to drive here". Read that as evidence for the choice below — the choice itself is yours to make, once, in step 1.
|
|
36
|
+
**The ticket prescribes the drive, not the mode.** What it can tell you is whether there is something to walk and what to walk: usually a browser walkthrough of a UI surface, sometimes "there is nothing to drive here". Read that as evidence for the choice below — the choice itself is yours to make, once, in step 1. A ticket that says "use Gates" is evidence about whether there is a surface, nothing more: when its `acceptanceCriteria` name a screen, flow or state a human could operate and a drive is available, the mode is Drive, whatever the ticket's text tells you. And "the installed or host runcastle doesn't have this branch's code yet" is never a reason against a drive — the review pass runs on the installed runcastle, but `review_drive` boots `{{FEATURE_BRANCH}}` itself, its own code, migrations and assets. One real review obeyed a ticket that prescribed Gates on exactly that reason, and a UI feature reached the human without ever being driven.
|
|
37
37
|
|
|
38
38
|
## Whether a drive is available
|
|
39
39
|
|
|
@@ -70,7 +70,7 @@ Two questions, in this order:
|
|
|
70
70
|
1. **Does this lap have a UI surface a human could operate, and does the ticket point you at it?** The `acceptanceCriteria` naming screens, flows or empty states is a yes. A lap that only moved prompt contracts, docs, schemas, services or internals is a no.
|
|
71
71
|
2. **Is a drive available?** The section above answers this from the host — it is a fact, not a judgement.
|
|
72
72
|
|
|
73
|
-
Both yes → **Drive mode**, step 2a. Anything else → **Gates mode**, step 2b. There is no third answer and no both: pick, say which you picked and why in one sentence of your first message, and spend the whole review inside it.
|
|
73
|
+
Both yes → **Drive mode**, step 2a — even when the ticket's text tells you to use Gates. Anything else → **Gates mode**, step 2b. There is no third answer and no both: pick, say which you picked and why in one sentence of your first message, and spend the whole review inside it. When your pick goes against a mode the ticket states, that same sentence says so and gives the reason — for example, "Drive mode, against the ticket's Gates: the criteria name the settings screen and a drive is available."
|
|
74
74
|
|
|
75
75
|
### 2a. Drive mode — walk the app
|
|
76
76
|
|
|
@@ -89,6 +89,8 @@ Either way: report an observation saying the drive could not start and which of
|
|
|
89
89
|
|
|
90
90
|
**Never build your own environment to drive in.** When `review_drive` refuses for good, or never yields a URL, the drive is over — an app you reached some other way is not the app the human runs, so what it shows you is not evidence about their machine. Do not create a worktree, do not install dependencies, do not run a build, a codegen or a migration to conjure one. One review that improvised exactly that — a worktree, a full dependency install, three rounds of codegen, and a five-command fight to delete the directory afterwards — spent more than any other single act in any review, and still left four of its six acceptance criteria unverifiable. Gates mode is what is left to you, and it is enough: read the server's gate results, read the diff along both axes, and report every criterion the drive would have covered as an observation saying it is unverified.
|
|
91
91
|
|
|
92
|
+
{{SCENARIOS}}
|
|
93
|
+
|
|
92
94
|
**Walk the app with `agent-browser`.** Its core loop, which you repeat:
|
|
93
95
|
|
|
94
96
|
```
|
|
@@ -180,7 +182,7 @@ A defect is also what a fix ticket can act on, so it carries something to act *f
|
|
|
180
182
|
|
|
181
183
|
**Severity is `high` when an acceptance criterion is unmet, when data/flow is broken, or when every criterion passes and the human's problem is still not solved**; `medium` for a real defect that is not that, `low` for the rest. It orders and labels; it never gates.
|
|
182
184
|
|
|
183
|
-
**Report defects highest severity first.**
|
|
185
|
+
**Report defects highest severity first.** Your defects reach the feature's lead in the order you report them, and the lead reads them in that order to decide what gets fixed first.
|
|
184
186
|
|
|
185
187
|
Report as you find things, never in a batch at the end: a finding you have sent survives an iteration that ends early, and one you were saving up does not. There is no closing wrap-up call — the digest (step 5) is the summary, and your observations render inside the page's collapsed *Full account* disclosure, alongside the digest's long account.
|
|
186
188
|
|
|
@@ -204,7 +206,7 @@ Its shape — `Lap <N>: <what landed, in the language of the product> · <X> def
|
|
|
204
206
|
Lap 2: the review page now opens on state and one action · 3 defects found, 2 fixed in-run · Gates mode
|
|
205
207
|
```
|
|
206
208
|
|
|
207
|
-
The counts are the ones you know as you write: how many defects you reported, and how many of those
|
|
209
|
+
The counts are the ones you know as you write: how many defects you reported, and how many of those were fixed in-run — `0`, since nothing burns a fix while the round is still running; the lead fixes them afterwards. The lap number is `lap` on `mcp__runcastle__get_feature_context`. If you could not drive, the line still names the mode you actually ran.
|
|
208
210
|
|
|
209
211
|
**The rest is not a review log. It is the lap's long account**, and the page keeps it behind a collapsed *Full account* disclosure at the bottom, with your observations — it is what the human opens when the one-liner is not enough, so it is neither the first thing they read nor rendered verbatim at the top. Write it anyway and write it well: they arrive wanting one question answered — *what did this lap actually do?* — and you are the agent best placed to answer it: you ran last, you hold the spec, and you have every implementer's own account above.
|
|
210
212
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Verification pass — tour and verify
|
|
2
2
|
|
|
3
|
-
You are running a bounded verification pass on `{{FEATURE_BRANCH}}` against `{{BASE_BRANCH}}`. The pass you verify is {{VERIFIES_PASS}}. The mode is inherited and never
|
|
3
|
+
You are running a bounded verification pass on `{{FEATURE_BRANCH}}` against `{{BASE_BRANCH}}`. The pass you verify is {{VERIFIES_PASS}}. The mode is inherited, not chosen afresh — with one exception. A Gates that pass took only because its ticket told it to is not inherited blindly: the review's own rule applies, so when the acceptance criteria name a screen, flow or state a human could operate and a drive is available, the mode is Drive. "The installed or host runcastle doesn't have this branch's code" is never a reason against a drive, because `review_drive` boots `{{FEATURE_BRANCH}}` itself.
|
|
4
4
|
|
|
5
5
|
{{DRIVE_AVAILABILITY}}
|
|
6
6
|
|
|
@@ -38,6 +38,8 @@ In **Drive mode**, call `mcp__runcastle__review_drive({ action: "start" })`, sta
|
|
|
38
38
|
|
|
39
39
|
{{DRIVE_INSTRUCTIONS}}
|
|
40
40
|
|
|
41
|
+
{{SCENARIOS}}
|
|
42
|
+
|
|
41
43
|
In **Gates mode**, read each fix diff against its finding and read the server's gate results for the fixed branch, below. Do not perform a second two-axis review of the whole branch. Read the branch from where you stand — `git diff {{BASE_BRANCH}}...{{FEATURE_BRANCH}}`, and `git show {{FEATURE_BRANCH}}:<path>` for a whole file: never check `{{FEATURE_BRANCH}}` out, and never leave a worktree holding it. A scratch worktree you cannot avoid is `git worktree add --detach <path> <sha>`, removed with `git worktree remove <path>` before you finish — never `git worktree add <path> <branch>`, which checks the branch out and leaves your directory holding it against the next session's launch.
|
|
42
44
|
|
|
43
45
|
Whichever mode you are in, the server has already run this project's verify commands on the fixed `{{FEATURE_BRANCH}}` — these are its results. **Never run a verify command yourself**: the checkout you are in is the human's, on `{{BASE_BRANCH}}` outside a drive, so it would test the base's code, not the fixes.
|
|
@@ -46,7 +48,7 @@ Whichever mode you are in, the server has already run this project's verify comm
|
|
|
46
48
|
|
|
47
49
|
Report findings through `mcp__runcastle__report_finding` as usual. Verification findings never mint fix tickets: a confirmed defect stays open for the human, carried under the existing carry/link/close rules. The ordinary review auto-fix cap is {{AUTO_FIX_CAP}}.
|
|
48
50
|
|
|
49
|
-
Write `{{DIGEST_PATH}}`. Its first line must name the
|
|
51
|
+
Write `{{DIGEST_PATH}}`. Its first line must name the mode you ran and say "verification pass" (for example, `Drive verification pass`) — and, when that is Drive over an inherited Gates, say why. Summarise which fixes held, which did not, and anything plainly broken on the tour. No `<promise>` markers inside the digest — the completion signal is a line in your message, never a line in this file. If the pass cannot run at all, write `{{BLOCKED_PATH}}` with the precise reason instead. Either way, the file you write is the last thing you do before signalling COMPLETE.
|
|
50
52
|
|
|
51
53
|
End the digest with exactly this machine-readable block. Name the mode actually completed; after a Drive failure followed by full Gates use `gates` and keep the drive failure in the one-line reason:
|
|
52
54
|
|
package/skills/packs/README.md
CHANGED
|
@@ -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; `
|
|
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,12 +8,10 @@ Scope-specific skills, each namespaced `/runcastle:<skill>`:
|
|
|
8
8
|
|
|
9
9
|
| Skill | Invoked | Does |
|
|
10
10
|
|---|---|---|
|
|
11
|
-
| `/runcastle:
|
|
12
|
-
| `/runcastle:
|
|
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:
|
|
14
|
+
| `/runcastle:prepare` | entry for `kind=prepare` | *original* — establishes the project's prepared settings and drive machinery with the human |
|
|
17
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 |
|
|
18
16
|
|
|
19
17
|
Layout (the verified plugin format — only `plugin.json` lives inside `.claude-plugin/`; `skills/` is a sibling at the plugin root):
|
|
@@ -25,16 +23,17 @@ packs/
|
|
|
25
23
|
├── .claude-plugin/
|
|
26
24
|
│ └── plugin.json # name: "runcastle" → sets the /runcastle: namespace
|
|
27
25
|
└── skills/
|
|
28
|
-
├──
|
|
29
|
-
├──
|
|
30
|
-
|
|
26
|
+
├── feature/
|
|
27
|
+
│ ├── SKILL.md
|
|
28
|
+
│ └── references/ # grilling, spec, tickets, rounds, planning-alone, preview, design
|
|
31
29
|
├── qa/SKILL.md
|
|
32
30
|
├── project/
|
|
33
31
|
│ ├── SKILL.md
|
|
34
32
|
│ └── references/ # loaded on demand by SKILL.md, never up front
|
|
35
33
|
│ ├── charter.md
|
|
36
|
-
│
|
|
37
|
-
|
|
34
|
+
│ ├── health-sweeps.md
|
|
35
|
+
│ └── triage.md
|
|
36
|
+
├── prepare/SKILL.md
|
|
38
37
|
└── code-review/SKILL.md
|
|
39
38
|
```
|
|
40
39
|
|
|
@@ -67,7 +66,7 @@ The session launcher spawns Claude Code with the pack's **root** directory (the
|
|
|
67
66
|
claude ... --plugin-dir "<abs path>/packages/skills/packs/runcastle" ...
|
|
68
67
|
```
|
|
69
68
|
|
|
70
|
-
The `name` field in `plugin.json` becomes the invocation namespace, so the skills resolve as `/runcastle:
|
|
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).
|
|
71
70
|
|
|
72
71
|
### Entry-skill isolation — settings deny rules, not `disable-model-invocation`
|
|
73
72
|
|
|
@@ -75,11 +74,11 @@ Every skill's `description` is loaded into every session in the pack, whether or
|
|
|
75
74
|
not that session can use it. That is cheap for a skill the model might genuinely
|
|
76
75
|
need and risky for one it must not run: a session carrying the descriptions of
|
|
77
76
|
every other kind's entry skill is one description-match away from running
|
|
78
|
-
another session's procedure — `project/SKILL.md` says "**Never run
|
|
79
|
-
grilling**" while `
|
|
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
|
|
80
79
|
that.
|
|
81
80
|
|
|
82
|
-
The
|
|
81
|
+
The **session-entry** skills — today `feature`, `qa`, `project` and
|
|
83
82
|
`prepare` — used to carry `disable-model-invocation:
|
|
84
83
|
true` for that reason, on the build-era understanding that explicit invocation
|
|
85
84
|
kept working (CC-INTEGRATION-NOTES §1). It no longer does: Claude Code now
|
|
@@ -97,13 +96,11 @@ live: **per-session settings**. The launcher launches each session with
|
|
|
97
96
|
— for every entry skill that is not that kind's own (`entrySkillsFor` /
|
|
98
97
|
`entrySkillDenyRules` in `packages/server/src/launcher`), and each injected
|
|
99
98
|
prompt states the policy in one line. Same layering as the edit guard: the
|
|
100
|
-
prompt says it, the harness enforces it. `chat`
|
|
101
|
-
|
|
102
|
-
|
|
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.
|
|
103
102
|
|
|
104
|
-
The
|
|
105
|
-
`ideate`) and `code-review` (reached by description) — are in no
|
|
106
|
-
deny list.
|
|
103
|
+
The reached skill — `code-review` (reached by description) — is in no deny list.
|
|
107
104
|
|
|
108
105
|
The rule, for anything added later: **a session-entry skill goes into
|
|
109
106
|
`ENTRY_SKILLS` and the per-kind table in
|
|
@@ -128,14 +125,13 @@ The standing convention across this pack:
|
|
|
128
125
|
rule lives there, backed by `launcher/edit-guard.ts`, and is *not* restated in
|
|
129
126
|
any skill).
|
|
130
127
|
- **Procedures belong to the skill.** One skill owns each procedure in full;
|
|
131
|
-
`
|
|
132
|
-
is the whole grilling procedure.
|
|
128
|
+
`feature/references/grilling.md` is the whole grilling procedure.
|
|
133
129
|
- **Where a skill names a fact the prompt also names, it points instead of
|
|
134
|
-
restating** — the
|
|
135
|
-
|
|
130
|
+
restating** — "the injected system prompt carries the slug and paths; trust
|
|
131
|
+
`get_feature_context` for the live state."
|
|
136
132
|
- **Where two skills need the same procedure, the second delegates by
|
|
137
|
-
reference** — "grill the way
|
|
138
|
-
second copy that ages differently.
|
|
133
|
+
reference** — "grill the way `feature/references/grilling.md` does" rather
|
|
134
|
+
than a second copy that ages differently.
|
|
139
135
|
- **A rule the hook enforces is stated once, as enforced, not as advice.** The
|
|
140
136
|
`qa` kind's write refusals are server-side; `qa/SKILL.md` says so rather than
|
|
141
137
|
asking nicely.
|
|
@@ -149,7 +145,7 @@ ticket instead.
|
|
|
149
145
|
|
|
150
146
|
1. Create `packs/<pack-name>/.claude-plugin/plugin.json` with at least `{ "name": "<pack-name>" }` — `name` sets the `/<pack-name>:` namespace.
|
|
151
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.
|
|
152
|
-
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`, `emit_tickets`, `record_event`).
|
|
153
149
|
4. Pass another `--plugin-dir` for it at launch.
|
|
154
150
|
|
|
155
151
|
## Not a pack: `../burner/`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "runcastle",
|
|
3
|
-
"description": "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).",
|
|
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.
|
|
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 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 (`./references/grilling.md`).
|
|
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,132 @@
|
|
|
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 never
|
|
21
|
+
open a design.
|
|
22
|
+
|
|
23
|
+
## 1. First use in a project
|
|
24
|
+
|
|
25
|
+
1. Install dependencies with the project's own install, on the host, in this
|
|
26
|
+
worktree. Skip it if they are already installed.
|
|
27
|
+
2. Work out how to serve a **preview page** with the project's own frontend dev
|
|
28
|
+
server. It runs no backend, no Docker and no database. In a Vite app that is
|
|
29
|
+
an extra entry. In Next.js it is a dev-only route kept out of production
|
|
30
|
+
builds. Add no packages to the project for this.
|
|
31
|
+
**Never use Storybook, even when the project already has it.** That includes
|
|
32
|
+
a `.runcastle/storybook/` or `.runcastle/stories/` folder: it is left over
|
|
33
|
+
from runcastle's retired stories setup, not a preview server for design. Do
|
|
34
|
+
not run it, extend it or copy its config. You may reuse its sample data or
|
|
35
|
+
network fakes (for example MSW handlers) by importing them into your own
|
|
36
|
+
preview page, served by the project's own dev server.
|
|
37
|
+
3. Check `.runcastle/design.json`. If it exists it holds the command that serves
|
|
38
|
+
previews here; reuse it.
|
|
39
|
+
|
|
40
|
+
## 2. One preview page per state
|
|
41
|
+
|
|
42
|
+
Each page mounts one state. Two ways to reach it:
|
|
43
|
+
|
|
44
|
+
- **Mount the piece directly with made-up props.** A message bubble with a long
|
|
45
|
+
message. This is the quick route for anything small.
|
|
46
|
+
- **Mount the whole screen with the server faked.** The fakes answer the
|
|
47
|
+
screen's queries at the `fetch` edge, and named mutations too, so "send"
|
|
48
|
+
works. For a state behind clicks (a dialog, a wizard step) the page performs
|
|
49
|
+
the clicks after load.
|
|
50
|
+
|
|
51
|
+
**A preview page is a dead end on purpose.** Other routes have no fakes, and may
|
|
52
|
+
not even compile in a design server, so a click that leaves the page strands the
|
|
53
|
+
human on an error. Keep them on the page: intercept link clicks and router
|
|
54
|
+
navigation inside the preview (the project's router or a capture-phase click
|
|
55
|
+
handler on `a[href]`) and do nothing, or show a small "navigation is off in this
|
|
56
|
+
preview" note. A flow across several screens is one preview page per screen,
|
|
57
|
+
not navigation.
|
|
58
|
+
|
|
59
|
+
States need no address and no backend. In runcastle's own repo start from
|
|
60
|
+
`.runcastle/preview/`: `fake-api.ts` (fake tRPC), `shell-fakes.ts` (the session
|
|
61
|
+
data the shell needs), `app-at.tsx` (renders the real `App` at an address) and
|
|
62
|
+
`event-source.ts` (a silent event stream).
|
|
63
|
+
|
|
64
|
+
## 3. Serve it and show it
|
|
65
|
+
|
|
66
|
+
- `mcp__runcastle__start_design_server({ command? })` runs your command in this
|
|
67
|
+
worktree, in a terminal runcastle owns, and returns the URL. Runcastle picks a
|
|
68
|
+
free port and gives it to you as `RUNCASTLE_DESIGN_PORT`: put
|
|
69
|
+
`$RUNCASTLE_DESIGN_PORT` in the command with a strict-port flag (for example
|
|
70
|
+
`vite --port $RUNCASTLE_DESIGN_PORT --strictPort`). The command is recorded in
|
|
71
|
+
`.runcastle/design.json`. **Commit that file with the design.** Once it exists
|
|
72
|
+
the argument is optional.
|
|
73
|
+
- `mcp__runcastle__show_panel({ view: 'design', path })` opens the human's panel
|
|
74
|
+
at the server's URL plus `path`. It refuses while no server runs and none is
|
|
75
|
+
recorded. The page lays out at a real screen width, scaled to fit the pane
|
|
76
|
+
(Desktop 1440 unless the human picked another); pass `width: 390` to show the
|
|
77
|
+
mobile layout, or `768` for a tablet.
|
|
78
|
+
- The other views are `plan`, `work`, `review`, `details` and `drive`. Open one
|
|
79
|
+
only when you are talking about that thing, not otherwise.
|
|
80
|
+
|
|
81
|
+
The server stops when this chat ends, when the feature ships, or after 30
|
|
82
|
+
minutes with no design view on screen. Opening the view again restarts it.
|
|
83
|
+
|
|
84
|
+
## 4. Iterate
|
|
85
|
+
|
|
86
|
+
The human talks, or points with **Select area** in the design view. A crop
|
|
87
|
+
reaches you in the chat as a line:
|
|
88
|
+
|
|
89
|
+
`[Screenshot: <absolute png path>] <their words>`
|
|
90
|
+
|
|
91
|
+
Read the image at that path before you answer. The file lives in runcastle's
|
|
92
|
+
data dir, not in the repo; never commit it.
|
|
93
|
+
|
|
94
|
+
**Tweaks.** For a choice that is genuinely still open (an accent colour,
|
|
95
|
+
density, which of two layouts, a radius), add a small collapsible **Tweaks**
|
|
96
|
+
menu in a corner of the preview page. Three or four controls at most. The menu
|
|
97
|
+
shows its current values as one line of text ("accent #5b8def · density compact
|
|
98
|
+
· layout B") so the human can say or paste what they chose. Do not add one for a
|
|
99
|
+
choice that is not open.
|
|
100
|
+
|
|
101
|
+
## 5. Approve and commit
|
|
102
|
+
|
|
103
|
+
When the human settles:
|
|
104
|
+
|
|
105
|
+
1. Write the chosen tweak values into the real code and **delete the Tweaks
|
|
106
|
+
menu**. Nothing from tweaks ships.
|
|
107
|
+
2. Commit the component, its preview page and its sample data as
|
|
108
|
+
`design: <what>`. Include `.runcastle/design.json` if it is new or changed.
|
|
109
|
+
3. **Never commit unapproved work.** Leave it uncommitted, or drop it. Before
|
|
110
|
+
you start a round, commit what the human approved or drop the rest, so
|
|
111
|
+
workers fork from the design they saw.
|
|
112
|
+
|
|
113
|
+
Your commit takes the normal landing path: during a round it lands between the
|
|
114
|
+
workers' landings, and while the human drives it waits until the drive stops.
|
|
115
|
+
|
|
116
|
+
## 6. Keep to UI
|
|
117
|
+
|
|
118
|
+
Design covers components, their preview pages and sample data. When the
|
|
119
|
+
behaviour behind a designed screen is worth handing to workers, the tickets name
|
|
120
|
+
the committed component and preview page and connect them without restyling
|
|
121
|
+
(`./tickets.md`); when it is small, wire it yourself after the design is
|
|
122
|
+
committed.
|
|
123
|
+
|
|
124
|
+
## 7. Honest limits
|
|
125
|
+
|
|
126
|
+
- Pages whose HTML the server builds (Next.js server components, Rails or Django
|
|
127
|
+
templates) cannot be previewed whole. Mount their client pieces directly.
|
|
128
|
+
- Live content (streams, sockets) shows canned content.
|
|
129
|
+
- Native mobile has no browser to render in.
|
|
130
|
+
|
|
131
|
+
Preview files are a byproduct. Nothing requires them and nothing checks them but
|
|
132
|
+
the project's typecheck. If one has gone stale when you next open it, repair it.
|
|
@@ -0,0 +1,99 @@
|
|
|
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.** When a message
|
|
86
|
+
comes from the project's orchestrator, a decision it changes keeps its
|
|
87
|
+
`**Assumed.**` line, or gains one, and adds
|
|
88
|
+
`**Changed by the orchestrator:** <why>`. The human has not seen it, and the
|
|
89
|
+
record must say who decided. A message that relays the human's own answer is
|
|
90
|
+
the human confirming: remove the marks, that line included.
|
|
91
|
+
|
|
92
|
+
**Later information supersedes, it does not rewrite.** When the human comes
|
|
93
|
+
back with something new after decisions were written — a constraint they
|
|
94
|
+
remembered, a change of mind — append it as a new decision that names the one it
|
|
95
|
+
replaces ("Supersedes: 4"), and amend `spec.md` where it is affected.
|
|
96
|
+
|
|
97
|
+
Keep `decisions.md` free of implementation minutiae: it records what was
|
|
98
|
+
decided and why. Whenever it changes and a `preview.html` exists, redraw the
|
|
99
|
+
preview in the same move (`./preview.md`). Commit it like any other doc.
|
|
@@ -0,0 +1,70 @@
|
|
|
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.** Never edit code, never install, and
|
|
11
|
+
never call `dispatch_round` in this run, whatever the plan says: no round starts
|
|
12
|
+
without the human's 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 — nothing else.
|
|
14
|
+
|
|
15
|
+
- **One turn.** Do the whole plan in this one turn. Never end the turn to ask a
|
|
16
|
+
question or to report progress: nobody will reply, and ending the turn ends
|
|
17
|
+
the run.
|
|
18
|
+
- **Frontier rounds.** Work in question rounds. A question round is every open
|
|
19
|
+
question that does not depend on an unanswered one. Write each as you would
|
|
20
|
+
put it to the human, with your recommended answer and the main alternative,
|
|
21
|
+
then accept your own recommendations and record them. Then ask what those
|
|
22
|
+
answers opened: that is the next question round. Write each to
|
|
23
|
+
`decisions.md` as it is decided (`./grilling.md`, the `**Assumed.**` shape),
|
|
24
|
+
not at the end, so a run that dies keeps what it had.
|
|
25
|
+
- **Depth rule.** Record a decision only if it changes what the feature is or
|
|
26
|
+
does for its users, or the human might reasonably overturn it. Anything an
|
|
27
|
+
engineer would settle while building (wording, internal formats, test
|
|
28
|
+
coverage) is not a question; it goes to the spec as detail.
|
|
29
|
+
- **Exactly one challenger.** When a question round would be empty, run one
|
|
30
|
+
separate agent: the Agent tool in Claude Code, `spawn_agent` in Codex. Give it
|
|
31
|
+
only the brief and `decisions.md`. Ask it for (a) design branches never asked,
|
|
32
|
+
within the depth rule, and (b) decisions it would have made differently, with
|
|
33
|
+
its reason. Do not tell it what you expect to hear. Ask its branches as one
|
|
34
|
+
more question round and decide them, with whatever they open. A decision it
|
|
35
|
+
disagrees with gets a `**Challenged:**` line with its reason, and your own
|
|
36
|
+
answer stands. There is no second pass. If you have no tool that runs a
|
|
37
|
+
separate agent, challenge your own plan as a separate pass and write in
|
|
38
|
+
`decisions.md` that the challenge was not independent.
|
|
39
|
+
- **A refused tool is not a wait.** If a tool is refused, do not retry it and do
|
|
40
|
+
not wait: decide on what you know, and treat that decision as one to check
|
|
41
|
+
first.
|
|
42
|
+
- **A timed-out tool is not a refused one.** A timeout is no answer, and the
|
|
43
|
+
call may have landed anyway. Retry it once, checking first that it did not
|
|
44
|
+
land: before repeating `emit_tickets`, `update_ticket` or `cancel_ticket`,
|
|
45
|
+
read `list_tickets` and send only what is missing. If the retry times out
|
|
46
|
+
too, carry on and say so in the closing message.
|
|
47
|
+
- **Check first.** Pick at most five decisions for the human to check first:
|
|
48
|
+
guesses about their intent the brief did not settle, decisions that force
|
|
49
|
+
several others, and decisions the challenger disagreed with. They open the
|
|
50
|
+
preview's decisions part (`./preview.md`).
|
|
51
|
+
- **No design.** Never open a design (`./design.md`): nobody is there to look.
|
|
52
|
+
|
|
53
|
+
## Straight through, then ask
|
|
54
|
+
|
|
55
|
+
1. Write `spec.md` (`./spec.md`) once the decisions are recorded.
|
|
56
|
+
2. Write the tickets if the work is worth handing to workers (`./tickets.md`);
|
|
57
|
+
otherwise the plan says you will build it yourself.
|
|
58
|
+
3. Draw the preview and run its self-check (`./preview.md`).
|
|
59
|
+
4. Commit the docs.
|
|
60
|
+
5. **End with one closing chat message** that covers the plan only: that it was
|
|
61
|
+
made without the human, how many decisions it holds and which are to check
|
|
62
|
+
first (by number and title), whether it is tickets or work you will do
|
|
63
|
+
yourself, and anything that stopped you doing the job (a refused or failed
|
|
64
|
+
tool the plan needed, and what you decided without it). Leave out the state
|
|
65
|
+
of tools and connectors the plan did not need. Close the message by asking
|
|
66
|
+
the human for their yes to start round 1 (or to start the work, if there are
|
|
67
|
+
no tickets).
|
|
68
|
+
6. Call `mcp__runcastle__wait_for_you({ why: "start round 1?" })`, then end the
|
|
69
|
+
turn. The human answers in this chat when they are back; their yes is what
|
|
70
|
+
starts the work, in a later turn.
|