scaffold-agent-specs 0.1.1 → 0.1.3
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 +17 -1
- package/lib/cli.js +21 -4
- package/lib/released-fingerprints.json +56 -0
- package/lib/scaffold.js +70 -0
- package/package.json +14 -3
- package/scaffold/.agent-specs/templates/adr/ADR.md +5 -5
- package/scaffold/.agent-specs/templates/feature/ACCEPTANCE_MATRIX.md +4 -4
- package/scaffold/.agent-specs/templates/feature/DESIGN.md +1 -1
- package/scaffold/.agent-specs/templates/feature/PLAN.md +4 -6
- package/scaffold/.agent-specs/templates/feature/RESEARCH.md +3 -3
- package/scaffold/.agent-specs/templates/feature/TASKS.md +9 -1
- package/scaffold/.agent-specs/templates/project/ARCHITECTURE.md +4 -4
- package/scaffold/.agent-specs/templates/project/GLOSSARY.md +3 -3
- package/scaffold/AGENTS.md +13 -8
- package/scaffold/docs/WORKFLOW.md +24 -13
- package/scaffold/docs/features/README.md +1 -1
package/README.md
CHANGED
|
@@ -62,6 +62,8 @@ npx scaffold-agent-specs feature "Account dashboard" --approved --design --resea
|
|
|
62
62
|
|
|
63
63
|
**Important:** The CLI copies and personalizes headings, IDs, titles, and dates. It **does not invent a feature spec**. Your coding agent must populate the remaining placeholders from the approved conversation, then **stop** until you separately authorize implementation. The `--approved` flag is an acknowledgment; the CLI cannot verify the conversation itself.
|
|
64
64
|
|
|
65
|
+
The `feature` command is a convenience for people. Agents are told to create feature directories by copying the templates themselves, following the steps in `docs/WORKFLOW.md`, so they don't depend on the CLI being installed or reachable from a sandbox.
|
|
66
|
+
|
|
65
67
|
## `init` installs
|
|
66
68
|
|
|
67
69
|
```text
|
|
@@ -87,6 +89,9 @@ No speculative feature, ADR, architecture document, glossary, or convention docu
|
|
|
87
89
|
| --- | --- |
|
|
88
90
|
| `init` | Copy the initial scaffold into the current directory. Never overwrite existing files. |
|
|
89
91
|
| `init --dry-run` | Preview which files would be created or skipped. |
|
|
92
|
+
| `update` | Bring scaffold files up to this version. Replace only files that are unmodified; skip customized ones. |
|
|
93
|
+
| `update --dry-run` | Preview which files would be updated, created, or skipped. |
|
|
94
|
+
| `update --force` | Also overwrite customized scaffold files, discarding local changes. |
|
|
90
95
|
| `feature "Title" --approved` | Create the next `feature-NNN-title/` and its three required docs. |
|
|
91
96
|
| `feature "Title" --approved --design` | Include optional detailed design. |
|
|
92
97
|
| `feature "Title" --approved --research` | Include optional research. |
|
|
@@ -95,7 +100,16 @@ No speculative feature, ADR, architecture document, glossary, or convention docu
|
|
|
95
100
|
| `--dir PATH` | Work in a specified repository root instead of the current directory. |
|
|
96
101
|
| `--help` / `--version` | Show help or the CLI version. |
|
|
97
102
|
|
|
98
|
-
Feature IDs are allocated above the **largest existing** feature ID, starting at `001`. Running `init` again adds newly missing files but never replaces
|
|
103
|
+
Feature IDs are allocated above the **largest existing** feature ID, starting at `001`. Running `init` again adds newly missing files but never replaces existing ones. `init` refuses to write through symlinked paths under the chosen root.
|
|
104
|
+
|
|
105
|
+
## Updating an existing repository
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
npx scaffold-agent-specs@latest update --dry-run # preview
|
|
109
|
+
npx scaffold-agent-specs@latest update
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`update` compares each scaffold file in your repository with every released version of it. A file that still matches a released version is replaced with the current one, and a file that is missing is created. A file you have customized is skipped and reported, so you can merge the changes by hand or rerun with `--force`. Formatting-only differences (for example, Prettier padding tables) don't count as customizations. Feature documents in `docs/features/feature-*/` are never touched, so existing features keep the layout they were written with.
|
|
99
113
|
|
|
100
114
|
There is intentionally no `implement` command: an agent should follow `AGENTS.md` and `docs/WORKFLOW.md` and wait for a separate implementation instruction. ADRs can be created from `.agent-specs/templates/adr/ADR.md` once architectural decisions are adopted.
|
|
101
115
|
|
|
@@ -103,6 +117,8 @@ There is intentionally no `implement` command: an agent should follow `AGENTS.md
|
|
|
103
117
|
|
|
104
118
|
```sh
|
|
105
119
|
npm test # Built-in Node.js test runner
|
|
120
|
+
npm run format # Format scaffold Markdown with Prettier
|
|
121
|
+
npm run fingerprints # Record scaffold fingerprints for `update` (before each release)
|
|
106
122
|
npm run pack:check # Preview npm-published file manifest
|
|
107
123
|
npm pack # Produce local npm tarball for testing
|
|
108
124
|
```
|
package/lib/cli.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
|
-
import { initProject, createFeature } from './scaffold.js';
|
|
3
|
+
import { initProject, createFeature, updateProject } from './scaffold.js';
|
|
4
4
|
|
|
5
5
|
const help = `scaffold-agent-specs: spec-driven scaffolding for coding agents
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
8
|
scaffold-agent-specs init [--dir PATH] [--dry-run]
|
|
9
|
+
scaffold-agent-specs update [--dir PATH] [--dry-run] [--force]
|
|
9
10
|
scaffold-agent-specs feature "Feature title" --approved [options]
|
|
10
11
|
scaffold-agent-specs --version
|
|
11
12
|
scaffold-agent-specs --help
|
|
@@ -18,9 +19,16 @@ Options for feature:
|
|
|
18
19
|
--dry-run Preview without writing; approval not required for a preview
|
|
19
20
|
--dir PATH Target repository root (default: current directory)
|
|
20
21
|
|
|
22
|
+
Options for update:
|
|
23
|
+
--dry-run Preview without writing
|
|
24
|
+
--force Also overwrite files that were modified locally
|
|
25
|
+
--dir PATH Target repository root (default: current directory)
|
|
26
|
+
|
|
21
27
|
The CLI copies templates, but does not generate a specification or implement code.
|
|
22
28
|
Your agent must fill the documents from the approved discussion and stop before implementation.
|
|
23
|
-
Existing files are never overwritten by init.
|
|
29
|
+
Existing files are never overwritten by init. update replaces only files that
|
|
30
|
+
still match a released version; locally modified files are skipped unless --force.
|
|
31
|
+
Feature documents in docs/features/feature-*/ are never touched.
|
|
24
32
|
`;
|
|
25
33
|
|
|
26
34
|
export function run(args) {
|
|
@@ -34,12 +42,16 @@ export function run(args) {
|
|
|
34
42
|
return;
|
|
35
43
|
}
|
|
36
44
|
const [command, ...rest] = args;
|
|
37
|
-
if (!['init', 'feature'].includes(command)) throw new Error(`Unknown command: ${command}. Try --help.`);
|
|
45
|
+
if (!['init', 'update', 'feature'].includes(command)) throw new Error(`Unknown command: ${command}. Try --help.`);
|
|
38
46
|
|
|
39
47
|
const flags = new Set();
|
|
40
48
|
const positionals = [];
|
|
41
49
|
let dir = process.cwd();
|
|
42
|
-
const allowed =
|
|
50
|
+
const allowed = new Set({
|
|
51
|
+
init: ['--dry-run'],
|
|
52
|
+
update: ['--dry-run', '--force'],
|
|
53
|
+
feature: ['--dry-run', '--approved', '--design', '--research', '--handoff'],
|
|
54
|
+
}[command]);
|
|
43
55
|
|
|
44
56
|
for (let i = 0; i < rest.length; i++) {
|
|
45
57
|
const argument = rest[i];
|
|
@@ -62,6 +74,11 @@ export function run(args) {
|
|
|
62
74
|
initProject(dir, { dryRun: flags.has('--dry-run') });
|
|
63
75
|
return;
|
|
64
76
|
}
|
|
77
|
+
if (command === 'update') {
|
|
78
|
+
if (positionals.length) throw new Error('update takes no positional arguments.');
|
|
79
|
+
updateProject(dir, { dryRun: flags.has('--dry-run'), force: flags.has('--force') });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
65
82
|
if (!positionals.length) throw new Error('Missing feature title. Try `feature "User statistics page" --approved`.');
|
|
66
83
|
createFeature(dir, positionals.join(' '), {
|
|
67
84
|
approved: flags.has('--approved'),
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
".agent-specs/templates/adr/ADR.md": [
|
|
3
|
+
"6bdd5aa7149e0e3a53ddf1ff3fc067c3797e0c9942844cbb00b34c228204183c"
|
|
4
|
+
],
|
|
5
|
+
".agent-specs/templates/conventions/CONVENTION.md": [
|
|
6
|
+
"462a9cbf6c502f6692c9813a2da02e796a3547d02fb58058e2153bf4e3dc91d3"
|
|
7
|
+
],
|
|
8
|
+
".agent-specs/templates/feature/ACCEPTANCE_MATRIX.md": [
|
|
9
|
+
"0efef77a6c06737d224289611ab9cd7640a987395bcb526fff4f4b5f86295753"
|
|
10
|
+
],
|
|
11
|
+
".agent-specs/templates/feature/DESIGN.md": [
|
|
12
|
+
"301b5b38817a3fa1f21d7ac1f9816f5edc294610322e82bbaf51898485a00934"
|
|
13
|
+
],
|
|
14
|
+
".agent-specs/templates/feature/HANDOFF.md": [
|
|
15
|
+
"5d089e10cd26341154f71262f1f7bbaf851ef42bdea73bf26a2c80cc647cc9dc"
|
|
16
|
+
],
|
|
17
|
+
".agent-specs/templates/feature/PLAN.md": [
|
|
18
|
+
"8502cc0a36a3868f8f255863db7abd58b9626ae0b9a9c76875aa77441a0cac2c",
|
|
19
|
+
"e23d02f2b21676dcc9493eee8b2ec617b922a912e118762d6afe191ac391f826"
|
|
20
|
+
],
|
|
21
|
+
".agent-specs/templates/feature/RESEARCH.md": [
|
|
22
|
+
"e68f104f0b35440da933573d7f04a861f62a8f8248a3156b975824d2cac40c53"
|
|
23
|
+
],
|
|
24
|
+
".agent-specs/templates/feature/TASKS.md": [
|
|
25
|
+
"0b6f660cb321bdbbeecd21af788e3954a01726bf111f079707fd927451ef49e7",
|
|
26
|
+
"a4c5de105bb6d474e2131994cb90fbcd4f3e436ba22b92a0f865755d00064d0d"
|
|
27
|
+
],
|
|
28
|
+
".agent-specs/templates/project/ARCHITECTURE.md": [
|
|
29
|
+
"3ed1a7ae1021f999fa7769f406f7de5e008d9f8c09e219214c817f580a1d9ae5"
|
|
30
|
+
],
|
|
31
|
+
".agent-specs/templates/project/GLOSSARY.md": [
|
|
32
|
+
"5f9109b0699879db0b6563e9df4889c3b0963893c43a1fd82a71f5f3d7327af9"
|
|
33
|
+
],
|
|
34
|
+
"AGENTS.md": [
|
|
35
|
+
"70196e937a5782962f69c2c0735929059fac6c60b724977ebbfea9d0e4c84b20",
|
|
36
|
+
"c08f3412d558b6992b0a2e003d5be0de201502846453c2b2da70c2d682d5815a",
|
|
37
|
+
"bc70d6dee9f3f76affb0636ff804a112885b0973aaa2753ac970fc83d0260b5e",
|
|
38
|
+
"a09404a3dce7e2c1f7aa0efce59c5b075943ad768a02b62dc51e08e44a050318"
|
|
39
|
+
],
|
|
40
|
+
"CLAUDE.md": [
|
|
41
|
+
"272bcb5a9f136af56c1c93203c21976e02a09ed0a59d2515fad23d24b6c34408"
|
|
42
|
+
],
|
|
43
|
+
"docs/WORKFLOW.md": [
|
|
44
|
+
"0712abf011e6632fcdaee95c9b0c7bcad39808b5d28678c25aa0c05d281f795f",
|
|
45
|
+
"637e83ce425e97ee9751a8500f5928d1f1ed2536e8d1a02b85bf6e11bc937192",
|
|
46
|
+
"9dd7762484311d7a2a59620d4e89c61e4eb68688d9ebe1b3e2f2ac6d114373fd"
|
|
47
|
+
],
|
|
48
|
+
"docs/adr/README.md": [
|
|
49
|
+
"2f27a4a5ecfb92725875c0b859194588b0ed367ac87b7d321ba063062abf25d5"
|
|
50
|
+
],
|
|
51
|
+
"docs/features/README.md": [
|
|
52
|
+
"a46ffb46dc49d5304db438179e6b090665d706d2f09c50c56bb2a0c09c92b5da",
|
|
53
|
+
"3fb7c6fa1177a5cb940e8066d18624ce0d32c76b945a9b1f183d8809f40a7275",
|
|
54
|
+
"ddf40d2b1fd1fb821799e59df15c4ab9ce9edf1e231b3fce5776ff3635c3ffaf"
|
|
55
|
+
]
|
|
56
|
+
}
|
package/lib/scaffold.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
1
2
|
import fs from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
4
5
|
|
|
5
6
|
export const bundledScaffold = fileURLToPath(new URL('../scaffold/', import.meta.url));
|
|
7
|
+
export const releasedFingerprintsFile = fileURLToPath(new URL('./released-fingerprints.json', import.meta.url));
|
|
6
8
|
const requiredFeatureFiles = ['PLAN.md', 'ACCEPTANCE_MATRIX.md', 'TASKS.md'];
|
|
7
9
|
const optionalFeatureFiles = ['DESIGN.md', 'RESEARCH.md', 'HANDOFF.md'];
|
|
8
10
|
|
|
@@ -84,6 +86,74 @@ export function initProject(target, { dryRun = false, log = console.log } = {})
|
|
|
84
86
|
return { created, skipped };
|
|
85
87
|
}
|
|
86
88
|
|
|
89
|
+
// Identifies a file's content regardless of formatting, so a released file that a
|
|
90
|
+
// formatter such as Prettier has rewritten (padding, emphasis markers) still matches.
|
|
91
|
+
export function fingerprint(content) {
|
|
92
|
+
const normalized = content.replace(/[\s*_-]/g, '');
|
|
93
|
+
return crypto.createHash('sha256').update(normalized).digest('hex');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getBundledFingerprints() {
|
|
97
|
+
return Object.fromEntries(getBundledFiles(bundledScaffold).map((rel) => [
|
|
98
|
+
rel.split(path.sep).join('/'),
|
|
99
|
+
fingerprint(fs.readFileSync(path.join(bundledScaffold, rel), 'utf8')),
|
|
100
|
+
]));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function updateProject(target, { dryRun = false, force = false, log = console.log } = {}) {
|
|
104
|
+
const root = path.resolve(target);
|
|
105
|
+
assertDirectory(root);
|
|
106
|
+
const released = JSON.parse(fs.readFileSync(releasedFingerprintsFile, 'utf8'));
|
|
107
|
+
const files = getBundledFiles(bundledScaffold);
|
|
108
|
+
const plan = [];
|
|
109
|
+
|
|
110
|
+
// Decide every action before writing anything.
|
|
111
|
+
for (const rel of files) {
|
|
112
|
+
const destination = path.join(root, rel);
|
|
113
|
+
assertSafePath(root, destination);
|
|
114
|
+
const incoming = fs.readFileSync(path.join(bundledScaffold, rel), 'utf8');
|
|
115
|
+
if (!pathExists(destination)) {
|
|
116
|
+
plan.push({ rel, action: 'create', incoming });
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (!fs.statSync(destination).isFile()) throw new Error(`Not a file: ${destination}`);
|
|
120
|
+
const current = fingerprint(fs.readFileSync(destination, 'utf8'));
|
|
121
|
+
const known = released[rel.split(path.sep).join('/')] ?? [];
|
|
122
|
+
if (current === fingerprint(incoming)) plan.push({ rel, action: 'current' });
|
|
123
|
+
else if (known.includes(current)) plan.push({ rel, action: 'update', incoming });
|
|
124
|
+
else if (force) plan.push({ rel, action: 'overwrite', incoming });
|
|
125
|
+
else plan.push({ rel, action: 'modified' });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const labels = {
|
|
129
|
+
create: dryRun ? 'would create' : 'create',
|
|
130
|
+
update: dryRun ? 'would update' : 'update',
|
|
131
|
+
overwrite: dryRun ? 'would overwrite' : 'overwrite',
|
|
132
|
+
};
|
|
133
|
+
for (const { rel, action, incoming } of plan) {
|
|
134
|
+
if (action === 'current') continue;
|
|
135
|
+
if (action === 'modified') {
|
|
136
|
+
log(`skip ${rel} (modified locally)`);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (!dryRun) {
|
|
140
|
+
const destination = path.join(root, rel);
|
|
141
|
+
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
142
|
+
fs.writeFileSync(destination, incoming);
|
|
143
|
+
}
|
|
144
|
+
log(`${labels[action]} ${rel}${action === 'overwrite' ? ' (local changes discarded)' : ''}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const count = (...actions) => plan.filter((item) => actions.includes(item.action)).length;
|
|
148
|
+
const modified = plan.filter((item) => item.action === 'modified').map((item) => item.rel);
|
|
149
|
+
log(`${dryRun ? 'Preview:' : 'Updated:'} ${count('update', 'overwrite')} ${dryRun ? 'to update' : 'updated'}, ${count('create')} ${dryRun ? 'to create' : 'created'}, ${count('current')} already current, ${modified.length} skipped.`);
|
|
150
|
+
if (modified.length) {
|
|
151
|
+
log('Skipped files differ from every released version, so they were left alone.');
|
|
152
|
+
log(`Compare them with the new versions in ${bundledScaffold} and merge by hand, or rerun with --force to overwrite them.`);
|
|
153
|
+
}
|
|
154
|
+
return { plan: plan.map(({ rel, action }) => ({ rel, action })), modified };
|
|
155
|
+
}
|
|
156
|
+
|
|
87
157
|
export function slugify(value) {
|
|
88
158
|
const slug = value.normalize('NFKD').replace(/[\u0300-\u036f]/g, '')
|
|
89
159
|
.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scaffold-agent-specs",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "A tiny, spec-driven workflow scaffold for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,7 +18,10 @@
|
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"test": "node --test",
|
|
21
|
-
"pack:check": "npm pack --dry-run"
|
|
21
|
+
"pack:check": "npm pack --dry-run",
|
|
22
|
+
"format": "npx --yes prettier@3 --write \"scaffold/**/*.md\"",
|
|
23
|
+
"format:check": "npx --yes prettier@3 --check \"scaffold/**/*.md\"",
|
|
24
|
+
"fingerprints": "node scripts/record-fingerprints.js"
|
|
22
25
|
},
|
|
23
26
|
"keywords": [
|
|
24
27
|
"agents",
|
|
@@ -28,5 +31,13 @@
|
|
|
28
31
|
"claude-code",
|
|
29
32
|
"codex"
|
|
30
33
|
],
|
|
31
|
-
"author": "rob-pasc"
|
|
34
|
+
"author": "rob-pasc",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/rob-pasc/scaffold-agent-specs.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/rob-pasc/scaffold-agent-specs#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/rob-pasc/scaffold-agent-specs/issues"
|
|
42
|
+
}
|
|
32
43
|
}
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
## Decision
|
|
15
15
|
|
|
16
|
-
[State the decision
|
|
16
|
+
[State the decision _actually adopted_, its boundaries, and the principal rationale.]
|
|
17
17
|
|
|
18
18
|
## Alternatives considered
|
|
19
19
|
|
|
20
|
-
| Alternative | Benefits
|
|
21
|
-
|
|
|
22
|
-
| [Option A]
|
|
23
|
-
| [Option B]
|
|
20
|
+
| Alternative | Benefits | Why not chosen |
|
|
21
|
+
| ----------- | ---------- | -------------- |
|
|
22
|
+
| [Option A] | [Benefits] | [Tradeoffs] |
|
|
23
|
+
| [Option B] | [Benefits] | [Tradeoffs] |
|
|
24
24
|
|
|
25
25
|
## Consequences
|
|
26
26
|
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
Each row must specify **observable behavior**, a verification method, and actual evidence. Write criteria when specifying the feature; update result and evidence during implementation. Do not mark `Pass` based solely on code inspection or optimism.
|
|
7
7
|
|
|
8
|
-
| ID
|
|
9
|
-
|
|
|
10
|
-
| AC-001 | FR-001
|
|
11
|
-
| AC-002 | FR-002
|
|
8
|
+
| ID | Requirement | Scenario / expected outcome | Verification method | Result | Evidence |
|
|
9
|
+
| ------ | ----------- | ------------------------------------------------ | ------------------------------- | ------- | ---------------------------- |
|
|
10
|
+
| AC-001 | FR-001 | [Given/when/then or clear expected result] | [Test name or manual procedure] | Not run | [Add evidence when verified] |
|
|
11
|
+
| AC-002 | FR-002 | [Expected result, including important edge case] | [Test name or manual procedure] | Not run | [Add evidence when verified] |
|
|
12
12
|
|
|
13
13
|
## Result legend
|
|
14
14
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
## Alternatives and tradeoffs
|
|
29
29
|
|
|
30
|
-
[Material design options and reasons for preferring the proposed one. Significant project-wide
|
|
30
|
+
[Material design options and reasons for preferring the proposed one. Significant project-wide _adopted_ choices should be recorded later as ADRs.]
|
|
31
31
|
|
|
32
32
|
## Open technical decisions
|
|
33
33
|
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
- **Feature ID:** `feature-NNN-kebab-case`
|
|
4
4
|
- **Scope status:** Approved by user
|
|
5
5
|
- **Scope approval date:** [YYYY-MM-DD]
|
|
6
|
-
- **Implementation status:** Not started
|
|
7
|
-
- **Technical readiness:** To be assessed before implementation
|
|
8
6
|
|
|
9
|
-
> Replace bracketed prompts with specifics from the approved discussion. This file records
|
|
7
|
+
> Replace bracketed prompts with specifics from the approved discussion. This file records _scope and intent_, not a claim that a technical design has been accepted. Track progress in `TASKS.md`, not here.
|
|
10
8
|
|
|
11
9
|
## Summary
|
|
12
10
|
|
|
@@ -35,7 +33,7 @@
|
|
|
35
33
|
|
|
36
34
|
## Non-functional requirements and constraints
|
|
37
35
|
|
|
38
|
-
[Performance, accessibility, security, privacy, compatibility, operational or design constraints
|
|
36
|
+
[Performance, accessibility, security, privacy, compatibility, operational or design constraints _actually relevant_ to this feature. State 'None identified' if appropriate.]
|
|
39
37
|
|
|
40
38
|
## User journeys and edge cases
|
|
41
39
|
|
|
@@ -55,8 +53,8 @@
|
|
|
55
53
|
|
|
56
54
|
## Scope change log
|
|
57
55
|
|
|
58
|
-
| Date
|
|
59
|
-
|
|
|
56
|
+
| Date | Change | User approval |
|
|
57
|
+
| ------------ | ---------------------- | -------------------------------------------- |
|
|
60
58
|
| [YYYY-MM-DD] | Initial approved scope | [Explicit approval reference / conversation] |
|
|
61
59
|
|
|
62
60
|
## References
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
|
|
16
16
|
## Alternatives evaluated
|
|
17
17
|
|
|
18
|
-
| Option
|
|
19
|
-
|
|
|
20
|
-
| [Option A] | [Evidence]
|
|
18
|
+
| Option | Evidence / strengths | Limitations / risks |
|
|
19
|
+
| ---------- | -------------------- | ------------------- |
|
|
20
|
+
| [Option A] | [Evidence] | [Risks] |
|
|
21
21
|
|
|
22
22
|
## Recommendation and confidence
|
|
23
23
|
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
# Implementation Tasks: [Feature title]
|
|
2
2
|
|
|
3
3
|
- **Feature ID:** `feature-NNN-kebab-case`
|
|
4
|
-
- **Status:**
|
|
4
|
+
- **Status:** Specified
|
|
5
5
|
|
|
6
6
|
This is the **authoritative progress checklist**. Draft ordered, independently verifiable tasks after scope approval. Map tasks to acceptance criteria where practical. Check a task only after its work is actually complete.
|
|
7
7
|
|
|
8
|
+
`Status` above is the feature's only lifecycle status. Use one of:
|
|
9
|
+
|
|
10
|
+
- `Specified`: specs written; readiness not yet checked.
|
|
11
|
+
- `Ready`: readiness checked before implementation; remaining blockers are listed below.
|
|
12
|
+
- `In progress`: implementation underway.
|
|
13
|
+
- `Implemented (verification pending)`: tasks done, but some acceptance criteria are not yet `Pass`.
|
|
14
|
+
- `Complete`: every acceptance criterion is `Pass`, or the user has explicitly accepted the exceptions.
|
|
15
|
+
|
|
8
16
|
## Tasks
|
|
9
17
|
|
|
10
18
|
- [ ] **T-001:** [First actionable implementation step] (supports `AC-001`)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Architecture Overview
|
|
2
2
|
|
|
3
|
-
> **Optional project document.** Create under `docs/ARCHITECTURE.md` when the system is complex enough to benefit from a maintained overview. Describe the
|
|
3
|
+
> **Optional project document.** Create under `docs/ARCHITECTURE.md` when the system is complex enough to benefit from a maintained overview. Describe the _current implemented system_, not hypothetical future architecture. Refer to ADRs for the reasons behind lasting choices.
|
|
4
4
|
|
|
5
5
|
## System at a glance
|
|
6
6
|
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
## Components and responsibilities
|
|
10
10
|
|
|
11
|
-
| Component
|
|
12
|
-
|
|
|
13
|
-
| [Component] | [Responsibility] | [Dependencies]
|
|
11
|
+
| Component | Responsibility | Key dependencies |
|
|
12
|
+
| ----------- | ---------------- | ---------------- |
|
|
13
|
+
| [Component] | [Responsibility] | [Dependencies] |
|
|
14
14
|
|
|
15
15
|
## Important data and request flows
|
|
16
16
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
> **Optional project document.** Create under `docs/GLOSSARY.md` when the domain has terms whose precise meaning matters across features. Prefer a short, authoritative definition over repeated explanations in feature plans.
|
|
4
4
|
|
|
5
|
-
| Term
|
|
6
|
-
|
|
|
7
|
-
| [Domain term] | [Precise definition]
|
|
5
|
+
| Term | Meaning in this project | Notes / related terms |
|
|
6
|
+
| ------------- | ----------------------- | ----------------------------------------- |
|
|
7
|
+
| [Domain term] | [Precise definition] | [Distinctions, links, examples if useful] |
|
|
8
8
|
|
|
9
9
|
## Usage notes (if needed)
|
|
10
10
|
|
package/scaffold/AGENTS.md
CHANGED
|
@@ -18,7 +18,7 @@ For **new features**, follow this sequence:
|
|
|
18
18
|
1. **Discover:** Discuss the idea with the user. Understand the problem, users, expected behavior, constraints, boundaries, and unresolved questions. Do not implement the feature or create its feature directory during discovery.
|
|
19
19
|
2. **Propose:** Present a concise scope summary covering the goal, in-scope and out-of-scope behavior, important acceptance outcomes, assumptions, and consequential open questions. Explicitly offer **accept / revise / discard**.
|
|
20
20
|
3. **Get approval:** Treat only a clear, affirmative user response as scope approval. If the user revises the proposal, summarize the revised scope and seek approval again. If discarded, do not create feature artifacts.
|
|
21
|
-
4. **Specify:** After approval, create `docs/features/feature-NNN-kebab-case/` and populate `PLAN.md`, `ACCEPTANCE_MATRIX.md`, and `TASKS.md` from `.agent-specs/templates/feature
|
|
21
|
+
4. **Specify:** After approval, create `docs/features/feature-NNN-kebab-case/` and populate `PLAN.md`, `ACCEPTANCE_MATRIX.md`, and `TASKS.md` from `.agent-specs/templates/feature/`, following the steps in [`docs/WORKFLOW.md`](docs/WORKFLOW.md) (Phase 3). Add `DESIGN.md` for substantial UX/technical design and `RESEARCH.md` for findings worth preserving, only when needed. Create `HANDOFF.md` when a real session handoff is useful. Record the approved scope faithfully. Mark proposed technical choices as proposed, not approved.
|
|
22
22
|
5. **Stop at the spec boundary:** After writing the feature documents, summarize what was created and stop. **Do not start implementation** until the user explicitly requests it, possibly in a later session.
|
|
23
23
|
6. **Implement and verify:** On an explicit implementation request, review the feature documents and relevant code. Resolve blockers, surface consequential technical choices, then execute tasks, validate acceptance criteria, and keep the documents current.
|
|
24
24
|
7. **Finish:** Update related documentation, capture architectural decisions actually adopted, report verification evidence and remaining limitations, and mark the feature complete only when acceptance criteria are satisfied or exceptions explicitly accepted by the user.
|
|
@@ -28,14 +28,14 @@ Existing-feature work and ordinary fixes should follow the user's requested scop
|
|
|
28
28
|
### Scope changes and technical decisions
|
|
29
29
|
|
|
30
30
|
- An approved feature scope is the baseline. Ask for renewed approval before materially changing promised behavior, exclusions, or acceptance criteria.
|
|
31
|
-
- Technical implementation details can evolve within that scope. Surface decisions that introduce major dependencies, migrations, security implications, substantial complexity, or broad architectural consequences before committing to them.
|
|
31
|
+
- Technical implementation details can evolve within that scope. Surface decisions that introduce major dependencies, migrations that modify or delete existing data, security implications, substantial complexity, or broad architectural consequences before committing to them.
|
|
32
32
|
- Keep proposed decisions in the feature `PLAN.md`. Add a project-wide ADR **when a significant architectural decision has actually been adopted**, typically after implementation. For consequential decisions adopted earlier, record the ADR at adoption rather than losing the rationale. Never turn an unimplemented proposal into an accepted ADR.
|
|
33
33
|
|
|
34
34
|
## Feature documentation contracts
|
|
35
35
|
|
|
36
|
-
- **`PLAN.md`** explains
|
|
36
|
+
- **`PLAN.md`** explains _why and what_, including approved scope, requirements, constraints, risks, and the proposed technical direction.
|
|
37
37
|
- **`ACCEPTANCE_MATRIX.md`** defines objectively verifiable outcomes and records methods, results, and evidence. Do not claim a pass without evidence.
|
|
38
|
-
- **`TASKS.md`** is the authoritative checklist for implementation progress. Keep items small and link them to acceptance IDs where practical.
|
|
38
|
+
- **`TASKS.md`** is the authoritative checklist for implementation progress and holds the feature's lifecycle status. Keep items small and link them to acceptance IDs where practical.
|
|
39
39
|
- **`DESIGN.md`** is optional detailed technical/interaction design, not a second feature specification.
|
|
40
40
|
- **`RESEARCH.md`** is optional durable investigative findings, not an approved decision.
|
|
41
41
|
- **`HANDOFF.md`** is optional, temporary context for a session or agent transition. It must never supersede the plan, acceptance matrix, or task checklist.
|
|
@@ -50,16 +50,22 @@ Existing-feature work and ordinary fixes should follow the user's requested scop
|
|
|
50
50
|
- Do not write speculative ADRs during feature discovery or initial specification. Capture proposed approaches and uncertainties in `PLAN.md` instead.
|
|
51
51
|
- Keep docs concise and accurate; remove stale claims rather than merely appending new text.
|
|
52
52
|
- Practice **progressive documentation**: create an optional document only to solve a concrete problem. Prefer updating an existing source of truth over producing redundant or empty files.
|
|
53
|
-
- If maintained, keep `docs/ARCHITECTURE.md` aligned with the
|
|
53
|
+
- If maintained, keep `docs/ARCHITECTURE.md` aligned with the _implemented_ system, `docs/GLOSSARY.md` aligned with shared domain language, and `docs/conventions/` aligned with stable project-specific practices. Create them only when useful, from `.agent-specs/templates/project/` or `.agent-specs/templates/conventions/`. An adopted architecture decision still belongs in an ADR.
|
|
54
54
|
|
|
55
55
|
## Verification and completion
|
|
56
56
|
|
|
57
57
|
- Before claiming completion, run relevant tests, linters, type checks, and build checks supported by the repository, or explain precisely why they were not run.
|
|
58
58
|
- Update acceptance results with concrete evidence (test name, command, output summary, or a reproducible manual check). Never infer a pass from implementation alone.
|
|
59
|
-
- Keep `TASKS.md` synchronized with actual progress. Do not mark blocked or incomplete work as done.
|
|
59
|
+
- Keep `TASKS.md` synchronized with actual progress, including its status, which is the single lifecycle status for the feature. Do not mark blocked or incomplete work as done.
|
|
60
60
|
- Call out unresolved failures, missing coverage, migrations, and follow-up work explicitly.
|
|
61
61
|
|
|
62
|
-
## Git
|
|
62
|
+
## Git commits
|
|
63
|
+
|
|
64
|
+
Commit your work as you go, without waiting to be asked. Commit approved feature specs on their own. During implementation, commit at **milestones**: points you would want to return to. A milestone passes the relevant checks and has one theme you can describe in a sentence, such as the domain logic for a feature with its tests, or the UI built on top of it. A feature typically takes a few commits; neither one per task nor one per feature. Also commit before risky steps (large refactors, migrations, dependency changes) and before ending a session. Split a commit that would mix unrelated concerns.
|
|
65
|
+
|
|
66
|
+
- Run the relevant checks before committing. If you commit while something is failing or incomplete, say so in the message.
|
|
67
|
+
- Don't commit secrets, credentials, local environment files, or build output that the repository doesn't already track.
|
|
68
|
+
- Don't push, rewrite or amend existing history, or change branches without the user's request.
|
|
63
69
|
|
|
64
70
|
Use **Conventional Commit-style** subjects with a meaningful scope:
|
|
65
71
|
|
|
@@ -74,7 +80,6 @@ Use **Conventional Commit-style** subjects with a meaningful scope:
|
|
|
74
80
|
- Use a lowercase type and a short, recognizable scope (app, package, or subsystem). Write an imperative, descriptive subject; aim to stay within 72 characters.
|
|
75
81
|
- For nontrivial changes, write a **prose body** explaining the substance and rationale, not a dump of filenames or generic boilerplate. Separate the subject and body with a blank line, and wrap prose at roughly 72–80 columns.
|
|
76
82
|
- Keep commits focused and truthful. Note breaking changes explicitly when applicable.
|
|
77
|
-
- Do not create a commit unless the user requests it or has explicitly authorized committing as part of the current task.
|
|
78
83
|
|
|
79
84
|
Example:
|
|
80
85
|
|
|
@@ -29,16 +29,26 @@ Ask the user to **accept, revise, or discard**.
|
|
|
29
29
|
|
|
30
30
|
## Phase 3: Specify (after accepted scope)
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Create the feature directory by hand:
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
1. **Number:** find the highest `NNN` among the existing `docs/features/feature-NNN-*` directories and add one (start at `001`). Never reuse a number.
|
|
35
|
+
2. **Name:** `docs/features/feature-NNN-kebab-case/`, where `kebab-case` is a short slug of the feature title (for example `feature-007-user-statistics-page`).
|
|
36
|
+
3. **Copy:** `PLAN.md`, `ACCEPTANCE_MATRIX.md`, and `TASKS.md` from `.agent-specs/templates/feature/`, plus any optional templates needed (see the table below).
|
|
37
|
+
4. **Fill identifiers:** in every copied file, replace `feature-NNN-kebab-case` with the directory name, the `NNN` in `Feature NNN:` with the number, `[Feature title]` with the title, and `[YYYY-MM-DD]` with today's date.
|
|
38
|
+
5. **Fill content:** replace every remaining bracketed prompt, such as `[First actionable implementation step]`, with content from the approved discussion, and delete template guidance that doesn't apply. No prompts may remain.
|
|
39
|
+
|
|
40
|
+
(The `scaffold-agent-specs feature` command performs steps 1–4 for people who prefer it; agents don't need it.)
|
|
41
|
+
|
|
42
|
+
Required and optional documents:
|
|
43
|
+
|
|
44
|
+
| File | Purpose | Required? |
|
|
45
|
+
| ---------------------- | ------------------------------------------------------------------------------ | -------------- |
|
|
46
|
+
| `PLAN.md` | Approved product scope, requirements, constraints, proposed technical approach | Yes |
|
|
47
|
+
| `ACCEPTANCE_MATRIX.md` | Testable criteria plus verification methods, results, and evidence | Yes |
|
|
48
|
+
| `TASKS.md` | Ordered, actionable implementation checklist, mapped to criteria | Yes |
|
|
49
|
+
| `DESIGN.md` | Detailed technical/UX design when complexity warrants it | Optional |
|
|
50
|
+
| `RESEARCH.md` | Durable findings from meaningful investigation | Optional |
|
|
51
|
+
| `HANDOFF.md` | Short-lived context for work that will resume elsewhere | Only if useful |
|
|
42
52
|
|
|
43
53
|
Write the approved scope into `PLAN.md`. Draft acceptance criteria and tasks that correspond to that scope. Cross-reference IDs where practical. Put unresolved technical questions in the plan, rather than inventing answers. Add `DESIGN.md` only for substantial design detail, and `RESEARCH.md` only when research findings are worth retaining. Do not write an ADR for an unimplemented option.
|
|
44
54
|
|
|
@@ -47,8 +57,8 @@ Write the approved scope into `PLAN.md`. Draft acceptance criteria and tasks tha
|
|
|
47
57
|
## Phase 4: Implement (separate explicit request)
|
|
48
58
|
|
|
49
59
|
- Re-read the active feature's plan, acceptance matrix, and tasks, plus any optional design/research documents; inspect relevant code and applicable `docs/conventions/` documentation.
|
|
50
|
-
- Check readiness: requirements coherent, blockers identified, implementation direction sensible, verification approach practical.
|
|
51
|
-
- Seek human input before significant new dependencies, migrations, security-sensitive choices, or changes to approved behavior. Technical refinement that stays within scope usually needs no additional approval.
|
|
60
|
+
- Check readiness: requirements coherent, blockers identified, implementation direction sensible, verification approach practical. Record any blockers under "Dependencies and blockers" in `TASKS.md`, then set its status to `Ready`, and to `In progress` once work starts.
|
|
61
|
+
- Seek human input before significant new dependencies, migrations that modify or delete existing data, security-sensitive choices, or changes to approved behavior. Purely additive migrations (for example, a new table or store that leaves existing data untouched) need no prior approval, but record them in the plan and report them. Technical refinement that stays within scope usually needs no additional approval.
|
|
52
62
|
- Work through `TASKS.md`, updating checked items to reflect reality. Keep plan notes synchronized when implementation choices change.
|
|
53
63
|
- Add or update tests and record concrete results in `ACCEPTANCE_MATRIX.md`.
|
|
54
64
|
- If interrupted, add or refresh `HANDOFF.md` with the current task, blockers, commands run, and the next actionable step.
|
|
@@ -60,16 +70,17 @@ Write the approved scope into `PLAN.md`. Draft acceptance criteria and tasks tha
|
|
|
60
70
|
- Update affected user/developer/project documentation in the same change. Maintain `docs/ARCHITECTURE.md`, `docs/GLOSSARY.md`, and `docs/conventions/` when they exist and are affected by the change.
|
|
61
71
|
- Create ADRs for meaningful architectural decisions **actually adopted**. Normally do this after the implementation is known; for a consequential choice adopted earlier, record it at that point.
|
|
62
72
|
- Report what shipped, what was validated, any limitations, and whether the feature is complete. A feature is not complete while required acceptance criteria remain failing, blocked, or unverified.
|
|
73
|
+
- Set the `TASKS.md` status to `Complete` only when that holds; otherwise use `Implemented (verification pending)` and list what remains.
|
|
63
74
|
|
|
64
75
|
## Maintaining the source of truth
|
|
65
76
|
|
|
66
77
|
- `PLAN.md` owns agreed scope, not task completion.
|
|
67
78
|
- `ACCEPTANCE_MATRIX.md` owns acceptance and verification evidence, not general project notes.
|
|
68
|
-
- `TASKS.md` owns implementation progress, not architectural rationale.
|
|
79
|
+
- `TASKS.md` owns implementation progress and the feature's lifecycle status, not architectural rationale.
|
|
69
80
|
- `DESIGN.md`, if present, owns detailed technical and UX design, not user-approved scope.
|
|
70
81
|
- `RESEARCH.md`, if present, preserves meaningful investigation and uncertainty, not decisions.
|
|
71
82
|
- `HANDOFF.md`, if present, is a snapshot for resumption and may be deleted once unnecessary.
|
|
72
|
-
- ADRs document
|
|
83
|
+
- ADRs document _adopted_, broadly relevant architecture decisions; feature plans retain proposals and feature-local tradeoffs.
|
|
73
84
|
- `docs/ARCHITECTURE.md` describes the implemented system; `docs/GLOSSARY.md` defines shared domain terminology; `docs/conventions/` records reusable project practices. Create these documents only when they provide value. Templates are under `.agent-specs/templates/`.
|
|
74
85
|
|
|
75
86
|
Approved scope changes must be brought back to the user before being incorporated as commitments. Keep artifacts understandable to someone resuming the project without the original chat history. **Progressive documentation:** do not create an optional document just because a template exists; prefer updating a single authoritative source over duplicating content.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Create a directory here **only after the user explicitly accepts the feature scope**. Do not create speculative feature directories during discovery.
|
|
4
4
|
|
|
5
|
-
After approval,
|
|
5
|
+
After approval, agents create the directory by copying the templates, following the steps in [`docs/WORKFLOW.md`](../WORKFLOW.md) (Phase 3), then fill all required documents from the accepted discussion. People can use `npx scaffold-agent-specs feature "Feature title" --approved` instead; it only creates the templated files and fills in identifiers, titles, and dates.
|
|
6
6
|
|
|
7
7
|
Each feature is named `feature-NNN-kebab-case`, for example `feature-007-user-statistics-page`. Start at `001` and choose the next number above the highest existing feature ID; do not reuse numbers.
|
|
8
8
|
|