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