@mlangroman/sdlc 0.1.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/LICENSE +21 -0
- package/README.md +89 -0
- package/bin/sdlc.mjs +162 -0
- package/package.json +32 -0
- package/skills/approve/SKILL.md +52 -0
- package/skills/cancel/SKILL.md +38 -0
- package/skills/chore/SKILL.md +26 -0
- package/skills/implement/SKILL.md +59 -0
- package/skills/land/SKILL.md +47 -0
- package/skills/next/SKILL.md +35 -0
- package/skills/plan/SKILL.md +43 -0
- package/skills/queue/SKILL.md +32 -0
- package/skills/ticket/SKILL.md +35 -0
- package/template/AGENTS.root.md +52 -0
- package/template/thoughts/AGENTS.md +96 -0
- package/template/thoughts/designs/.gitkeep +0 -0
- package/template/thoughts/docs/.gitkeep +0 -0
- package/template/thoughts/plans/.gitkeep +0 -0
- package/template/thoughts/reviews/.gitkeep +0 -0
- package/template/thoughts/tickets/.gitkeep +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Martin Lang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# sdlc
|
|
2
|
+
|
|
3
|
+
**Ticket → plan → implement → land** — an agentic software development pipeline packaged as [agent skills](https://skills.sh), with a one-command project setup.
|
|
4
|
+
|
|
5
|
+
Work is defined in a `thoughts/` folder as reviewable markdown artifacts (tickets and plans) with explicit human gates between every phase. Execution state lives in [beads](https://github.com/gastownhall/beads), implementation happens in isolated git worktrees, and every change gets a persisted code review before it merges.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
Full project setup (thoughts folder + skills + `AGENTS.md`/`CLAUDE.md` symlinks + beads):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @mlangroman/sdlc setup
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Skills only, for any of the 40+ agents the [skills CLI](https://www.npmjs.com/package/skills) supports (Claude Code, Cursor, Codex, …):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx skills add MJLang/sdlc # all nine skills
|
|
19
|
+
npx skills add MJLang/sdlc --skill ticket --skill plan # a subset
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## The pipeline
|
|
23
|
+
|
|
24
|
+
| Skill | Transition | Gate |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `/ticket <idea>` | new ticket (`draft`) | — |
|
|
27
|
+
| — (hand-edit `Status: approved`) | ticket `draft` → `approved` | **human** |
|
|
28
|
+
| `/plan <NNN>` | ticket `approved` → plan (`review`) | — |
|
|
29
|
+
| `/approve <NNN>` | plan `review` → `approved`; creates beads epic + step issues | **human** |
|
|
30
|
+
| `/implement <NNN>` | executes the plan in its own worktree; ends with a review verdict | — |
|
|
31
|
+
| `/land <NNN>` | squash-merge to main; plan → `merged`, ticket → `implemented` | **human** |
|
|
32
|
+
| `/chore <idea>` | lightweight lane: small change end-to-end in one pass | **human** |
|
|
33
|
+
| `/cancel <NNN> [plan]` | cancel a line of work (or just the plan, to re-plan) | **human** |
|
|
34
|
+
| `/queue` | read-only dashboard: in flight, stalled, awaiting a human | — |
|
|
35
|
+
| `/next` | one autonomous pipeline iteration — pair with `/loop` | — |
|
|
36
|
+
|
|
37
|
+
Design principles:
|
|
38
|
+
|
|
39
|
+
- **Artifacts over chat.** Tickets say *what and why*; plans say *how*, step by step with an explicit dependency graph. Both are markdown files you review and approve.
|
|
40
|
+
- **Humans hold the gates.** Approving a ticket is a deliberate hand-edit. `/approve`, `/land`, `/chore`, and `/cancel` never run on the agent's initiative.
|
|
41
|
+
- **Frontmatter records gates; beads records reality.** A file's `Status` only changes at hand-offs. Live progress is always a beads query, never a file edit.
|
|
42
|
+
- **Worktree isolation.** Every plan is implemented on its own branch in `.worktrees/<plan-name>`, one commit per step, pushed as each step closes — a crashed session strands nothing.
|
|
43
|
+
- **Reviews are artifacts.** Full reviewer output persists to `thoughts/reviews/` and travels with the branch; `/land` refuses to merge without an `APPROVED` verdict for the exact HEAD it is merging.
|
|
44
|
+
- **Autonomy without gate-crossing.** `/loop /next` keeps planning and implementing whatever is legal, and queues everything that needs a human.
|
|
45
|
+
|
|
46
|
+
The full workflow contract lives in [`template/thoughts/AGENTS.md`](template/thoughts/AGENTS.md) — `setup` copies it to `thoughts/AGENTS.md` in your project, and the skills treat it as the source of truth.
|
|
47
|
+
|
|
48
|
+
## What `setup` does
|
|
49
|
+
|
|
50
|
+
Run inside your project directory:
|
|
51
|
+
|
|
52
|
+
1. `git init` if the directory is not a repository (the pipeline needs branches and worktrees)
|
|
53
|
+
2. Creates `thoughts/{tickets,plans,designs,docs,reviews}/` and `thoughts/AGENTS.md`, with a `thoughts/CLAUDE.md → AGENTS.md` symlink
|
|
54
|
+
3. Creates a starter root `AGENTS.md` (or adopts an existing root `CLAUDE.md` as `AGENTS.md`) and symlinks root `CLAUDE.md → AGENTS.md`
|
|
55
|
+
4. Installs the nine skills into `.claude/skills/`
|
|
56
|
+
5. Runs `bd init` if [beads](https://github.com/gastownhall/beads) is installed
|
|
57
|
+
|
|
58
|
+
Flags: `--force` (overwrite existing files), `--skip-skills`, `--skip-beads`.
|
|
59
|
+
|
|
60
|
+
## After setup
|
|
61
|
+
|
|
62
|
+
1. Edit the **Project Configuration** section of `thoughts/AGENTS.md` — this is the one place the skills read per-project values from:
|
|
63
|
+
- **Targets** — the areas of your repo work can land in (e.g. `cms | jobs | web | utils` for a monorepo)
|
|
64
|
+
- **Quality gates** — the commands that must pass after every implementation step (e.g. `pnpm check`)
|
|
65
|
+
- **Reviewers** — map targets to reviewer agents if you have them; otherwise a general code review is used
|
|
66
|
+
- **Product docs** — where tickets ground their summaries (default `thoughts/docs/`)
|
|
67
|
+
- **Frontend constraints** — e.g. "no new pages until the design system exists"
|
|
68
|
+
2. Drop your product/vision docs into `thoughts/docs/`
|
|
69
|
+
3. Start: `/ticket <your first idea>`
|
|
70
|
+
|
|
71
|
+
## Requirements
|
|
72
|
+
|
|
73
|
+
- **git** — worktrees, branches, and (ideally) a remote
|
|
74
|
+
- **[beads](https://github.com/gastownhall/beads)** (`bd`) — issue tracking, dependency graphs, and the claim mutex that keeps parallel sessions off the same plan
|
|
75
|
+
- An agent that supports skills — built for [Claude Code](https://claude.com/claude-code), installable anywhere the [skills CLI](https://skills.sh) reaches
|
|
76
|
+
|
|
77
|
+
## Repository layout
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
skills/ one folder per skill (SKILL.md) — what `npx skills add` installs
|
|
81
|
+
template/ files copied into your project by `setup`
|
|
82
|
+
thoughts/AGENTS.md the pipeline contract (workflow instructions)
|
|
83
|
+
AGENTS.root.md starter root AGENTS.md (beads conventions, session protocol)
|
|
84
|
+
bin/sdlc.mjs the zero-dependency setup CLI
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
MIT
|
package/bin/sdlc.mjs
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @mlangroman/sdlc — project bootstrapper for the ticket → plan → implement → land pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx @mlangroman/sdlc setup [--force] [--skip-skills] [--skip-beads]
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readdirSync, renameSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { dirname, join } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { spawnSync } from 'node:child_process';
|
|
13
|
+
|
|
14
|
+
const pkgRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
15
|
+
const cwd = process.cwd();
|
|
16
|
+
|
|
17
|
+
const tty = process.stdout.isTTY;
|
|
18
|
+
const c = (code, s) => (tty ? `\x1b[${code}m${s}\x1b[0m` : s);
|
|
19
|
+
const ok = (s) => console.log(` ${c('32', '✓')} ${s}`);
|
|
20
|
+
const skip = (s) => console.log(` ${c('90', '•')} ${s}`);
|
|
21
|
+
const warn = (s) => console.log(` ${c('33', '!')} ${s}`);
|
|
22
|
+
const head = (s) => console.log(`\n${c('1', s)}`);
|
|
23
|
+
|
|
24
|
+
const args = process.argv.slice(2);
|
|
25
|
+
const command = args.find((a) => !a.startsWith('-'));
|
|
26
|
+
const flags = new Set(args.filter((a) => a.startsWith('-')));
|
|
27
|
+
const force = flags.has('--force') || flags.has('-f');
|
|
28
|
+
|
|
29
|
+
const SKILLS_DIR = join(pkgRoot, 'skills');
|
|
30
|
+
const THOUGHTS_SUBDIRS = ['tickets', 'plans', 'designs', 'docs', 'reviews'];
|
|
31
|
+
|
|
32
|
+
function help() {
|
|
33
|
+
console.log(`
|
|
34
|
+
${c('1', '@mlangroman/sdlc')} — ticket → plan → implement → land pipeline for agentic development
|
|
35
|
+
|
|
36
|
+
Usage:
|
|
37
|
+
npx @mlangroman/sdlc setup [options] Set up the pipeline in the current directory
|
|
38
|
+
|
|
39
|
+
Options:
|
|
40
|
+
--force, -f Overwrite existing thoughts/AGENTS.md, root AGENTS.md, and skills
|
|
41
|
+
--skip-skills Do not install skills into .claude/skills/
|
|
42
|
+
--skip-beads Do not run bd init
|
|
43
|
+
|
|
44
|
+
What setup does:
|
|
45
|
+
1. git init (if not already a repository)
|
|
46
|
+
2. Creates thoughts/{${THOUGHTS_SUBDIRS.join(',')}} + thoughts/AGENTS.md (+ CLAUDE.md symlink)
|
|
47
|
+
3. Creates a root AGENTS.md (if missing) and a root CLAUDE.md → AGENTS.md symlink
|
|
48
|
+
4. Installs the pipeline skills into .claude/skills/
|
|
49
|
+
5. Initializes beads (bd init), if bd is installed
|
|
50
|
+
|
|
51
|
+
Skills can also be installed on their own, for any supported agent, via the skills CLI:
|
|
52
|
+
npx skills add MJLang/sdlc
|
|
53
|
+
`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Symlink CLAUDE.md → AGENTS.md (relative). Falls back to a copy where symlinks are unavailable.
|
|
57
|
+
function linkClaudeMd(dir, label) {
|
|
58
|
+
const link = join(dir, 'CLAUDE.md');
|
|
59
|
+
if (existsSync(link) || (lstatSync(link, { throwIfNoEntry: false })?.isSymbolicLink())) {
|
|
60
|
+
const st = lstatSync(link);
|
|
61
|
+
if (st.isSymbolicLink()) skip(`${label}/CLAUDE.md symlink exists`);
|
|
62
|
+
else warn(`${label}/CLAUDE.md exists as a regular file — leaving it; consider merging it into AGENTS.md and symlinking`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
symlinkSync('AGENTS.md', link);
|
|
67
|
+
ok(`${label}/CLAUDE.md → AGENTS.md symlink`);
|
|
68
|
+
} catch {
|
|
69
|
+
cpSync(join(dir, 'AGENTS.md'), link);
|
|
70
|
+
warn(`${label}/CLAUDE.md created as a copy (symlinks unavailable on this system)`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function copyIfMissing(src, dest, label) {
|
|
75
|
+
if (existsSync(dest) && !force) {
|
|
76
|
+
skip(`${label} exists (use --force to overwrite)`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
cpSync(src, dest);
|
|
80
|
+
ok(label);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function setup() {
|
|
84
|
+
console.log(c('1', '\nSetting up the sdlc pipeline in ') + cwd);
|
|
85
|
+
|
|
86
|
+
head('git');
|
|
87
|
+
if (existsSync(join(cwd, '.git'))) {
|
|
88
|
+
skip('already a git repository');
|
|
89
|
+
} else {
|
|
90
|
+
const r = spawnSync('git', ['init'], { cwd, stdio: 'pipe' });
|
|
91
|
+
if (r.status === 0) ok('git init (the pipeline uses worktrees and branches)');
|
|
92
|
+
else warn('git init failed — run it yourself; the pipeline requires git');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
head('thoughts/');
|
|
96
|
+
for (const d of THOUGHTS_SUBDIRS) {
|
|
97
|
+
const p = join(cwd, 'thoughts', d);
|
|
98
|
+
if (existsSync(p)) skip(`thoughts/${d}/ exists`);
|
|
99
|
+
else {
|
|
100
|
+
mkdirSync(p, { recursive: true });
|
|
101
|
+
writeFileSync(join(p, '.gitkeep'), '');
|
|
102
|
+
ok(`thoughts/${d}/`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
copyIfMissing(join(pkgRoot, 'template', 'thoughts', 'AGENTS.md'), join(cwd, 'thoughts', 'AGENTS.md'), 'thoughts/AGENTS.md (pipeline instructions)');
|
|
106
|
+
linkClaudeMd(join(cwd, 'thoughts'), 'thoughts');
|
|
107
|
+
|
|
108
|
+
head('root instructions');
|
|
109
|
+
const rootAgents = join(cwd, 'AGENTS.md');
|
|
110
|
+
const rootClaude = join(cwd, 'CLAUDE.md');
|
|
111
|
+
if (!existsSync(rootAgents) && existsSync(rootClaude) && lstatSync(rootClaude).isFile()) {
|
|
112
|
+
// Adopt an existing CLAUDE.md as the canonical AGENTS.md, then symlink back.
|
|
113
|
+
renameSync(rootClaude, rootAgents);
|
|
114
|
+
ok('moved existing CLAUDE.md → AGENTS.md (canonical file)');
|
|
115
|
+
}
|
|
116
|
+
copyIfMissing(join(pkgRoot, 'template', 'AGENTS.root.md'), rootAgents, 'AGENTS.md (root agent instructions)');
|
|
117
|
+
linkClaudeMd(cwd, '.');
|
|
118
|
+
|
|
119
|
+
if (!flags.has('--skip-skills')) {
|
|
120
|
+
head('skills → .claude/skills/');
|
|
121
|
+
for (const name of readdirSync(SKILLS_DIR)) {
|
|
122
|
+
const src = join(SKILLS_DIR, name);
|
|
123
|
+
const dest = join(cwd, '.claude', 'skills', name);
|
|
124
|
+
if (existsSync(dest) && !force) {
|
|
125
|
+
skip(`${name} exists (use --force to overwrite)`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
mkdirSync(dest, { recursive: true });
|
|
129
|
+
cpSync(src, dest, { recursive: true, force: true });
|
|
130
|
+
ok(name);
|
|
131
|
+
}
|
|
132
|
+
console.log(` ${c('90', 'other agents (cursor, codex, …): npx skills add MJLang/sdlc')}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!flags.has('--skip-beads')) {
|
|
136
|
+
head('beads');
|
|
137
|
+
const bd = spawnSync('bd', ['--version'], { stdio: 'pipe' });
|
|
138
|
+
if (bd.error || bd.status !== 0) {
|
|
139
|
+
warn('bd (beads) not found — install it from https://github.com/gastownhall/beads, then run: bd init');
|
|
140
|
+
} else if (existsSync(join(cwd, '.beads'))) {
|
|
141
|
+
skip('.beads/ exists');
|
|
142
|
+
} else {
|
|
143
|
+
const r = spawnSync('bd', ['init'], { cwd, stdio: 'inherit' });
|
|
144
|
+
if (r.status === 0) ok('bd init');
|
|
145
|
+
else warn('bd init failed — run it yourself');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
console.log(`
|
|
150
|
+
${c('1', 'Done. Next steps:')}
|
|
151
|
+
1. Edit the ${c('1', 'Project Configuration')} section in thoughts/AGENTS.md
|
|
152
|
+
(targets, quality gates, reviewers, product docs)
|
|
153
|
+
2. Drop your product/context docs into thoughts/docs/
|
|
154
|
+
3. In your agent: ${c('1', '/ticket <your first idea>')}
|
|
155
|
+
|
|
156
|
+
Pipeline: /ticket → approve by hand → /plan → /approve → /implement → /land
|
|
157
|
+
Dashboard: /queue Autonomous: /loop /next Small fixes: /chore
|
|
158
|
+
`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (command === 'setup') setup();
|
|
162
|
+
else help();
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mlangroman/sdlc",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Ticket → plan → implement → land: an agentic SDLC pipeline as installable agent skills, with one-command project setup (thoughts/ folder, AGENTS.md/CLAUDE.md symlinks, beads issue tracking).",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agent-skills",
|
|
7
|
+
"skills",
|
|
8
|
+
"claude-code",
|
|
9
|
+
"sdlc",
|
|
10
|
+
"beads",
|
|
11
|
+
"workflow",
|
|
12
|
+
"agents"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": "Martin Lang <martin@mercator.io>",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/MJLang/sdlc.git"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"bin": {
|
|
22
|
+
"sdlc": "bin/sdlc.mjs"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"bin/",
|
|
26
|
+
"skills/",
|
|
27
|
+
"template/"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: approve
|
|
3
|
+
description: Human gate — approve a reviewed plan (creates its beads epic + step issues), or re-sync an amended, already-approved plan into its epic.
|
|
4
|
+
argument-hint: <plan number, e.g. 003>
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Approve or re-sync plan $ARGUMENTS. This is a human gate: it runs only on explicit user invocation.
|
|
9
|
+
|
|
10
|
+
Two modes, chosen by the plan's current state:
|
|
11
|
+
- **First approval** — `Status: review`, no `Beads Epic`.
|
|
12
|
+
- **Amendment re-sync** — `Status: approved` with `Beads Epic` set, and the plan file has been edited. This is the sanctioned way to change a plan after approval — including adding scope while `/implement` is running.
|
|
13
|
+
|
|
14
|
+
If the plan is `draft`, refuse: it is not finished. If it does not exist, refuse.
|
|
15
|
+
|
|
16
|
+
## Amendment rules — enforced in both modes
|
|
17
|
+
|
|
18
|
+
- Step numbers are immutable — never renumber. New steps get fresh numbers and place themselves via `Depends on:`.
|
|
19
|
+
- Removed steps stay in the file, marked `~~Step N~~ — removed: <why>`.
|
|
20
|
+
- A dependency on an already-closed issue is simply satisfied, so appending steps mid-flight is safe.
|
|
21
|
+
|
|
22
|
+
## Mode: first approval
|
|
23
|
+
|
|
24
|
+
1. Read the plan in full. Unresolved **Open Questions** → list them and ask the user to resolve them before approving.
|
|
25
|
+
2. Create the epic:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
bd create "<plan title>" --type=epic --priority=2 \
|
|
29
|
+
--description="Epic for plan <plan filename>. Ticket: <ticket filename>."
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. Create one child issue per step (parallel subagents are fine when there are many):
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bd create "<step title>" --type=task --parent=<epic-id> --priority=2 \
|
|
36
|
+
--description="Step N of <plan filename>: <what, files touched>"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
4. Wire step ordering from the plan's `Depends on:` lines: `bd dep add <later-step-id> <earlier-step-id>`.
|
|
40
|
+
5. Update the plan file atomically — the one place frontmatter and beads are synced: set `Beads Epic: <epic-id>`, set `Status: approved`, and append a **Beads** section mapping steps ↔ issue ids.
|
|
41
|
+
6. Report: the epic id, the issue ids, what `bd ready` shows unblocked, and that `/implement {NNN}` may now run.
|
|
42
|
+
|
|
43
|
+
## Mode: amendment re-sync
|
|
44
|
+
|
|
45
|
+
1. Read the plan and the epic's children (`bd show <epic-id>`). Diff plan steps against issues using the **Beads** section mapping:
|
|
46
|
+
- a step with no issue → create it (`--parent=<epic-id>`) and wire its `Depends on:` deps;
|
|
47
|
+
- a step marked removed whose issue is still open → `bd close <id> --reason="superseded by plan amendment"`;
|
|
48
|
+
- closed issues for unchanged steps → leave untouched.
|
|
49
|
+
2. Update the plan's **Beads** section with the new mapping; record the amendment in both places: a line in the plan body, and `bd update <epic-id> --append-notes="amended: +<n> steps, -<m> steps — <one-line why>"`.
|
|
50
|
+
3. Report what changed. A running `/implement` needs no restart — it re-derives its issue set from beads every iteration, so new issues simply join its queue.
|
|
51
|
+
|
|
52
|
+
This skill is idempotent in both modes: re-running with nothing to sync changes nothing and says so.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cancel
|
|
3
|
+
description: Human gate — cancel a line of work (ticket + plan + epic + worktree), or just the plan to re-plan against the same ticket.
|
|
4
|
+
argument-hint: <number> [plan]
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Cancel work for $ARGUMENTS. This is a human gate: it runs only on explicit user invocation.
|
|
9
|
+
|
|
10
|
+
Scope comes from the second word of the arguments:
|
|
11
|
+
- **(default)** — cancel the whole line of work: ticket, plan, epic, worktree, branch.
|
|
12
|
+
- **`plan`** — cancel only the plan, to re-plan differently: the ticket returns to `approved`, and `/plan {NNN}` may then write a fresh plan (its precondition permits replacing a `cancelled` one).
|
|
13
|
+
|
|
14
|
+
## Before destroying anything
|
|
15
|
+
|
|
16
|
+
1. Resolve what exists for {NNN}: ticket, plan, `Beads Epic`, worktree `.worktrees/<plan-name>`, branch (local and remote).
|
|
17
|
+
2. Show the blast radius and, if there is unmerged work, confirm with the user before proceeding:
|
|
18
|
+
- worktree: `git -C .worktrees/<plan-name> status --short` and `git log main..<plan-name> --oneline`
|
|
19
|
+
- epic: open issues (`bd show <epic-id>`)
|
|
20
|
+
|
|
21
|
+
## Steps
|
|
22
|
+
|
|
23
|
+
1. **Beads:** close the epic and all open child issues: `bd close <ids...> --reason="cancelled: <short why>"`.
|
|
24
|
+
2. **Git** (only after the confirmation above):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git worktree remove --force .worktrees/<plan-name>
|
|
28
|
+
git branch -D <plan-name>
|
|
29
|
+
git push origin --delete <plan-name> # if it was published
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. **Statuses** (the gate flip):
|
|
33
|
+
- scope `plan`: plan → `Status: cancelled`; ticket stays `approved`.
|
|
34
|
+
- default: plan → `cancelled` (if one exists), ticket → `cancelled`.
|
|
35
|
+
4. **Push — mandatory:** commit the status flips (`cancel: <ticket title> (ticket NNN) — <short why>`), then `git push` and `bd dolt push`.
|
|
36
|
+
5. **Report:** what was cancelled, what was destroyed, and — for scope `plan` — that `/plan {NNN}` is the next step.
|
|
37
|
+
|
|
38
|
+
Handle partial states gracefully: a ticket with no plan (just flip the ticket), a plan with no epic yet (no beads work), an epic with no worktree (no git work). Cancel what exists, skip what doesn't, report both.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: chore
|
|
3
|
+
description: Human gate — the lightweight lane. Take a small, low-risk change (typo, doc fix, config tweak, dep bump) end-to-end in one pass — chore ticket → worktree → gates + one review → merge — without a plan or epic.
|
|
4
|
+
argument-hint: <short description of the small change>
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Run the chore lane for: $ARGUMENTS. This is a human gate: invocation IS the approval — which is why this skill may merge to main at the end, and why it runs only on explicit user invocation.
|
|
9
|
+
|
|
10
|
+
## Lane guard — refuse and point to /ticket if any of these fail
|
|
11
|
+
|
|
12
|
+
- The change is small and low-risk: typo, docs, config tweak, dependency bump, tiny bugfix.
|
|
13
|
+
- No new feature surface, no schema/contract changes, no new patterns being established.
|
|
14
|
+
- Expected diff ≲ 5 files / ~150 lines. If the diff outgrows this during implementation, STOP: keep the ticket, tell the user it needs a real plan (`/plan {NNN}`), and leave the worktree in place for it.
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. **Ticket (audit trail):** allocate the next number and write `thoughts/tickets/{NNN}-{slug}.md` as usual, with `Type: chore` and `Status: approved` (invocation is approval). Note in the body: "Chore lane — no plan."
|
|
19
|
+
2. **Bead:** one task, no epic: `bd create "<title>" --type=task --priority=3 --description="Chore {NNN}: <what>"`, then claim it.
|
|
20
|
+
3. **Worktree:** from up-to-date main (`git pull --rebase`): `git worktree add .worktrees/{NNN}-c-{slug} -b {NNN}-c-{slug}`, publish with `git push -u origin {NNN}-c-{slug}`.
|
|
21
|
+
4. **Implement** the change in the worktree. Commit and push.
|
|
22
|
+
5. **Gates:** the gate commands defined in `thoughts/AGENTS.md` (Project Configuration), plus the target's `test` / `typecheck` scripts where defined.
|
|
23
|
+
6. **Review — one pass:** dispatch the reviewer mapped to the change's lane in `thoughts/AGENTS.md` (or a general code-review subagent if none is configured). Persist the output to `thoughts/reviews/{NNN}-round1.md` in the worktree and commit it. MUST FIX → fix, re-run gates, one re-review. Still blocked → stop and report; do not merge.
|
|
24
|
+
7. **Merge** (squash, as `/land` does): in the main checkout, `git pull --rebase`, `git merge --squash {NNN}-c-{slug}`, flip the ticket → `Status: implemented` in the same commit. Message: `chore: <title> (ticket NNN)`.
|
|
25
|
+
8. **Close out:** `bd close <id>`; `git push` + `bd dolt push` (mandatory); remove the worktree and branch (local + remote).
|
|
26
|
+
9. **Report:** merge commit, diff stat, review verdict.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: implement
|
|
3
|
+
description: Implement an approved plan in its own git worktree — claim the beads epic, execute steps via subagents in dependency order, run quality gates per step, then one full code review. Use when a plan is approved and its beads epic exists.
|
|
4
|
+
argument-hint: <plan number, e.g. 003>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Implement plan $ARGUMENTS per the pipeline in `thoughts/AGENTS.md`.
|
|
8
|
+
|
|
9
|
+
## Preconditions — refuse with the specific failure if unmet
|
|
10
|
+
|
|
11
|
+
1. The plan exists, has `Status: approved`, and `Beads Epic:` is set. If `review` → needs `/approve` first. If `merged` → already done.
|
|
12
|
+
2. **Claim the epic as the very first action** — this is the concurrency mutex:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
bd update <epic-id> --claim
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
If it is already claimed / in_progress by another session, STOP: another loop or session owns this plan.
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
1. From an up-to-date main (`git pull --rebase`), create the worktree — path and branch are both the plan name (plan filename without `.md`):
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git worktree add .worktrees/<plan-name> -b <plan-name>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If the worktree or branch already exists, resume it — do not recreate. On resume with a dirty worktree: diff the uncommitted changes against the in-progress step and either finish or reset them; never blindly commit.
|
|
29
|
+
2. Publish the branch immediately: `git push -u origin <plan-name>` — from here on, nothing exists only locally. (Skip only if the repo has no remote; note it in the report.)
|
|
30
|
+
|
|
31
|
+
## Execution loop
|
|
32
|
+
|
|
33
|
+
Repeat until every issue in the epic is closed. **Re-derive the issue set from beads at the top of every iteration** — plans can be amended mid-flight (`/approve` re-sync), and newly added issues simply join the queue.
|
|
34
|
+
|
|
35
|
+
1. `bd ready` → pick unblocked issues belonging to the epic. Claim each before working: `bd update <id> --claim`.
|
|
36
|
+
2. For each claimed issue, spawn an implementer subagent (Agent tool) working **inside the worktree directory**, giving it: the ticket, the plan, the step's text, and the instruction to follow existing repo conventions. Steps the plan marks parallelizable (disjoint file sets) may run as concurrent subagents; otherwise serialize — parallel edits to overlapping files in one worktree will conflict.
|
|
37
|
+
3. After each step, run the plan's quality gates inside the worktree: the gate commands defined in `thoughts/AGENTS.md` (Project Configuration), plus the target's own `test` / `typecheck` scripts where defined. Gates fail → fix before proceeding.
|
|
38
|
+
4. Gates pass → commit in the worktree (one commit per step: `step N: <title> (<issue-id>)`), `bd close <issue-id>`, and `git push` — every finished step is on the remote branch the moment it closes; a crashed session strands nothing.
|
|
39
|
+
5. Blocked on something only a human can decide → flag it (`bd update <issue-id> --add-label human`), leave the issue open, and continue with other unblocked steps. If nothing else can proceed, stop and report.
|
|
40
|
+
|
|
41
|
+
## Review — once per plan, at the end
|
|
42
|
+
|
|
43
|
+
1. Dispatch the reviewer mapped to the plan's `Target` in `thoughts/AGENTS.md` (Project Configuration) — both lanes' reviewers if the diff spans lanes; a thorough general code-review subagent if no reviewer is configured. Pass the ticket and plan paths.
|
|
44
|
+
2. Persist each round's full reviewer output verbatim to `thoughts/reviews/{NNN}-round{n}.md` inside the worktree and commit it — the review is an artifact that travels with the branch; its NITs are fodder for later chore tickets.
|
|
45
|
+
3. MUST FIX findings → fix in the worktree, re-run gates, commit, re-review (next round, next file). Cap at 3 rounds; if still blocked, flag the epic (`bd update <epic-id> --add-label human`) and report.
|
|
46
|
+
4. On APPROVED: commit the final review file first, then record the verdict against the resulting HEAD and push:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
bd update <epic-id> --append-notes="review: APPROVED sha=<worktree HEAD sha> rounds=<n>"
|
|
50
|
+
git push
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Never
|
|
54
|
+
|
|
55
|
+
- Never merge to main — that is `/land`, a human gate.
|
|
56
|
+
- Never edit files outside the worktree. Plan and ticket frontmatter are untouched here; live progress lives in beads.
|
|
57
|
+
- Never ask the user questions mid-run — use the `human` label and keep going where possible.
|
|
58
|
+
|
|
59
|
+
**Report:** steps completed, gate results, review verdict, worktree path, and that `/land {NNN}` is the next (human) step.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: land
|
|
3
|
+
description: Human gate — merge an implemented plan's worktree into main, flip plan/ticket statuses, close the beads epic, clean up, and push.
|
|
4
|
+
argument-hint: <plan number, e.g. 003>
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Land plan $ARGUMENTS. This is a human gate: it runs only on explicit user invocation.
|
|
9
|
+
|
|
10
|
+
## Preconditions — verify ALL; refuse with the specific failure otherwise
|
|
11
|
+
|
|
12
|
+
1. The plan exists with `Status: approved` and `Beads Epic:` set; the worktree `.worktrees/<plan-name>` exists.
|
|
13
|
+
2. Every issue in the epic is closed. Open `human`-labeled issues block landing unless the user explicitly waives them — list them and confirm.
|
|
14
|
+
3. The epic's notes contain `review: APPROVED sha=<sha>`, and that sha either equals the worktree's current HEAD or is connected to it by an unbroken chain of `rebased: <old>→<new> gates=pass` notes (written in step 1). Any other commits after the verdict mean the review phase of `/implement` must re-run first.
|
|
15
|
+
4. The review artifact exists in the worktree: `thoughts/reviews/{NNN}-round*.md`.
|
|
16
|
+
|
|
17
|
+
## Steps
|
|
18
|
+
|
|
19
|
+
1. **Freshness.** In the worktree: `git fetch`; if main has moved, rebase onto latest main.
|
|
20
|
+
- Rebase **conflicts** → STOP. Conflict resolution is semantic risk: resolve in the worktree, then re-run `/implement`'s review phase (new HEAD ⇒ new verdict) before landing.
|
|
21
|
+
- Rebase **clean** → re-run the quality gates (the gate commands in `thoughts/AGENTS.md` + target tests), then record the hop: `bd update <epic-id> --append-notes="rebased: <old-sha>→<new-sha> gates=pass"`. Gate failures block landing.
|
|
22
|
+
2. **Merge** — default is squash: one ticket = one reviewable unit = one commit on main.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git pull --rebase # in the main checkout
|
|
26
|
+
git merge --squash <plan-name>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Before committing, flip the state files **in the same commit**: plan → `Status: merged`, ticket → `Status: implemented`. Commit message: `<type>: <ticket title> (ticket NNN)`, body referencing the plan file and epic id.
|
|
30
|
+
3. **Close beads:** `bd close <epic-id>` plus any straggler step issues (`--reason` where non-obvious).
|
|
31
|
+
4. **Push — mandatory** where the root `AGENTS.md` grants git authority (skip only if the repo has no remote; note it in the report):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git push
|
|
35
|
+
bd dolt push
|
|
36
|
+
git status # MUST show "up to date with origin"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
5. **Clean up:**
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git worktree remove .worktrees/<plan-name>
|
|
43
|
+
git branch -D <plan-name>
|
|
44
|
+
git push origin --delete <plan-name>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
6. **Report:** the merge commit, statuses flipped, epic closed, cleanup done.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: next
|
|
3
|
+
description: Autonomous loop dispatcher — perform exactly one legal pipeline transition (plan an approved ticket, or implement an approved plan) and queue the human gates. Designed to be driven by /loop.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Run ONE iteration of the ticket → plan → implement pipeline (`thoughts/AGENTS.md`). Strictly non-interactive: never ask the user anything; flag decisions with the `human` label (`bd update <id> --add-label human`).
|
|
8
|
+
|
|
9
|
+
## Derive state — from disk and beads only, never from memory of past sessions
|
|
10
|
+
|
|
11
|
+
Spawn ONE read-only subagent (Explore, cheapest available model tier — mechanical parsing) to collect the snapshot and return it as a compact table, no prose. Do not gather inline: in loop mode this runs every iteration, and the driver's context must stay small for the `/implement` that may follow.
|
|
12
|
+
|
|
13
|
+
1. Plans: `Status` + `Beads Epic` of every file in `thoughts/plans/`.
|
|
14
|
+
2. Tickets: `Status` of every file in `thoughts/tickets/`.
|
|
15
|
+
3. Live: `bd ready`, `bd list --status=in_progress`, `bd human list`, and per in-flight epic: claim holder + last-activity times.
|
|
16
|
+
4. In-flight file sets: for every plan that is `approved` with open epic issues, the union of the files its steps declare.
|
|
17
|
+
|
|
18
|
+
The subagent gathers facts only. The transition decision below — legality, overlap, claim semantics — is made HERE, by you, from the snapshot.
|
|
19
|
+
|
|
20
|
+
## Pick the highest-priority legal transition — first match wins, execute exactly one
|
|
21
|
+
|
|
22
|
+
1. **Implement**: a plan with `Status: approved`, an epic recorded, open issues in the epic, the epic NOT claimed/in_progress by another session, **and no overlap between its declared file set and any in-flight plan's** → invoke `/implement {NNN}`. It claims first; if the claim fails, treat the plan as owned elsewhere and fall through to the next candidate. Candidates skipped for file overlap are reported, never silently dropped.
|
|
23
|
+
2. **Plan**: a ticket with `Status: approved` and no plan file with its number → invoke `/plan {NNN}`.
|
|
24
|
+
3. **Idle**: no legal transition → report idle immediately and stop. Keep this path cheap — no research, no subagents.
|
|
25
|
+
|
|
26
|
+
## Never
|
|
27
|
+
|
|
28
|
+
- Never perform `/approve`, `/land`, `/cancel`, or `/chore` — those are human gates. Instead, end every report with the **human queue**:
|
|
29
|
+
- plans in `Status: review` (awaiting `/approve`),
|
|
30
|
+
- plans whose epic notes carry an APPROVED review verdict (awaiting `/land`),
|
|
31
|
+
- anything in `bd human list`,
|
|
32
|
+
- **stale claims** — epics claimed/in_progress with no beads or git activity for >24h: likely a crashed session; a human should unclaim, after which `/implement` resumes cleanly.
|
|
33
|
+
- Never ask questions. On ambiguity, flag the nearest issue with the `human` label and move on.
|
|
34
|
+
|
|
35
|
+
One transition per invocation. When it completes (or refuses), report and stop — the outer `/loop` schedules the next iteration.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plan
|
|
3
|
+
description: Write an implementation plan for an approved ticket. Use when a ticket in thoughts/tickets is approved and needs a concrete plan before implementation.
|
|
4
|
+
argument-hint: <ticket number, e.g. 003>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Write the plan for ticket $ARGUMENTS — the instruction artifact of the pipeline in `thoughts/AGENTS.md`.
|
|
8
|
+
|
|
9
|
+
## Preconditions — refuse with the specific failure if unmet
|
|
10
|
+
|
|
11
|
+
1. The ticket `thoughts/tickets/{NNN}-*.md` exists.
|
|
12
|
+
2. The ticket has `Status: approved`. If `draft`, tell the user to review and approve the ticket first.
|
|
13
|
+
3. No plan with number {NNN} exists in `thoughts/plans/` (unless its `Status` is `cancelled`). If one exists, stop and report it — plans are revised, not duplicated.
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. **Research first.** Read the ticket in full, the product docs in `thoughts/docs/`, and the code of the ticket's Target. Understand existing conventions before proposing anything — the plan must follow the repo's grain, and the code reviewers will hold the implementation to it.
|
|
18
|
+
2. **Frontend constraint.** If the plan includes frontend work, check `thoughts/AGENTS.md` (Project Configuration) for design-system constraints (e.g. no new pages until the design system exists) and honor any configured design skill for on-brand implementation. Note both in the plan.
|
|
19
|
+
3. **Write** `thoughts/plans/{NNN}-{t}-{kebab-case-title}.md` — `t` = first letter of Type, `NNN` = same number as the ticket:
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
---
|
|
23
|
+
Status: review
|
|
24
|
+
Tags: []
|
|
25
|
+
Type: <type>
|
|
26
|
+
Target: <target>
|
|
27
|
+
Ticket Origin: <ticket filename>
|
|
28
|
+
Beads Epic:
|
|
29
|
+
---
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
(`Beads Epic` stays empty — `/approve` fills it.)
|
|
33
|
+
|
|
34
|
+
Body sections:
|
|
35
|
+
- **Context** — why this work exists, link to the ticket, the relevant existing code.
|
|
36
|
+
- **Implementation Steps** — numbered. Each step states: what to do, files touched, and an explicit `Depends on: step N` line (or `Depends on: none`). Steps must be independently completable and gate-checkable. Mark steps whose file sets are disjoint as parallelizable. These `Depends on:` lines become beads issue dependencies at approval — they are the machine-readable form; a mermaid diagram of the step graph is optional, for human readability only.
|
|
37
|
+
- **Quality Gates** — what must pass after every step: the gate commands defined in `thoughts/AGENTS.md` (Project Configuration), plus the target's own `test` / `typecheck` / `build` scripts where defined.
|
|
38
|
+
- **Verification** — how to exercise the finished work end-to-end, mapped to the ticket's acceptance criteria.
|
|
39
|
+
- **Open Questions** — anything unresolved.
|
|
40
|
+
|
|
41
|
+
4. **Stop at `review`.** Do NOT create beads issues, worktrees, or code. Report the plan path and that it awaits human review → `/approve {NNN}`.
|
|
42
|
+
|
|
43
|
+
If something is ambiguous and no user is available (unattended run), do not guess silently: record it under **Open Questions** — the human resolves it at review time.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: queue
|
|
3
|
+
description: Read-only dashboard of the ticket → plan → implement → land pipeline — what is in flight, what is stalled, and what awaits a human decision. Use when the user asks what needs them, what's in progress, or for overall pipeline status.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Build the pipeline dashboard. Strictly read-only — no mutations to files, beads, or git.
|
|
7
|
+
|
|
8
|
+
## Gather — delegate to a cheap subagent
|
|
9
|
+
|
|
10
|
+
Spawn ONE read-only subagent (Explore, cheapest available model tier — this is mechanical parsing) to collect the snapshot below and return it as a compact table, no prose. Do not gather inline: delegation keeps this session's context clean.
|
|
11
|
+
|
|
12
|
+
1. Tickets: `Status` of every file in `thoughts/tickets/`.
|
|
13
|
+
2. Plans: `Status` + `Beads Epic` of every file in `thoughts/plans/`.
|
|
14
|
+
3. Beads: `bd ready`, `bd list --status=in_progress`, `bd human list`, and per in-flight epic: open/closed child counts, last-activity times, and any `review:` / `rebased:` notes.
|
|
15
|
+
4. Worktrees: `git worktree list`; branches ahead of main.
|
|
16
|
+
5. Recently landed: the last ~5 main commits referencing tickets.
|
|
17
|
+
|
|
18
|
+
Interpretation of the snapshot (staleness, what needs a human) happens here, not in the subagent.
|
|
19
|
+
|
|
20
|
+
## Report — human queue first
|
|
21
|
+
|
|
22
|
+
1. **Needs you now**
|
|
23
|
+
- plans in `Status: review` → awaiting `/approve`
|
|
24
|
+
- epics whose notes carry `review: APPROVED` for the worktree's HEAD → awaiting `/land`
|
|
25
|
+
- `bd human list` flags
|
|
26
|
+
- **stale claims** — epics claimed/in_progress with no beads or git activity for >24h: likely a crashed session; note the recovery (unclaim, then `/implement` resumes)
|
|
27
|
+
2. **In flight** — plans `approved` with open epic issues: N/M steps closed, claim holder, last activity, worktree path
|
|
28
|
+
3. **Ready to start** — plans `approved` awaiting `/implement`; tickets `approved` without a plan (→ `/plan`)
|
|
29
|
+
4. **Drafts** — tickets in `draft` awaiting your approval
|
|
30
|
+
5. **Recently landed** — the last few merges
|
|
31
|
+
|
|
32
|
+
Keep it compact — one line per item, with ids and the next command inline. Omit empty sections.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ticket
|
|
3
|
+
description: Create a new work ticket in thoughts/tickets from an idea. Use when the user describes a new feature, bug, refactor, or chore that should enter the ticket → plan → implement pipeline.
|
|
4
|
+
argument-hint: <one-line idea or description>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Create a new ticket — the intent artifact of the pipeline described in `thoughts/AGENTS.md`.
|
|
8
|
+
|
|
9
|
+
Input: $ARGUMENTS
|
|
10
|
+
|
|
11
|
+
## Steps
|
|
12
|
+
|
|
13
|
+
1. **Allocate the number.** Next number = the highest number used by any file in `thoughts/tickets/` or `thoughts/plans/`, plus one, zero-padded to 3 digits.
|
|
14
|
+
2. **Classify.** Type: `feature | bug | refactor | chore`. Target: one of the targets defined in `thoughts/AGENTS.md` (Project Configuration). Infer both from the idea and the product docs in `thoughts/docs/`. If the target is genuinely ambiguous, ask the user; when running unattended, pick the best fit and record the assumption under Open Questions.
|
|
15
|
+
3. **Write** `thoughts/tickets/{NNN}-{kebab-case-title}.md`:
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
---
|
|
19
|
+
Status: draft
|
|
20
|
+
Tags: []
|
|
21
|
+
Type: <type>
|
|
22
|
+
Target: <target>
|
|
23
|
+
---
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Body sections:
|
|
27
|
+
- **Summary** — what and why, grounded in the product docs in `thoughts/docs/` (user journeys, goals).
|
|
28
|
+
- **Scope** — explicitly in scope / out of scope.
|
|
29
|
+
- **Acceptance Criteria** — checkable outcomes, not implementation steps.
|
|
30
|
+
- **Open Questions** — if any; empty section is fine.
|
|
31
|
+
|
|
32
|
+
4. **Stay high-level.** A ticket describes WHAT and WHY — never implementation steps; that is the plan's job. A ticket must fit a single reviewable unit of work: if the idea is bigger than that, split it into multiple tickets and tell the user how you split it.
|
|
33
|
+
5. **Report** the file path and remind the user: the ticket stays `draft` until they approve it (flip `Status: approved`), which is what makes it eligible for `/plan`.
|
|
34
|
+
|
|
35
|
+
Do NOT create beads issues, plans, or code here.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Agent Instructions
|
|
2
|
+
|
|
3
|
+
This project uses **bd** (beads) for issue tracking — run `bd prime` for full workflow context.
|
|
4
|
+
|
|
5
|
+
> **Architecture:** Issues live in a local Dolt DB (`.beads/dolt/`); sync uses `bd dolt push/pull` over `refs/dolt/data` on your git remote (separate from `refs/heads/*`). `.beads/issues.jsonl` is a passive export, not the source of truth — see [SYNC_CONCEPTS.md](https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md) for anti-patterns.
|
|
6
|
+
|
|
7
|
+
## Folder Structure
|
|
8
|
+
|
|
9
|
+
- Use the `thoughts/` folder to define work — the ticket → plan → implement → land pipeline is described in `thoughts/AGENTS.md`.
|
|
10
|
+
- `thoughts/docs/` holds product/context docs that tickets are grounded in.
|
|
11
|
+
|
|
12
|
+
## Beads Issue Tracker
|
|
13
|
+
|
|
14
|
+
### Quick Reference
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bd ready # Find available work
|
|
18
|
+
bd show <id> # View issue details
|
|
19
|
+
bd update <id> --claim # Claim work
|
|
20
|
+
bd close <id> # Complete work
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Rules
|
|
24
|
+
|
|
25
|
+
- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
|
|
26
|
+
- Run `bd prime` for detailed command reference and session close protocol
|
|
27
|
+
- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files
|
|
28
|
+
|
|
29
|
+
## Quality Gates
|
|
30
|
+
|
|
31
|
+
<!-- Define the commands that must pass before work merges, and keep them in sync
|
|
32
|
+
with the "Quality gates" line in thoughts/AGENTS.md (Project Configuration). -->
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm test
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Session Completion
|
|
39
|
+
|
|
40
|
+
**When ending a work session:**
|
|
41
|
+
|
|
42
|
+
1. **File issues for remaining work** — create beads issues for anything that needs follow-up
|
|
43
|
+
2. **Run quality gates** (if code changed) — tests, linters, builds
|
|
44
|
+
3. **Update issue status** — close finished work, update in-progress items
|
|
45
|
+
4. **Push to remote** — both code and beads data:
|
|
46
|
+
```bash
|
|
47
|
+
git pull --rebase
|
|
48
|
+
git push
|
|
49
|
+
bd dolt push
|
|
50
|
+
```
|
|
51
|
+
5. **Verify** — all changes committed AND pushed
|
|
52
|
+
6. **Hand off** — provide context for next session
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Workflow Setup
|
|
2
|
+
|
|
3
|
+
- Do not edit files outside of the ticket-plan tree of the current task
|
|
4
|
+
|
|
5
|
+
The pipeline is **ticket → plan → implement → land**. This file describes the artifacts and their states. Every state transition is owned by a skill — run the skill, never flip a `Status` by hand. The one exception: approving a ticket (`draft` → `approved`) is a deliberate hand-edit by the human — that edit *is* the gate:
|
|
6
|
+
|
|
7
|
+
| Skill | Transition | Gate |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `/ticket <idea>` | new ticket (`draft`) | — |
|
|
10
|
+
| — (hand-edit, the one exception) | ticket `draft` → `approved` | **human** |
|
|
11
|
+
| `/plan <NNN>` | ticket `approved` → plan (`review`) | — |
|
|
12
|
+
| `/approve <NNN>` | plan `review` → `approved`; creates beads epic + issues. Re-run on an approved plan = **amendment re-sync** | **human** |
|
|
13
|
+
| `/implement <NNN>` | executes approved plan in its worktree; ends with a review verdict | — |
|
|
14
|
+
| `/land <NNN>` | merge to main; plan → `merged`, ticket → `implemented` | **human** |
|
|
15
|
+
| `/chore <idea>` | lightweight lane: chore ticket → worktree → gates + one review → merge, in one pass | **human** |
|
|
16
|
+
| `/cancel <NNN> [plan]` | cancel the line of work (or just the plan, to re-plan); closes epic, removes worktree | **human** |
|
|
17
|
+
| `/queue` | read-only dashboard: in flight, stalled, awaiting a human | — |
|
|
18
|
+
| `/next` | one autonomous iteration (for `/loop`); never crosses human gates | — |
|
|
19
|
+
|
|
20
|
+
**State rule:** frontmatter `Status` records the last gate an artifact passed and changes only at hand-offs. Live execution state (what is in progress *right now*) lives in beads only — look it up via the plan's `Beads Epic` id (`bd show <id>`, `bd list --status=in_progress`), never by editing frontmatter.
|
|
21
|
+
|
|
22
|
+
**Chore lane:** small, low-risk changes (typo, docs, config tweak, dep bump) skip the plan: `/chore` runs the whole lane in a single human-invoked pass. If the diff outgrows ~5 files / ~150 lines, the change leaves the lane and gets a real plan.
|
|
23
|
+
|
|
24
|
+
## Project Configuration
|
|
25
|
+
|
|
26
|
+
> Edit this section for your project — the pipeline skills read these values.
|
|
27
|
+
|
|
28
|
+
- **Targets:** `app` <!-- the areas of the repo work can land in, e.g. cms | jobs | web | utils for a monorepo, or a single name for a simple repo -->
|
|
29
|
+
- **Quality gates:** `npm test` <!-- the command(s) that must pass after every implementation step, e.g. root `pnpm check` plus workspace test/typecheck scripts -->
|
|
30
|
+
- **Reviewers:** general code review <!-- map targets to reviewer agents if you have them, e.g. cms|jobs|utils → backend-code-reviewer, web → frontend-code-reviewer -->
|
|
31
|
+
- **Product docs:** `thoughts/docs/` <!-- where tickets ground their Summary; add your product/vision doc here -->
|
|
32
|
+
- **Frontend constraints:** none <!-- e.g. "no new pages until the design system in apps/web is established; route UI design through impeccable" -->
|
|
33
|
+
|
|
34
|
+
## Tickets
|
|
35
|
+
|
|
36
|
+
Tickets are the originating point of most of the work in this system. They are the starting artifacts of work, laying out the ideas and overall feature/work definition to be implemented. They are *not* concrete implementations, but rather high-level descriptions of what needs to be done.
|
|
37
|
+
Each ticket is a self-contained unit of work and should be able to fit into a single reviewable unit of work.
|
|
38
|
+
|
|
39
|
+
- They live in [./tickets].
|
|
40
|
+
|
|
41
|
+
Frontmatter Includes:
|
|
42
|
+
- Status: 'draft' | 'approved' | 'implemented' | 'cancelled'
|
|
43
|
+
- `draft` → `approved` is a human decision; it makes the ticket eligible for `/plan`.
|
|
44
|
+
- `approved` → `implemented` is flipped by `/land` when the plan's worktree merges.
|
|
45
|
+
- Tags: A list of tags associated with the ticket.
|
|
46
|
+
- Type: 'feature' | 'bug' | 'refactor' | 'chore'
|
|
47
|
+
- Target: one of the targets defined in Project Configuration above
|
|
48
|
+
|
|
49
|
+
Naming Conventions:
|
|
50
|
+
- {NUMBER}-{KEBAB-CASE-TITLE} / Example: `001-setup-test-harness`
|
|
51
|
+
|
|
52
|
+
## Plans
|
|
53
|
+
|
|
54
|
+
Plans are the concrete steps to take to complete a ticket. They are written by `/plan` based on the ticket's target and any other relevant context. If they include frontend work, they also honor the project's frontend constraints (Project Configuration) for on-brand implementation.
|
|
55
|
+
|
|
56
|
+
- They live in [./plans]
|
|
57
|
+
- They include an implementation plan broken down in steps. Each step carries an explicit `Depends on:` line; steps with disjoint file sets are marked parallelizable.
|
|
58
|
+
- The `Depends on:` lines are the machine-readable dependency graph — they become beads issue dependencies at approval. A mermaid diagram of the step graph is optional, for human readability only.
|
|
59
|
+
- Plans include a beads list. Each plan is its own beads epic.
|
|
60
|
+
- Beads epics (and their step issues) are created by `/approve` when the plan is approved.
|
|
61
|
+
|
|
62
|
+
**Amendments** — plans change after approval; the sanctioned path is: edit the plan file, then re-run `/approve {NNN}` to re-sync the epic. Rules:
|
|
63
|
+
- Step numbers are immutable — never renumber. New steps get fresh numbers and place themselves via `Depends on:`.
|
|
64
|
+
- Removed steps stay in the file, marked `~~Step N~~ — removed: <why>`.
|
|
65
|
+
- Amending mid-flight is safe: a running `/implement` re-derives its issue set from beads each iteration, so added steps join its queue automatically.
|
|
66
|
+
|
|
67
|
+
Frontmatter Includes:
|
|
68
|
+
- Status: 'draft' | 'review' | 'approved' | 'merged' | 'cancelled'
|
|
69
|
+
- `review` = awaiting human review. `review` → `approved` only via `/approve`; `approved` → `merged` only via `/land`.
|
|
70
|
+
- There is deliberately no `in progress` status — live progress is a beads query, not frontmatter.
|
|
71
|
+
- Tags: A list of tags associated with the ticket.
|
|
72
|
+
- Type: 'feature' | 'bug' | 'refactor' | 'chore'
|
|
73
|
+
- Target: one of the targets defined in Project Configuration above
|
|
74
|
+
- Ticket Origin: The ticket that this plan is associated with
|
|
75
|
+
- Beads Epic: The beads epic that this plan is associated with (set by `/approve`)
|
|
76
|
+
|
|
77
|
+
Naming Conventions:
|
|
78
|
+
- {NUMBER}-{TYPE-FIRST-LETTER}-{KEBAB-CASE-TITLE} / Example: `001-f-setup-test-harness`
|
|
79
|
+
- The Number is always the same number as the ticket number.
|
|
80
|
+
|
|
81
|
+
## Reviews
|
|
82
|
+
|
|
83
|
+
Full review output is persisted verbatim to `thoughts/reviews/{NNN}-round{n}.md`, written inside the worktree during the review phase and merged to main at `/land` — the audit trail travels with the change. The machine-checked verdict (`review: APPROVED sha=...`) lives on the epic's notes; the file holds the complete findings, including NITs (fodder for later chore tickets).
|
|
84
|
+
|
|
85
|
+
## Implementation
|
|
86
|
+
|
|
87
|
+
Implementation is owned by `/implement` and happens only after a plan is `approved`. Its first action is claiming the epic (`bd update <epic-id> --claim`) — the concurrency mutex that keeps parallel sessions and loops off the same plan.
|
|
88
|
+
|
|
89
|
+
Each plan is implemented within its own git worktree at `.worktrees/<plan-name>` (worktree and branch are both named after the plan) so it stays separate from the main branch. The branch is published immediately, and implementer subagents execute the steps in beads dependency order — one commit per step, pushed as soon as the step closes, so a crashed session strands nothing.
|
|
90
|
+
After each step, the quality gates run inside the worktree: the gate commands in Project Configuration plus the target's own `test` / `typecheck` scripts where defined. A step is closed in beads only when its gates pass.
|
|
91
|
+
|
|
92
|
+
`/next` schedules around declared file sets: it will not start a plan whose files overlap a plan already in flight.
|
|
93
|
+
|
|
94
|
+
## After Implementation
|
|
95
|
+
|
|
96
|
+
One full code review per plan, at the end (not per step — the per-step check is the mechanical gates). The reviewer is dispatched by the plan's `Target` using the reviewer mapping in Project Configuration; both lanes' reviewers if the diff spans lanes, a thorough general code review if none is configured. MUST FIX findings are fixed and re-reviewed until APPROVED; each round is persisted to `thoughts/reviews/` and the verdict is recorded on the epic's notes (`review: APPROVED sha=...`), which is the precondition `/land` checks. Merging to main is `/land`, a human gate.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|