monkeyshape 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,49 +19,24 @@ src/core/client.ts arch/host-access
19
19
  mshape check failed: 2 problems
20
20
  ```
21
21
 
22
- ## Install
22
+ ## Quick start
23
23
 
24
24
  ```sh
25
- bun add -d monkeyshape effect @biomejs/biome typescript @types/bun
25
+ bunx --package monkeyshape mshape init my-app
26
26
  ```
27
27
 
28
- monkeyshape runs on Bun and asks your `tsc` and `biome` which files they cover; `effect` is a
29
- peer dependency. Add these files (the tests build a repo from exactly these blocks):
28
+ A new repo whose gate (`bun run check`) passes, with one starter test: Bun, TypeScript, Effect,
29
+ beads, the configs, CI, and five skills for your coding agent. Then the working loop, one chat each:
30
30
 
31
- ```jsonc
32
- // tsconfig.json
33
- { "extends": "monkeyshape/tsconfig.base.json", "include": ["src", "test", "shape.config.ts"] }
34
- ```
35
-
36
- ```jsonc
37
- // biome.json
38
- {
39
- "root": true,
40
- "extends": ["monkeyshape/biome"],
41
- "files": { "includes": ["src/**", "test/**", "shape.config.ts", "*.json"] }
42
- }
43
- ```
44
-
45
- ```ts
46
- // shape.config.ts
47
- import { defineConfig } from "monkeyshape";
48
-
49
- export default defineConfig({
50
- arch: {
51
- modules: {
52
- core: { description: "Deterministic logic. No host I/O." },
53
- adapters: { description: "Host I/O behind services.", mayImport: ["core"], hostAccess: true },
54
- },
55
- },
56
- });
57
- ```
58
-
59
- ```md
60
- <!-- AGENTS.md -->
61
- # My project: commands, gotchas and decision authority for agents, in 150 lines or fewer.
62
- ```
31
+ 1. `/roadmap` with a brain-dump: the direction, and one deferred epic per goal.
32
+ 2. `/milestone` with your priorities: a plan with acceptance on real data, beads, and
33
+ tracks, each its own worktree from `mshape track new`.
34
+ 3. `/track` in each track's worktree: the agent works its queue and opens PRs.
35
+ 4. `/handoff` when a chat's context runs low; a fresh chat runs `/track` to continue.
36
+ 5. `/review-pr <n>` in its own chat; you merge.
63
37
 
64
- Then make it your gate: `tsc && biome ci --error-on-warnings && mshape check && bun test`.
38
+ The conventions in full: [docs/workflow.md](docs/workflow.md). An existing repo:
39
+ [docs/adopting.md](docs/adopting.md).
65
40
 
66
41
  ## What `mshape check` enforces
67
42
 
@@ -72,6 +47,7 @@ Then make it your gate: `tsc && biome ci --error-on-warnings && mshape check &&
72
47
  | `refs` | Docs and comments that point at paths, scripts or decisions that don't exist |
73
48
  | `budgets` | Bloated `AGENTS.md`, decision logs and memories; oversized files |
74
49
  | `coverage` | Code that escaped the typechecker or the linter and rots silently |
50
+ | `skills` | Installed skills that agents can't see (a broken `.claude/skills` link) or that lag the package |
75
51
 
76
52
  Existing violations can be grandfathered with `mshape baseline --init`; counts may then only
77
53
  go down. Every escape hatch (`// shape-ignore <rule>: <reason>`, config allowances) needs a reason.
@@ -0,0 +1,131 @@
1
+ # The working loop
2
+
3
+ How a repo made by `mshape init` is worked, by a human and coding agents together. Read this
4
+ once after `init`; the skills it names carry the detail, so you don't need it again.
5
+
6
+ The split: **skills carry judgement, the `mshape` CLI carries everything deterministic.** A
7
+ skill interviews, proposes, writes prose and grooms beads; it never builds a worktree or a
8
+ file layout by hand, because the CLI does that and is tested. Each skill is started by name
9
+ in a fresh chat, so your message can be just the skill and your intent.
10
+
11
+ ## Three horizons, three files
12
+
13
+ Plan in detail only what is near. Each horizon has one home and one way of staying true.
14
+
15
+ | Horizon | Home | Written by | Kept true by |
16
+ |---|---|---|---|
17
+ | Direction: months | docs/roadmap.md, plus one deferred beads epic per goal | `/roadmap` | Rewritten in place at each milestone boundary |
18
+ | Milestone: several PRs from several agents | plan/MILESTONE.md | `/milestone` | Frozen for the milestone, replaced at the next |
19
+ | Track state: today | the track's handoff, in `.handoffs` | `/track`, `/handoff` | Overwritten at every handoff |
20
+
21
+ - **The roadmap** opens with a status table, so nobody reads the design as a spec. It is
22
+ never cited by code or by normative docs (AGENTS.md, DECISIONS.md, skills): name the file,
23
+ but the refs check rejects links into its sections. Its goals are deferred epics with no children until a milestone pulls them
24
+ in, so they never crowd `bd ready`.
25
+ - **The milestone plan** says the goal and how you'll know it is met on real data, where
26
+ things stand, the tracks with their beads and acceptance, the interfaces between tracks,
27
+ decision points and what is deferred. When a track diverges from it, the track says so in
28
+ its handoff; a divergence that changes another track's work is a conversation with the
29
+ human, not an edit to the plan. Only handoffs and beads cite it.
30
+ - **A handoff** is what a fresh chat reads to continue a track, and what the human reads to
31
+ decide what to relay. Handoffs live inside git's directory and are linked into every
32
+ checkout as `.handoffs`; they are never committed, so there is one live copy.
33
+
34
+ What a change did and what it showed goes in the **PR body**, which is the narrative the
35
+ human actually reads. Long investigations go in a dated note under `notes/`, which nothing
36
+ normative may cite.
37
+
38
+ Everything else has one home too:
39
+
40
+ - A rule a machine can check is **a check**, whose message gives the reason and the fix. A
41
+ domain invariant is **a test named after it**. The local reason for some code is **a
42
+ comment at that code**.
43
+ - **DECISIONS.md** holds only live decisions worth their budget: a surprising external fact
44
+ that was measured, or a choice between real alternatives that would be expensive to undo.
45
+ The best entries name the tempting wrong fix. A feature design isn't one; it goes in the
46
+ code.
47
+ - **Notes** are immutable: write a new one instead of updating an old one. A lesson that
48
+ should apply going forward is promoted to a check, a test or a decision.
49
+
50
+ ## The loop
51
+
52
+ | Step | Started by | What happens |
53
+ |---|---|---|
54
+ | Init | you: `mshape init <name>` | A new repo whose gate passes, with one starter test: template, toolchain, beads, the five skills, the handoffs store. |
55
+ | Long term | chat: `/roadmap` + a brain-dump | Interview until goals are clear; write docs/roadmap.md; one deferred epic per goal; open a PR. |
56
+ | Mid term | chat: `/milestone` + priorities | Retrospective on the last milestone; agree a goal with acceptance on real data; write plan/MILESTONE.md; groom beads and the roadmap; garden; create the tracks with `mshape track new`; remove finished ones. |
57
+ | Short term | chat in a track's worktree: `/track` | Read the handoff and the track's queue; work; open PRs. |
58
+ | Hand off | you, near 75% of a chat's context: `/handoff` | The handoff is rewritten so a fresh chat can continue; open one in the same worktree and run `/track`. |
59
+ | Review | chat: `/review-pr <number>` | Review against real data in a scratch worktree (`mshape review <n>`); findings go on the PR; you merge. |
60
+
61
+ A first repo goes: `mshape init`, then `/roadmap`, then `/milestone`, then one chat per track
62
+ running `/track`. The first milestone of a new repo is "a first result on a real target".
63
+
64
+ ## Tracks
65
+
66
+ A track is one line of parallel work: a name, a git worktree, a branch, a beads label and a
67
+ handoff, all derived from the name by `mshape track`:
68
+
69
+ - `mshape track new <name>` creates the worktree `.agents/worktrees/<repo>@<name>`, the branch
70
+ `track/<name>` and the handoff, and links the shared paths from `shape.config.ts`
71
+ (gitignored data such as a dataset) into the worktree.
72
+ - `mshape track list` shows the tracks and each one's open beads; `mshape track current`
73
+ names the track of the current directory, and fails with a reason anywhere else.
74
+ - `mshape track rm <name>` removes a finished track. It refuses while the worktree has
75
+ uncommitted work or the branch has unmerged commits, and says which; `--force` discards
76
+ them. Merged means in `main` or in its upstream, which `rm` fetches first, so a PR merged
77
+ on the remote counts before anyone pulls; a merge commit, a rebase and a squash all count. It also refuses while any bead labelled `track:<name>` isn't closed, and `--force`
78
+ doesn't override that: close each one, or move it to the track that will do it.
79
+
80
+ Its beads carry the label `track:<name>`; its queue is `bd ready --label track:<name>`. An
81
+ empty queue doesn't mean the track is done: `bd ready` leaves out beads in progress or blocked.
82
+ The track is done when `mshape track list` shows it with 0 open beads and `merged: yes`.
83
+
84
+ **Ad-hoc tracks.** For work that didn't come from a milestone, run `mshape track new <name>`
85
+ yourself, open a chat in the worktree it prints and run `/track`. The handoff starts as a
86
+ stub, so `/track` interviews you about the work and writes the charter and its beads.
87
+ `mshape track rm <name>` when it's merged.
88
+
89
+ **When to hand off.** At a natural break, around 75% of the context window. A handoff
90
+ records state, lessons not yet promoted, traps and messages for other tracks; you relay
91
+ those messages by pasting them where they belong, or by asking the track's next chat to read
92
+ the other handoff.
93
+
94
+ ## Pull requests and review
95
+
96
+ - Agents commit, push and open PRs; the human merges. A track has one PR open at a time, from
97
+ its branch. Batch a track's beads into PRs of one theme, typically 1k to 2.5k changed
98
+ lines: many small PRs cost more review than a few large ones. That is a default for
99
+ batching, not a gate: a small PR is fine when it unblocks work or keeps docs in step with
100
+ code.
101
+ - The PR body says what changed and why, the evidence on real data, the gate output, the bug
102
+ class a new check closes, what is not done, and the beads closed or filed.
103
+ - `bun run check` is the gate, the same locally and in CI. It is green before every PR.
104
+ - `/review-pr` runs in its own chat, in a detached worktree at the PR's head that
105
+ `mshape review <n>` makes and `mshape review rm <n>` removes. A review is not a track: it
106
+ has no handoff, and everything about it lives on the PR. A review holds the PR to 95%,
107
+ not 100%: a blocker is a defect the PR would ship, and the skill says what counts. It
108
+ takes as many rounds as that needs, and LGTM means nothing is open. You merge, and can
109
+ step in at any point.
110
+
111
+ ## Beads
112
+
113
+ - A bead points to intent; it isn't a spec. Keep it short: the intent, why, and an outcome
114
+ as acceptance.
115
+ - Three kinds: deferred direction epics (no children), milestone stories labelled by track,
116
+ and interface beads between tracks with an owner and a consumer.
117
+ - **Process beads.** When the process itself gets in the way, file a bead labelled
118
+ `process` saying what broke (`bd create --labels process ...`). `/milestone` reviews them
119
+ at the boundary, and fixes that are general land upstream in monkeyshape.
120
+
121
+ ## The milestone boundary
122
+
123
+ The only ceremony, and `/milestone` runs all of it; the skill holds the steps. Between
124
+ boundaries, tracks just work their queues.
125
+
126
+ ## Who decides
127
+
128
+ AGENTS.md has a decision-authority section; fill it in for your repo. The default: humans
129
+ own priorities, milestones, merging, spend above a cap and anything that leaves the machine.
130
+ Agents decide design, refactors, docs, checks and beads within the milestone, and explain
131
+ what they did in the PR body. When in doubt, an agent acts and explains.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monkeyshape",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Opinionated checks, configs and conventions for humans and coding agents building together on Bun, TypeScript, Effect and beads.",
5
5
  "keywords": [
6
6
  "bun",
@@ -40,14 +40,18 @@
40
40
  "files": [
41
41
  "src",
42
42
  "config",
43
+ "template",
44
+ "skills",
43
45
  "!src/**/*.test.ts",
44
46
  "README.md",
47
+ "docs/workflow.md",
45
48
  "LICENSE"
46
49
  ],
47
50
  "scripts": {
48
51
  "typecheck": "tsc -p .",
49
52
  "lint": "biome ci --error-on-warnings .",
50
53
  "fix": "biome check --write .",
54
+ "mshape": "bun src/cli/main.ts",
51
55
  "shape": "bun src/cli/main.ts check",
52
56
  "check": "bun run typecheck && bun run lint && bun run shape && bun test"
53
57
  },
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: handoff
3
+ description: Use when the human says /handoff, or asks to wrap up a track's chat because the context is running out or the session is ending. Rewrites the track's handoff so a fresh chat running /track can continue with nothing else.
4
+ ---
5
+
6
+ # Handoff: hand a track to a fresh chat
7
+
8
+ The next session knows only the repo, the beads and the handoff you write now. Write for an
9
+ agent as capable as you who wasn't here: what it needs to continue, not what you did. What a
10
+ change did belongs in its PR body and commits, not here.
11
+
12
+ ## 1. Which track
13
+
14
+ Run `mshape track current`. If it exits 1, tell the human its reason and stop: a handoff
15
+ belongs to a track.
16
+
17
+ ## 2. Leave nothing only in this chat
18
+
19
+ - **Uncommitted work:** if no PR is open from the track branch, commit it there, as a WIP
20
+ commit if it isn't finished, and push. If one is open, a push would add it to the PR:
21
+ leave it uncommitted (the next chat opens in this same worktree) and list it in State.
22
+ Never stash: the stash is shared by every worktree.
23
+ - **Beads:** close what merged; claim what is half done; file what you found and didn't do.
24
+ - **Open PRs:** note each one's number and what it waits on.
25
+
26
+ ## 3. Rewrite the handoff
27
+
28
+ Overwrite `.handoffs/<name>.md`; don't append. Other tracks write to its Messages while you
29
+ work, so read the file again just before writing, and keep every message you hadn't seen.
30
+
31
+ Keep its format: the title, `Status:` and `Queue:` lines, then exactly the sections Charter,
32
+ State (with today's date), Lessons not yet promoted, Traps, Messages, in that order, with
33
+ `###` for headings inside them. About 120 lines at most.
34
+
35
+ - **Charter:** leave it unless the work changed what the track is for; then rewrite it, and
36
+ say in State that it changed and why.
37
+ - **State:** done (PRs and beads, by number), in flight (the branch, the PR, what is half
38
+ done and the next command to run), and next. Concrete enough to act on without asking.
39
+ - **Lessons not yet promoted:** what you learned that should become a check, a test, an
40
+ AGENTS.md gotcha or a decision. If promoting one is quick, do it now instead and delete
41
+ it here. A lesson that is really a bead becomes one.
42
+ - **Traps:** what will bite the next session. Delete traps that are no longer true.
43
+ - **Messages:** delete the answered ones and keep the open ones. Your messages to other
44
+ tracks go in their handoffs, not here.
45
+
46
+ ## 4. Check it and hand over
47
+
48
+ Run `mshape track list`: this track must show `stub` (if the charter isn't agreed yet:
49
+ leave it empty, never write one the human hasn't agreed) or `active`, never `invalid`. If it
50
+ shows `invalid`, each problem is printed under its row: fix them all and run it again. Then
51
+ tell the human, in a few lines: what is done and in flight, any messages they need to relay to another track or decide on, and "open a
52
+ fresh chat in this worktree and run `/track`".
53
+
54
+ Review this skill when a fresh chat had to rediscover something the last one knew.
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: milestone
3
+ description: Use at a milestone boundary, when the human brings priorities for the next stretch of work, or when the repo has a roadmap but no milestone plan yet. Runs the retrospective, agrees a goal with acceptance on real data, writes plan/MILESTONE.md, grooms beads and the roadmap, gardens, and creates the tracks with mshape track.
4
+ ---
5
+
6
+ # Milestone: the mid horizon and the boundary
7
+
8
+ A milestone is the next significant delivery: several PRs from each of several parallel
9
+ tracks. The boundary is the repo's only ceremony, and this skill runs all of it, in order.
10
+ The human owns priorities and approves the plan; you bring the evidence and the proposal.
11
+
12
+ Run this in the main checkout, on an up-to-date `main`, in a fresh chat.
13
+
14
+ ## 1. Gather
15
+
16
+ - plan/MILESTONE.md (the milestone ending), docs/roadmap.md, AGENTS.md.
17
+ - `mshape track list`, and every track's handoff in `.handoffs`: state, lessons not yet
18
+ promoted, messages nobody answered.
19
+ - The milestone's epic and its children (`bd list --parent <epic> --all`), and
20
+ `bd list --label process` for what got in the way.
21
+ - Merged PRs since the plan was written (`gh pr list --state merged`), and their bodies'
22
+ "not done" sections.
23
+ - `mshape garden`.
24
+
25
+ On a repo's first milestone there is nothing to look back on: skip to step 3.
26
+
27
+ ## 2. Retrospective
28
+
29
+ Tell the human, briefly: what shipped against each acceptance line, what slipped and why,
30
+ what the process beads and handoff lessons say, and what you would change. Facts with
31
+ links (PRs, beads), not a story. Ask what they saw that you didn't.
32
+
33
+ ## 3. Agree the goal
34
+
35
+ Propose one goal, from the human's priorities and the roadmap, with **acceptance on real
36
+ data**: a run on a named real target, or a real repo or user doing the thing, never "tests
37
+ pass". A new repo's first milestone is "a first result on a real target". Say what you
38
+ would defer to make it fit, and why. Iterate until the human agrees; don't write the plan
39
+ before that.
40
+
41
+ ## 4. Write plan/MILESTONE.md
42
+
43
+ First move the old plan to notes/, named with today's date (YYYY-MM-DD-milestone-<n>.md).
44
+ Then write the new one, about 500 lines at most:
45
+
46
+ - **Goal, and how we'll know:** the acceptance agreed above.
47
+ - **Where we are:** a gap table, measured where it can be.
48
+ - **What changed since the last milestone, and why.**
49
+ - **Interfaces the tracks share:** every path, command, format or schema two tracks both
50
+ touch, with its owner and consumer, settled before anyone starts. This is the section
51
+ that keeps parallel work from colliding; spend the effort here.
52
+ - **Tracks:** a table of name, charter, beads and acceptance. Split into as many parallel
53
+ tracks as the work allows: each touches disjoint files and meets the others only at the
54
+ interfaces. Derive the number from the work, not a habit: up to about five is usual, and
55
+ one is fine when the work is sequential. When a track ends up holding far more than the
56
+ others, or the riskiest work alongside everything else, split it.
57
+ - **Decision points**, **spend** for big runs, and **deferred items, each with a reason**.
58
+
59
+ The plan is frozen once tracks start. Say so at its top.
60
+
61
+ ## 5. Groom
62
+
63
+ - Create the milestone epic, and its stories as children labelled `track:<name>`, with
64
+ dependencies (`bd dep add`). An interface gets its own bead, owned by one track. A bead
65
+ is intent and an outcome as acceptance, about 1,500 characters at most, not a spec.
66
+ - Pull roadmap epics in with `bd undefer`; close epics whose work is done.
67
+ - Close, defer or rewrite every open story the milestone doesn't need, with a reason. A
68
+ story deferred out of the milestone drops its `track:` label.
69
+ - P1 is the critical path only.
70
+ - Re-verify each bd memory (`bd memories`) against the code; rewrite or delete stale ones.
71
+ - Every `TODO(<bead id>)` in code whose bead is now closed: fix it or re-point it.
72
+
73
+ ## 6. Garden
74
+
75
+ Act on `mshape garden`: anything over budget or grown since the last boundary gets pruned,
76
+ not waived. Promote each handoff lesson to a check, a test, an AGENTS.md gotcha or a
77
+ decision, or delete it. Try to turn each prose rule into a check, and each review finding
78
+ that recurred into one. A process bead whose fix is general belongs upstream in monkeyshape:
79
+ tell the human; filing outside the repo is theirs to approve.
80
+
81
+ ## 7. Roadmap and PR
82
+
83
+ Update docs/roadmap.md: the status table, and what this milestone taught. Then one PR with
84
+ the plan, the roadmap and the garden changes, gate green, the body saying what was decided
85
+ and why. The human merges.
86
+
87
+ ## 8. Tracks
88
+
89
+ Once the PR is merged (or the human says to start):
90
+
91
+ - `mshape track rm <name>` for each finished track whose `beads` column in
92
+ `mshape track list` shows 0. A `-` means beads weren't counted, and `rm` may then remove
93
+ the track with only a note. So first get `bd` working, or check by hand that
94
+ `bd list --label track:<name> --limit 0` lists nothing (it hides only closed beads).
95
+ If `rm` refuses, report the reason; never reach for `--force` without the human. If the
96
+ reason is open beads, `--force` won't help, and grooming has already decided each one:
97
+ move it to the track the new plan gives it, or close it if it's done, and list what you
98
+ did in your report. Ask the human only when the plan doesn't say.
99
+ - `mshape track new <name>` for each new track. Fill its handoff: `Status: active`, the
100
+ charter (its beads, the interfaces it owns or consumes), the state ("not started", and
101
+ how to start), the traps you already know, and messages from the plan.
102
+
103
+ Finish by telling the human what to launch: for each track, the worktree path and "open a
104
+ chat there and run `/track`".
105
+
106
+ Review this skill after each boundary it runs: what the retrospective found about the
107
+ process applies to this file too.
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: review-pr
3
+ description: Use when asked to review a pull request (a number or URL), to re-review one after its author replied or pushed fixes, or to review a follow-up PR that answers an earlier review's findings. Runs the change on real data in a scratch worktree, probes what it claims to enforce, posts every finding on the PR with a severity, and re-reviews until it can say "LGTM".
4
+ ---
5
+
6
+ # Review a pull request
7
+
8
+ A review is judged by what it **ran and read**, not by what it guessed from the diff. Every
9
+ finding carries its evidence: the input that breaks it, a real-data output, or the line of
10
+ code it rests on. Read AGENTS.md first: it holds the rules the PR is reviewed against.
11
+
12
+ **Ground rules**
13
+ - **The PR is the review's only home.** Findings, evidence, replies and what is still open
14
+ all go on it; nothing about the review is kept anywhere else. A fresh chat re-reviewing
15
+ reads the thread.
16
+ - **Don't fix the PR yourself**: the author fixes findings in the same PR.
17
+ - **Hold the PR to 95%, not 100%.** A blocker is a defect the PR would ship and someone
18
+ would hit, shown by a concrete failing input or a real-data result. "Could be better", or
19
+ an edge nobody has, is a nit, in any round. Style never blocks: the linter owns style.
20
+ - **A nit stays open until it's settled:** fixed in this PR, declined with a reason you
21
+ accept, or filed by the author as a bead when it is real work beyond the PR. Never call a
22
+ blocker a nit to close a review.
23
+ - **As many rounds as that takes.** If each fix keeps opening a new blocker, tell the human:
24
+ the design may need rethinking more than another patch. The human can step in at any point.
25
+ - Real data may be read and run freely; spend past the repo's cap, or writes to shared data,
26
+ need the human first (see AGENTS.md).
27
+
28
+ ## 1. A worktree at the PR's head
29
+
30
+ ```bash
31
+ N=<pr number>
32
+ gh pr view $N --json title,body,files,commits
33
+ gh api repos/{owner}/{repo}/pulls/$N -q .head.sha # the head you review and anchor to
34
+ mshape review $N # detached worktree at that head, shared data linked; prints its path
35
+ cd <that path> && bun install --frozen-lockfile
36
+ ```
37
+
38
+ Never review in your own checkout. If the review's head and the API's differ, the author
39
+ pushed meanwhile: run `mshape review $N` again.
40
+
41
+ **A follow-up PR** that answers an earlier review: read that PR's thread first
42
+ (`gh pr view <earlier> --comments`, and its inline comments as in step 5). Each finding it
43
+ claims to answer is a re-review item (step 5), on top of reviewing its own diff.
44
+
45
+ ## 2. Read the diff
46
+
47
+ Read the PR body and every changed file. Then go through it for:
48
+
49
+ - **The invariants it claims.** If a schema, check or test says it enforces something, list
50
+ the inputs that should fail. Those are your probes in step 3.
51
+ - **Docs it touches, or should have.** Do AGENTS.md, DECISIONS.md, the skills and the
52
+ handoffs still agree with the change? Grep for prose it made stale.
53
+ - **The usual misses.** New code outside the gate (a tsconfig `include`, a test glob)? A
54
+ check that a free-text field walks around? A check-then-write that isn't atomic? A path
55
+ that breaks in a worktree, a symlink or a fresh clone? An error message that doesn't say
56
+ what to do?
57
+
58
+ ## 3. Run it
59
+
60
+ From cheapest to most expensive:
61
+
62
+ 1. **Run what the PR adds**, on real data, in every mode it has. Do the numbers in the PR
63
+ body reproduce? Does each exit code mean what its doc says?
64
+ 2. **Probe checks adversarially**: throwaway scripts that build inputs which should be
65
+ rejected, one variation each, from a real artifact where there is one. **A bad input
66
+ that passes is a finding**, and the probe's input and output are its evidence on the PR.
67
+ Probes are scratch and are never committed or kept: one worth keeping is a regression
68
+ test, and that is the author's to add (step 4). **When the PR adds a check**, also probe
69
+ it with valid input it must pass: a false failure reaches everyone who runs the check,
70
+ and is a blocker.
71
+ 3. **Run the real workflow** when the claim is about what it produces end to end.
72
+
73
+ Don't rerun the gate on the first pass if the PR body shows it green; do on a re-review whose
74
+ fix touched code.
75
+
76
+ ## 4. Post on the PR
77
+
78
+ Post **one review**, inline comments anchored to the head commit, built as a JSON file so
79
+ the quoting survives:
80
+
81
+ ```bash
82
+ # review.json: {commit_id, event: "COMMENT", body, comments: [{path, line, side: "RIGHT", body}]}
83
+ gh api repos/{owner}/{repo}/pulls/$N/reviews --input review.json -q .html_url
84
+ ```
85
+
86
+ Anchor each comment to a head-commit line that is in the diff; a finding with no such line
87
+ goes in the review body. Each comment opens with a **bold one-sentence finding** and its
88
+ severity (blocker or nit), then the evidence, then a suggested fix.
89
+
90
+ - **A blocker in code asks for a regression test** in the PR: one that fails on this head
91
+ and passes once fixed. A blocker in prose (two docs that disagree, a wrong instruction)
92
+ asks for the fix; there is nothing to test.
93
+ - **If a check could rule out the whole class**, say so: the PR body's "Class closed by"
94
+ line is where the author answers it.
95
+
96
+ The body says what was run and what came out, the blockers, the nits with no line, and what
97
+ looked good. Use `COMMENT`: GitHub refuses approve and request-changes on your own
98
+ account's PR. Then tell the human in a few lines: what you ran, each finding and its
99
+ severity, the review link. **Stop and wait** for the author.
100
+
101
+ ## 5. Re-review
102
+
103
+ When told the author responded, read the thread: every reply, the new commits and the fix
104
+ diff (`gh pr view $N --comments`, `gh api repos/{owner}/{repo}/pulls/$N/comments`). The head
105
+ you reviewed last is your previous review's `commit_id`
106
+ (`gh api repos/{owner}/{repo}/pulls/$N/reviews`). Run `mshape review $N` to move the
107
+ worktree to the new head; it prints the previous one too.
108
+
109
+ 1. **"Fixed" is a claim.** For each code blocker, find its regression test and run it on
110
+ both heads. It must fail on the old one and pass on the new:
111
+
112
+ ```bash
113
+ git switch --detach <old head> && git checkout <new head> -- <test file> <files it needs>
114
+ bun test <test file> # must fail
115
+ git reset -q --hard && git switch --detach <new head>
116
+ bun test <test file> # must pass
117
+ ```
118
+
119
+ The failure on the old head must be the test's own assertion, saying what the finding
120
+ said: a load or import error means it never reached the bug, so check out the helpers
121
+ and fixtures it imports too, and rerun `bun install` if the dependencies changed. A test
122
+ that passes on the old head doesn't test the bug: that is a finding. For a prose
123
+ blocker, read the fix. Rerun the real-data runs the findings rested on.
124
+ 2. Look for what the fix opened: a new unchecked field, the mirror case of a new check.
125
+ 3. **Pushback is an argument, not a refusal.** If it holds, say so and drop the point; if it
126
+ doesn't, answer with evidence.
127
+ 4. Reply in the threads, then post a short summary review: what was re-verified, what is
128
+ resolved, what is still open. Tell the human.
129
+
130
+ **When nothing is open, say "LGTM"** explicitly, on the PR and to the human: every blocker
131
+ resolved and verified, every nit settled. Never while a finding is open or unverified.
132
+ Merging is the human's call. When the review is over, `mshape review rm $N`: it lists what
133
+ it discards, which in a review worktree is only scratch, then removes it.
134
+
135
+ Review this skill when a blocker it should have caught reaches `main`.
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: roadmap
3
+ description: Use when the human brings a brain-dump about where the repo is heading (new goals, a change of direction, a fresh repo after mshape init), or asks to rewrite the roadmap. Interviews until the goals are clear, writes docs/roadmap.md with a status table first, keeps one deferred beads epic per goal, and opens a PR.
4
+ ---
5
+
6
+ # Roadmap: the long horizon
7
+
8
+ The roadmap is direction, not a spec: months ahead, coarse, rewritten in place, never cited
9
+ by code or normative docs. Your job is to turn a brain-dump into goals clear enough that a
10
+ later `/milestone` can pick one and give it acceptance on real data.
11
+
12
+ Run this in the main checkout, on an up-to-date `main`, in a fresh chat.
13
+
14
+ ## 1. Read what exists
15
+
16
+ - docs/roadmap.md, if there is one, and AGENTS.md.
17
+ - The direction epics: `bd list --type epic --all`. Deferred ones are goals not yet pulled
18
+ into a milestone; open ones are in flight; closed ones shipped.
19
+ - If a milestone is running, plan/MILESTONE.md, only to know what is already committed.
20
+
21
+ ## 2. Interview
22
+
23
+ Ask in small batches, and propose answers rather than asking open questions: "I read this as
24
+ X; is that right?" is cheaper for the human than "what do you mean?". Keep going until you
25
+ could write, for every goal:
26
+
27
+ - **The consumer:** who or what uses it first. No goal without one.
28
+ - **What done looks like** on real data or a real target, not a feature list.
29
+ - **Why now, or why later**, and what it depends on.
30
+ - **What is out of scope**, said out loud, so the next agent doesn't build it.
31
+ - **Spend or authority** it will need from the human (money, public releases, data).
32
+
33
+ Push back where the brain-dump conflicts with the code, with the repo's principles in
34
+ AGENTS.md, or with itself. The human owns priorities; you own pointing out that two of them
35
+ collide. Stop interviewing when another question would not change what you write.
36
+
37
+ ## 3. Write docs/roadmap.md
38
+
39
+ Rewrite it in place; git has the history, so keep no revision log and no frozen copy.
40
+
41
+ - **Open with a status table**: one row per goal, with status `Shipped`, `Milestone N` (in
42
+ progress), `Later` or `Idea`, and the epic id. A reader learns what exists without reading
43
+ the design.
44
+ - Then scope (who it's for, what it is not), then a section per goal: the intent, the
45
+ consumer, what done looks like, and what was learned so far. Far-off detail belongs here,
46
+ not in beads.
47
+ - No dated promises, no restating AGENTS.md or DECISIONS.md, and nothing other docs would
48
+ need to cite: if something must be enforced, it becomes a check, a test or a decision.
49
+
50
+ ## 4. One deferred epic per goal
51
+
52
+ For each goal without an epic: `bd create --type epic --title "<goal>" --description "..."`
53
+ with the goal, two or three lines of why, and the roadmap section it comes from, then
54
+ `bd defer <id>`. **No child stories:** a milestone creates those when it pulls the epic in.
55
+ For goals that changed, rewrite the epic; for goals dropped, close it with the reason. Put
56
+ each epic's id in the status table.
57
+
58
+ ## 5. PR
59
+
60
+ Branch from `main`, commit, push, and open a PR whose body says what changed in the
61
+ direction and why, which epics were created, rewritten or closed, and what the interview
62
+ left open. Gate green first (`bun run check`). The human merges.
63
+
64
+ Then tell the human the next step: `/milestone` in a fresh chat, with their priorities.
65
+
66
+ Review this skill when a roadmap written with it was hard for `/milestone` to plan from.