gspec 1.16.0 → 1.17.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.
Files changed (34) hide show
  1. package/README.md +33 -6
  2. package/bin/gspec.js +214 -33
  3. package/commands/gspec.analyze.md +9 -0
  4. package/commands/gspec.audit.md +84 -9
  5. package/commands/gspec.feature.md +10 -0
  6. package/commands/gspec.implement.md +19 -8
  7. package/commands/gspec.tasks.md +150 -0
  8. package/dist/antigravity/gspec-analyze/SKILL.md +9 -0
  9. package/dist/antigravity/gspec-audit/SKILL.md +85 -10
  10. package/dist/antigravity/gspec-feature/SKILL.md +10 -0
  11. package/dist/antigravity/gspec-implement/SKILL.md +19 -8
  12. package/dist/antigravity/gspec-tasks/SKILL.md +154 -0
  13. package/dist/claude/gspec-analyze/SKILL.md +9 -0
  14. package/dist/claude/gspec-audit/SKILL.md +85 -10
  15. package/dist/claude/gspec-feature/SKILL.md +10 -0
  16. package/dist/claude/gspec-implement/SKILL.md +19 -8
  17. package/dist/claude/gspec-tasks/SKILL.md +155 -0
  18. package/dist/codex/gspec-analyze/SKILL.md +9 -0
  19. package/dist/codex/gspec-audit/SKILL.md +85 -10
  20. package/dist/codex/gspec-feature/SKILL.md +10 -0
  21. package/dist/codex/gspec-implement/SKILL.md +19 -8
  22. package/dist/codex/gspec-tasks/SKILL.md +154 -0
  23. package/dist/cursor/gspec-analyze.mdc +9 -0
  24. package/dist/cursor/gspec-audit.mdc +85 -10
  25. package/dist/cursor/gspec-feature.mdc +10 -0
  26. package/dist/cursor/gspec-implement.mdc +19 -8
  27. package/dist/cursor/gspec-tasks.mdc +153 -0
  28. package/dist/opencode/gspec-analyze/SKILL.md +9 -0
  29. package/dist/opencode/gspec-audit/SKILL.md +85 -10
  30. package/dist/opencode/gspec-feature/SKILL.md +10 -0
  31. package/dist/opencode/gspec-implement/SKILL.md +19 -8
  32. package/dist/opencode/gspec-tasks/SKILL.md +154 -0
  33. package/package.json +1 -1
  34. package/templates/spec-sync.md +2 -1
package/README.md CHANGED
@@ -25,7 +25,7 @@ These documents become the shared context for all subsequent AI interactions. Wh
25
25
 
26
26
  The only commands you *need* are the four fundamentals and `/gspec-implement`. Everything else exists to help when your project calls for it.
27
27
 
28
- The fundamentals give your AI tool enough context to build well — it knows what the product is, how it should look, what technologies to use, and what engineering standards to follow. From there, `/gspec-implement` can take a plain-language description and start building. The remaining commands — `/gspec-research`, `/gspec-feature`, `/gspec-architect`, `/gspec-analyze`, and `/gspec-audit` — add structure and rigor when the scope or complexity warrants it.
28
+ The fundamentals give your AI tool enough context to build well — it knows what the product is, how it should look, what technologies to use, and what engineering standards to follow. From there, `/gspec-implement` can take a plain-language description and start building. The remaining commands — `/gspec-research`, `/gspec-feature`, `/gspec-architect`, `/gspec-tasks`, `/gspec-analyze`, and `/gspec-audit` — add structure and rigor when the scope or complexity warrants it.
29
29
 
30
30
  ```mermaid
31
31
  flowchart LR
@@ -42,11 +42,14 @@ flowchart LR
42
42
  Architect["4. Architect
43
43
  technical blueprint"]
44
44
 
45
- Analyze["5. Analyze & Audit
45
+ Plan["5. Plan
46
+ ordered tasks"]
47
+
48
+ Analyze["6. Analyze & Audit
46
49
  reconcile specs
47
50
  check specs vs code"]
48
51
 
49
- Build["6. Build
52
+ Build["7. Build
50
53
  implement"]
51
54
 
52
55
  Define --> Research
@@ -55,9 +58,12 @@ flowchart LR
55
58
  Research --> Specify
56
59
  Research --> Build
57
60
  Specify --> Architect
61
+ Specify --> Plan
58
62
  Specify --> Build
63
+ Architect --> Plan
59
64
  Architect --> Analyze
60
65
  Architect --> Build
66
+ Plan --> Build
61
67
  Analyze --> Build
62
68
  Build --> Define
63
69
 
@@ -65,6 +71,7 @@ flowchart LR
65
71
  style Research fill:#a855f7,color:#fff,stroke:none
66
72
  style Specify fill:#f59e0b,color:#fff,stroke:none
67
73
  style Architect fill:#f59e0b,color:#fff,stroke:none
74
+ style Plan fill:#f59e0b,color:#fff,stroke:none
68
75
  style Analyze fill:#f59e0b,color:#fff,stroke:none
69
76
  style Build fill:#22c55e,color:#fff,stroke:none
70
77
  ```
@@ -105,7 +112,15 @@ Use `/gspec-feature` when you want detailed PRDs with prioritized capabilities a
105
112
 
106
113
  Use `/gspec-architect` when your feature involves significant technical complexity — new data models, service boundaries, auth flows, or integration points that benefit from upfront design. It also **identifies technical gaps and ambiguities** in your specs and proposes solutions, so that `/gspec-implement` can focus on building rather than making architectural decisions. For straightforward features, `/gspec-implement` can make sound architectural decisions on its own using your `stack` and `practices` specs.
107
114
 
108
- **5. Analyze & Audit** *(optional)* — Reconcile discrepancies before building, and keep specs honest as the codebase evolves.
115
+ **5. Plan** *(optional)* — Decompose a feature PRD into ordered work.
116
+
117
+ | Command | Role | What it produces |
118
+ |---|---|---|
119
+ | `/gspec-tasks` | Engineering Lead | A sibling `gspec/features/<feature>.tasks.md` file with stable task IDs, explicit `deps:` lines, and `[P]` markers for parallel-safe work |
120
+
121
+ Use `/gspec-tasks` after `/gspec-feature` (and after `/gspec-architect` when it exists) for any feature large enough that build order matters or that has work which could legitimately run in parallel. The output is what `/gspec-implement` consumes — when a tasks file exists for an in-scope feature, implement plans phases from it, respecting deps and surfacing `[P]`-marked tasks for parallel execution. Trivial features can skip this step and go straight to `/gspec-implement`, which falls back to PRD-checkbox-driven planning.
122
+
123
+ **6. Analyze & Audit** *(optional)* — Reconcile discrepancies before building, and keep specs honest as the codebase evolves.
109
124
 
110
125
  | Command | Role | What it does |
111
126
  |---|---|---|
@@ -116,11 +131,11 @@ Use `/gspec-analyze` after `/gspec-architect` (or any time multiple specs exist)
116
131
 
117
132
  Use `/gspec-audit` periodically — before a major release, after a long sprint, or any time you suspect docs have drifted from code. Audit reads package manifests, configs, source files, and test output, then asks you per-finding whether to update the spec to match the code, keep the spec and fix the code separately, or defer. Each finding is presented one at a time with the spec quote and the code evidence side by side. Audit never modifies code.
118
133
 
119
- **6. Build** — Implement with full context.
134
+ **7. Build** — Implement with full context.
120
135
 
121
136
  | Command | Role | What it does |
122
137
  |---|---|---|
123
- | `/gspec-implement` | Senior Engineer | Reads all specs, plans the build order, and implements |
138
+ | `/gspec-implement` | Senior Engineer | Reads all specs (including any `*.tasks.md` files), plans the build order, and implements |
124
139
 
125
140
  **Spec Sync** — gspec includes always-on spec sync that automatically keeps your specification documents in sync as the code evolves. This is installed alongside the skills and requires no manual intervention — when code changes affect spec-documented behavior, the sync rules prompt your AI tool to update the relevant gspec files.
126
141
 
@@ -182,6 +197,18 @@ Saved specs are organized by type in `~/.gspec/` (profiles, stacks, styles, prac
182
197
  gspec restore playbook/my-starter
183
198
  ```
184
199
 
200
+ ## Extensions
201
+
202
+ Author your own skills and have them auto-installed alongside the built-in `gspec-*` commands in every project. Extensions live in `~/.gspec/extensions/` as Markdown files with `name` and `description` frontmatter and the same shape as anything in `commands/`.
203
+
204
+ ```bash
205
+ gspec extension save ./my-deploy.md # Install a local skill file as a user extension
206
+ gspec extension list # See what's installed
207
+ gspec extension remove my-deploy # Delete from ~/.gspec/extensions/
208
+ ```
209
+
210
+ When you next run `npx gspec` in a project, the installer copies the built-in skills first, then emits each valid extension into the same per-platform install directory using the same formatting. Extension names that collide with built-in `gspec-*` skills are rejected with an error; malformed or duplicate extensions are skipped with a warning.
211
+
185
212
  ## Output Structure
186
213
 
187
214
  All specifications live in a `gspec/` directory at your project root:
package/bin/gspec.js CHANGED
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { program } from 'commander';
4
- import { readdir, readFile, writeFile, mkdir, stat } from 'node:fs/promises';
4
+ import { readdir, readFile, writeFile, mkdir, stat, unlink } from 'node:fs/promises';
5
5
  import { join, dirname, basename } from 'node:path';
6
6
  import { homedir } from 'node:os';
7
7
  import { fileURLToPath } from 'node:url';
8
8
  import { createInterface } from 'node:readline';
9
9
  import chalk from 'chalk';
10
+ import { TARGETS as EMITTER_TARGETS } from '../scripts/emitters.js';
10
11
 
11
12
  const __dirname = dirname(fileURLToPath(import.meta.url));
12
13
  const DIST_DIR = join(__dirname, '..', 'dist');
@@ -28,38 +29,21 @@ const BANNER = `
28
29
  ${chalk.white('═════════════════════════════baller.software═══')}
29
30
  `;
30
31
 
31
- const TARGETS = {
32
- claude: {
33
- sourceDir: join(DIST_DIR, 'claude'),
34
- installDir: '.claude/skills',
35
- label: 'Claude Code',
36
- layout: 'directory',
37
- },
38
- cursor: {
39
- sourceDir: join(DIST_DIR, 'cursor'),
40
- installDir: '.cursor/commands',
41
- label: 'Cursor',
42
- layout: 'flat',
43
- },
44
- antigravity: {
45
- sourceDir: join(DIST_DIR, 'antigravity'),
46
- installDir: '.agent/skills',
47
- label: 'Antigravity',
48
- layout: 'directory',
49
- },
50
- codex: {
51
- sourceDir: join(DIST_DIR, 'codex'),
52
- installDir: '.agents/skills',
53
- label: 'Codex',
54
- layout: 'directory',
55
- },
56
- opencode: {
57
- sourceDir: join(DIST_DIR, 'opencode'),
58
- installDir: '.opencode/skills',
59
- label: 'Open Code',
60
- layout: 'directory',
61
- },
62
- };
32
+ // Derive install-side TARGETS from the shared emitter config so we have one source of truth.
33
+ // `sourceDir` is computed from the shared `distSubdir`; `emit` is reused for installing user extensions.
34
+ const TARGETS = Object.fromEntries(
35
+ Object.entries(EMITTER_TARGETS).map(([key, t]) => [key, {
36
+ ...t,
37
+ sourceDir: join(DIST_DIR, t.distSubdir),
38
+ }]),
39
+ );
40
+
41
+ // Names emitted by core gspec; user extensions cannot collide with these.
42
+ const BUILTIN_SKILL_NAMES = new Set([
43
+ 'gspec-profile', 'gspec-feature', 'gspec-tasks', 'gspec-style',
44
+ 'gspec-stack', 'gspec-practices', 'gspec-architect', 'gspec-analyze',
45
+ 'gspec-audit', 'gspec-research', 'gspec-implement', 'gspec-migrate',
46
+ ]);
63
47
 
64
48
  const TARGET_CHOICES = [
65
49
  { key: '1', name: 'claude', label: 'Claude Code' },
@@ -1397,6 +1381,8 @@ program
1397
1381
 
1398
1382
  await install(targetName, process.cwd());
1399
1383
 
1384
+ await installExtensions(targetName, process.cwd());
1385
+
1400
1386
  await seedFromSavedSpecs(process.cwd());
1401
1387
 
1402
1388
  await installSpecSync(targetName, process.cwd());
@@ -1424,6 +1410,176 @@ program
1424
1410
  }
1425
1411
  });
1426
1412
 
1413
+ // --- Extensions ---
1414
+
1415
+ const EXTENSIONS_DIR = join(GSPEC_HOME, 'extensions');
1416
+ const EXTENSION_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
1417
+
1418
+ async function loadExtensions() {
1419
+ let entries;
1420
+ try {
1421
+ entries = await readdir(EXTENSIONS_DIR);
1422
+ } catch (e) {
1423
+ if (e.code === 'ENOENT') return [];
1424
+ throw e;
1425
+ }
1426
+
1427
+ const files = entries.filter((f) => f.endsWith('.md'));
1428
+ const loaded = [];
1429
+ for (const file of files) {
1430
+ const path = join(EXTENSIONS_DIR, file);
1431
+ const content = await readFile(path, 'utf-8');
1432
+ const { fields, body } = parseFrontmatter(content);
1433
+ loaded.push({ file, path, fields, body, content });
1434
+ }
1435
+ return loaded;
1436
+ }
1437
+
1438
+ function validateExtension(ext) {
1439
+ const errors = [];
1440
+ if (!ext.fields.name) errors.push("missing 'name' frontmatter");
1441
+ if (!ext.fields.description) errors.push("missing 'description' frontmatter");
1442
+ if (ext.fields.name && !EXTENSION_NAME_RE.test(ext.fields.name)) {
1443
+ errors.push(`invalid name "${ext.fields.name}" (must match /^[a-z0-9][a-z0-9-]*$/)`);
1444
+ }
1445
+ if (ext.fields.name && BUILTIN_SKILL_NAMES.has(ext.fields.name)) {
1446
+ errors.push(`name "${ext.fields.name}" collides with a built-in gspec skill`);
1447
+ }
1448
+ return errors;
1449
+ }
1450
+
1451
+ async function installExtensions(targetName, cwd) {
1452
+ const extensions = await loadExtensions();
1453
+ if (extensions.length === 0) return;
1454
+
1455
+ const target = TARGETS[targetName];
1456
+ const valid = [];
1457
+ for (const ext of extensions) {
1458
+ const errors = validateExtension(ext);
1459
+ if (errors.length > 0) {
1460
+ console.warn(chalk.yellow(` ! Skipping extension ${ext.file}: ${errors.join('; ')}`));
1461
+ continue;
1462
+ }
1463
+ valid.push(ext);
1464
+ }
1465
+
1466
+ // Resolve duplicates by name (last write wins, with a warning)
1467
+ const byName = new Map();
1468
+ for (const ext of valid) {
1469
+ if (byName.has(ext.fields.name)) {
1470
+ console.warn(chalk.yellow(
1471
+ ` ! Extension name "${ext.fields.name}" defined in two files; ${ext.file} overrides ${byName.get(ext.fields.name).file}`
1472
+ ));
1473
+ }
1474
+ byName.set(ext.fields.name, ext);
1475
+ }
1476
+ const finalSet = Array.from(byName.values());
1477
+ if (finalSet.length === 0) return;
1478
+
1479
+ console.log(chalk.bold(`\nInstalling ${finalSet.length} user extension${finalSet.length === 1 ? '' : 's'} from ~/.gspec/extensions/...\n`));
1480
+ const installPath = join(cwd, target.installDir);
1481
+ for (const ext of finalSet) {
1482
+ const meta = { name: ext.fields.name, description: ext.fields.description };
1483
+ await target.emit(installPath, ext.body, meta);
1484
+ console.log(` ${chalk.green('+')} ${ext.fields.name} ${chalk.dim('(extension)')}`);
1485
+ }
1486
+ }
1487
+
1488
+ async function extensionList() {
1489
+ console.log(BANNER);
1490
+ const extensions = await loadExtensions();
1491
+ if (extensions.length === 0) {
1492
+ console.log(chalk.dim('\n No extensions installed in ~/.gspec/extensions/.\n'));
1493
+ console.log(chalk.dim(' Use "gspec extension save <path>" to install one.\n'));
1494
+ return;
1495
+ }
1496
+
1497
+ console.log(chalk.bold(`\n ${extensions.length} extension${extensions.length === 1 ? '' : 's'} in ~/.gspec/extensions/:\n`));
1498
+ for (const ext of extensions) {
1499
+ const errors = validateExtension(ext);
1500
+ const name = ext.fields.name || chalk.dim('(no name)');
1501
+ const desc = ext.fields.description ? chalk.dim(` — ${ext.fields.description}`) : '';
1502
+ if (errors.length > 0) {
1503
+ console.log(` ${chalk.yellow('!')} ${ext.file} → ${name}${desc}`);
1504
+ console.log(` ${chalk.yellow(errors.join('; '))}`);
1505
+ } else {
1506
+ console.log(` ${chalk.green('•')} ${name}${desc}`);
1507
+ console.log(` ${chalk.dim(ext.file)}`);
1508
+ }
1509
+ }
1510
+ console.log();
1511
+ }
1512
+
1513
+ async function extensionSave(srcPath) {
1514
+ console.log(BANNER);
1515
+
1516
+ if (!srcPath) {
1517
+ console.error(chalk.red('\n Usage: gspec extension save <path-to-extension.md>\n'));
1518
+ process.exit(1);
1519
+ }
1520
+
1521
+ let content;
1522
+ try {
1523
+ content = await readFile(srcPath, 'utf-8');
1524
+ } catch (e) {
1525
+ if (e.code === 'ENOENT') {
1526
+ console.error(chalk.red(`\n File not found: ${srcPath}\n`));
1527
+ process.exit(1);
1528
+ }
1529
+ throw e;
1530
+ }
1531
+
1532
+ const { fields } = parseFrontmatter(content);
1533
+ const ext = { file: basename(srcPath), fields };
1534
+ const errors = validateExtension(ext);
1535
+ if (errors.length > 0) {
1536
+ console.error(chalk.red(`\n Cannot save extension: ${errors.join('; ')}\n`));
1537
+ process.exit(1);
1538
+ }
1539
+
1540
+ await mkdir(EXTENSIONS_DIR, { recursive: true });
1541
+ const destPath = join(EXTENSIONS_DIR, `${fields.name}.md`);
1542
+
1543
+ try {
1544
+ await stat(destPath);
1545
+ const overwrite = await promptConfirm(chalk.yellow(`\n Extension "${fields.name}" already exists. Overwrite? [y/N]: `));
1546
+ if (!overwrite) {
1547
+ console.log(chalk.dim('\n Cancelled.\n'));
1548
+ return;
1549
+ }
1550
+ } catch (e) {
1551
+ if (e.code !== 'ENOENT') throw e;
1552
+ }
1553
+
1554
+ await writeFile(destPath, content, 'utf-8');
1555
+ console.log(chalk.green(`\n ✓ Saved extension to ~/.gspec/extensions/${fields.name}.md\n`));
1556
+ console.log(chalk.dim(` It will be installed alongside core skills the next time you run "gspec" in a project.\n`));
1557
+ }
1558
+
1559
+ async function extensionRemove(name) {
1560
+ console.log(BANNER);
1561
+
1562
+ if (!name) {
1563
+ console.error(chalk.red('\n Usage: gspec extension remove <name>\n'));
1564
+ process.exit(1);
1565
+ }
1566
+
1567
+ const path = join(EXTENSIONS_DIR, `${name}.md`);
1568
+ try {
1569
+ await stat(path);
1570
+ } catch (e) {
1571
+ if (e.code === 'ENOENT') {
1572
+ console.error(chalk.red(`\n Extension not found: ~/.gspec/extensions/${name}.md\n`));
1573
+ process.exit(1);
1574
+ }
1575
+ throw e;
1576
+ }
1577
+
1578
+ await unlink(path);
1579
+ console.log(chalk.green(`\n ✓ Removed ~/.gspec/extensions/${name}.md\n`));
1580
+ console.log(chalk.dim(` Already-installed copies in projects (.claude/skills/, .cursor/commands/, etc.) are left in place — delete them manually if desired.\n`));
1581
+ }
1582
+
1427
1583
  program
1428
1584
  .command('save')
1429
1585
  .description('Save a gspec spec to ~/.gspec for reuse across projects')
@@ -1446,4 +1602,29 @@ program
1446
1602
  await createPlaybook();
1447
1603
  });
1448
1604
 
1605
+ const extensionCmd = program
1606
+ .command('extension')
1607
+ .description('Manage user-authored gspec extension skills in ~/.gspec/extensions/');
1608
+
1609
+ extensionCmd
1610
+ .command('list')
1611
+ .description('List installed extensions')
1612
+ .action(async () => {
1613
+ await extensionList();
1614
+ });
1615
+
1616
+ extensionCmd
1617
+ .command('save <path>')
1618
+ .description('Save a local .md skill file as a user extension in ~/.gspec/extensions/')
1619
+ .action(async (path) => {
1620
+ await extensionSave(path);
1621
+ });
1622
+
1623
+ extensionCmd
1624
+ .command('remove <name>')
1625
+ .description('Remove a user extension from ~/.gspec/extensions/ (does not uninstall already-emitted copies)')
1626
+ .action(async (name) => {
1627
+ await extensionRemove(name);
1628
+ });
1629
+
1449
1630
  program.parse();
@@ -31,6 +31,7 @@ Read **every** available gspec document in this order:
31
31
  6. `gspec/architecture.md` — Technical blueprint: project structure, data model, API design, environment
32
32
  7. `gspec/research.md` — Competitive analysis and feature proposals
33
33
  8. `gspec/features/*.md` — Individual feature requirements and dependencies
34
+ 9. `gspec/features/*.tasks.md` — For any feature that has a tasks file, read it alongside the PRD. Tasks files declare a build order and parallelism strategy that must stay consistent with the PRD's capabilities
34
35
 
35
36
  If fewer than two spec files exist, inform the user that there is nothing to cross-reference and stop.
36
37
 
@@ -75,6 +76,14 @@ Systematically compare specs against each other. Look for these categories of di
75
76
  - Acceptance criteria in a feature PRD contradict architectural decisions
76
77
  - Edge cases handled differently across specs
77
78
 
79
+ #### Tasks ↔ PRD Conflicts
80
+ For any feature that has a `gspec/features/<feature>.tasks.md` file, validate the tasks file against its PRD:
81
+ - A task's `covers:` line quotes capability text that does not exist in the PRD (orphan task)
82
+ - A PRD capability is not `covers:`-referenced by any task in the tasks file (orphan capability — every unchecked capability must be covered by at least one task)
83
+ - A task's checkbox is `- [x]` but its covered capability is still `- [ ]` in the PRD, or vice versa (state inconsistency)
84
+ - A task's `deps:` references a task ID that does not exist in the file
85
+ - The tasks file's `feature:` frontmatter slug does not match its filename's feature slug
86
+
78
87
  **Do NOT flag:**
79
88
  - Minor wording or style differences that don't change meaning
80
89
  - Missing information (gaps are for `gspec-architect` to handle)
@@ -12,11 +12,12 @@ You should:
12
12
  - Read and deeply internalize all available gspec documents
13
13
  - Inspect the actual codebase — package manifests, source files, tests, configs, stylesheets, routes, data models, and git history where relevant
14
14
  - Identify concrete drift — not stylistic differences, but substantive mismatches where the spec and the code disagree on a fact, technology, behavior, or requirement
15
+ - Identify **orphan capabilities** — coherent feature-level capabilities the code implements that no feature PRD describes
15
16
  - Present each discrepancy to the user one at a time, clearly showing what each side says
16
17
  - Offer resolution options with a recommendation
17
18
  - Wait for the user's decision before moving to the next discrepancy
18
- - Update the affected spec files to reflect each resolution
19
- - Never modify code as part of this command — audit only updates specs
19
+ - Update the affected spec files to reflect each resolution; for orphan capabilities, draft a new feature PRD in `gspec/features/` when the user accepts
20
+ - Never modify code as part of this command — audit only updates specs and adds new feature PRDs
20
21
 
21
22
  ---
22
23
 
@@ -34,6 +35,7 @@ Read **every** available gspec document in this order:
34
35
  6. `gspec/architecture.md` — Technical blueprint: project structure, data model, API design, environment
35
36
  7. `gspec/research.md` — Competitive analysis and feature proposals (informational only — not audited against code)
36
37
  8. `gspec/features/*.md` — Individual feature requirements, priorities, and capability checkboxes
38
+ 9. `gspec/features/*.tasks.md` — When a feature has a tasks file, also read it. Tasks files declare a per-task execution checkbox state and `covers:` traceability to PRD capabilities; both are subject to drift checks against the code
37
39
 
38
40
  If the `gspec/` directory is empty, inform the user that there are no specs to audit and stop.
39
41
 
@@ -55,6 +57,11 @@ Build a picture of what the code **actually** is. Read the following, as availab
55
57
  - Component library usage — what the UI actually imports and composes
56
58
  - Test files — what framework, what coverage areas
57
59
 
60
+ **Capability mapping**
61
+ - Build a short mental list of the coherent, user-visible capabilities the code implements — not low-level details, but feature-level units (e.g. "users can export data as CSV", "admin can invite team members", "documents have version history"). A capability typically shows up as a cluster: a route + handler + UI surface + test, or an end-to-end flow.
62
+ - For each capability, note whether it appears in any `gspec/features/*.md` PRD (by feature name, capability checkbox, or acceptance criteria). Capabilities with no PRD coverage are candidates for the **Orphan Capability** category in Phase 3.
63
+ - Be deliberately conservative: a utility helper, an internal admin script, or a piece of plumbing is **not** a capability worth a PRD. Only flag things a user (end user, admin, integrator) would recognize as a feature.
64
+
58
65
  **Version control signals** (use sparingly; git log is authoritative only where the spec makes explicit claims about workflow)
59
66
  - `git log --oneline -n 20` for recent commit-message style (only if practices.md makes claims about commit conventions)
60
67
  - `git config --local --get-regexp '^branch\.'` / branch listing for branching strategy (only if practices.md makes claims about branching)
@@ -99,6 +106,22 @@ Systematically compare specs against the evidence from Phase 2. Look for these c
99
106
  - A feature PRD's acceptance criteria describe behavior that the code explicitly handles differently
100
107
  - A feature PRD references a data field, endpoint, or UI element whose implementation has diverged (e.g., PRD says "users can filter by tag", code has filter-by-category)
101
108
 
109
+ #### Tasks Drift (only when a tasks file exists for the feature)
110
+ - A task is marked `- [x]` in the tasks file but the code does not implement what the task describes
111
+ - A task is marked `- [ ]` but the code clearly implements it (the checkbox should be updated)
112
+ - A task's `covers:` references capability text the PRD no longer contains (the PRD was edited but the tasks file wasn't refreshed — recommend regenerating via `/gspec-tasks`)
113
+ - A capability is marked `- [x]` in the PRD but one or more of its covering tasks is still `- [ ]` (or vice versa) — flag the inconsistency and recommend the user reconcile state
114
+
115
+ #### Orphan Capability (code implements a feature that has no PRD)
116
+ - The code ships a coherent, user-visible capability that no `gspec/features/*.md` PRD describes
117
+ - Evidence is typically a cluster — a route + handler + UI surface + test — that adds up to something a user would call a feature
118
+ - An orphan capability is **not** the same as Feature Drift: drift is divergence within a specced feature; an orphan is an entirely unspecced feature
119
+ - Use the **capability mapping** from Phase 2 as your candidate list. Filter out:
120
+ - Internal utilities, admin scripts, dev tooling, or plumbing the user never sees
121
+ - Capabilities that *are* covered by an existing PRD even if checkboxes are stale (those are Feature Drift, not orphans)
122
+ - Capabilities that are partial enough that calling them a "feature" overstates them (note the partial work in the audit summary instead)
123
+ - The recommended resolution is to draft a new feature PRD in `gspec/features/` so the capability is captured, its checkboxes can drive future audits, and `gspec-implement` can extend it correctly
124
+
102
125
  #### Profile Drift (rare; treat conservatively)
103
126
  - The profile's stated audience, scope, or value proposition conflicts with what the product actually does in code (e.g., profile says "B2B only" but the code has a consumer signup flow)
104
127
  - **Profile drift is usually a signal to update the product, not the spec.** Flag profile drift for user discussion rather than recommending an automatic spec update.
@@ -125,7 +148,7 @@ For each discrepancy, present:
125
148
  ```
126
149
  ### Drift [N]: [Brief title]
127
150
 
128
- **Category:** [Stack / Architecture / Style / Practice / Feature / Profile]
151
+ **Category:** [Stack / Architecture / Style / Practice / Feature / Orphan Capability / Profile]
129
152
 
130
153
  **Spec says:**
131
154
  - **[File, section]**: [exact quote or precise summary]
@@ -145,6 +168,33 @@ For each discrepancy, present:
145
168
  Which would you like?
146
169
  ```
147
170
 
171
+ For an **Orphan Capability** finding, the presentation differs slightly — there is no "spec says" side, and the resolution options are different:
172
+
173
+ ```
174
+ ### Drift [N]: Orphan Capability — [Capability name]
175
+
176
+ **Category:** Orphan Capability
177
+
178
+ **Spec says:** *(no PRD covers this capability)*
179
+
180
+ **Code shows:**
181
+ - **Capability:** [one-sentence description in user-facing terms]
182
+ - **Evidence:** [route(s), handler file(s), UI file(s), test file(s) — concrete paths]
183
+ - **Scope estimate:** [trivial / focused single feature / large enough to need decomposition]
184
+
185
+ **Why this matters:** Without a PRD, future audits can't track this capability's completeness, `gspec-implement` won't know how to extend it correctly, and the team has no documented intent to compare against.
186
+
187
+ **Recommended action:** Draft a new feature PRD in `gspec/features/` so the capability is captured.
188
+
189
+ **Options:**
190
+ 1. **Draft a feature PRD now** — Audit will create `gspec/features/<slug>.md` following the gspec-feature schema, marking implemented capabilities as `- [x]` based on the code evidence. *(See Phase 5 for the inline drafting protocol.)*
191
+ 2. **Defer to `/gspec-feature` later** — Audit notes this in the code-follow-up summary so you can run `/gspec-feature` on it as a separate, deeper conversation.
192
+ 3. **Not actually a feature** — The code is internal plumbing or out of scope; audit drops the finding and won't re-flag it (note this back to the user as a hint they may want to add a comment in the code so future audits know).
193
+ 4. **Defer** — Skip for now.
194
+
195
+ Which would you like?
196
+ ```
197
+
148
198
  **Wait for the user's response before proceeding.** The user may:
149
199
  - Choose an option by number
150
200
  - Propose a different resolution (e.g., partially update the spec)
@@ -164,31 +214,56 @@ When updating specs to match the code:
164
214
  - **Do not rewrite sections** — if a one-line change resolves the drift, make a one-line change
165
215
  - **Do not add changelog annotations** — git history captures what changed
166
216
 
217
+ #### Drafting a new feature PRD for an Orphan Capability
218
+
219
+ When the user picks option 1 ("Draft a feature PRD now") for an Orphan Capability finding, audit creates a new file in `gspec/features/`. The drafting follows the **same schema and rules as `gspec-feature`** — do not invent a different format. Specifically:
220
+
221
+ - **Filename:** kebab-case slug derived from the capability name, e.g. `csv-export.md`, `team-invitations.md`. Confirm the slug with the user before writing if it's not obvious.
222
+ - **Frontmatter:** the file must start with
223
+ ```
224
+ ---
225
+ spec-version: <<<SPEC_VERSION>>>
226
+ ---
227
+ ```
228
+ followed by the main heading.
229
+ - **Required sections** (in this order, no extras): Overview, Users & Use Cases, Scope, Capabilities, Dependencies, Assumptions & Risks, Success Metrics, Implementation Context.
230
+ - **Capabilities section is the load-bearing one for audit:** list each user-visible capability the code already implements as a checkbox, and mark it `- [x]` when the code clearly satisfies it. Include 2–4 brief acceptance criteria per capability based on what the code actually does (read tests and handlers to extract these). If a capability is only partially implemented, leave it `- [ ]` and note the gap.
231
+ - **Priority:** assign `P0`/`P1`/`P2` based on the capability's apparent centrality. Lean toward `P0` for capabilities the code clearly treats as core; `P1`/`P2` for ancillary ones.
232
+ - **Technology agnosticism:** the PRD must not name specific frameworks, libraries, databases, or services even though you derived it from concrete code. Use generic terms ("data store", "API", "authentication service"). Refer to `gspec-feature`'s technology-agnostic vocabulary list if needed.
233
+ - **Portability:** do not reference project-specific personas, design system details, or stack choices. Use generic role descriptions ("end users", "administrators").
234
+ - **Resolve ambiguity inline before writing:** if the code's intent is unclear (e.g., is this admin-only or for all users? is this experimental or shipped?), ask the user 1–2 targeted questions in chat *before* writing the file. Do not embed unresolved questions in the PRD.
235
+ - **Implementation Context block:** include the standard verbatim note at the bottom (see `gspec-feature`'s section 8).
236
+ - **Decomposition:** if the orphan capability is actually a *cluster* of distinct features (audit's "Scope estimate" was "large enough to need decomposition"), pause and propose a breakdown to the user before writing — same protocol as `gspec-feature` for multi-feature output. Confirm the breakdown, then write one file per feature.
237
+
238
+ After writing, briefly tell the user what was created (filename + capability list with checkbox states) and continue to the next finding.
239
+
167
240
  ### Phase 6: Final Verification
168
241
 
169
242
  After all discrepancies have been resolved (or deferred):
170
243
 
171
244
  1. **Re-read the updated specs** briefly to confirm the edits landed correctly
172
245
  2. **Present a summary:**
173
- - Total discrepancies found, grouped by category
246
+ - Total discrepancies found, grouped by category (including Orphan Capability)
174
247
  - Number where spec was updated to match code
175
248
  - Number where spec was kept as-is (code flagged for follow-up)
249
+ - Number of new feature PRDs created (with filenames) and capabilities those PRDs cover
176
250
  - Number deferred
177
- - List of files that were updated
251
+ - List of files that were updated or created
178
252
  3. **Flag code follow-ups**: if the user chose "Keep the spec and fix code" for any finding, list those at the end as a punch list so they don't get lost. Do not modify code — this is a reference list for the user or a follow-up implement run.
253
+ 4. **Flag orphan-capability hand-offs**: if the user picked "Defer to `/gspec-feature` later" for any orphan capability, list the capability and the evidence (file paths) so a follow-up `/gspec-feature` run has everything it needs.
179
254
 
180
255
  ---
181
256
 
182
257
  ## Rules
183
258
 
184
259
  - **Never modify code.** This command only reads code and updates specs. If a drift suggests the code should change, list it in the code-follow-up summary and let the user decide whether to run `/gspec-implement` or fix it themselves.
185
- - **Never create new spec files.** Audit only updates existing gspec documents.
186
- - **Never silently update specs.** Every change requires user approval via the drift resolution flow.
260
+ - **Never create new foundation specs.** Audit must not create `profile.md`, `stack.md`, `style.md`/`style.html`, `practices.md`, `architecture.md`, or `research.md`. The only new files audit may create are feature PRDs in `gspec/features/`, and only as the explicit resolution to an Orphan Capability finding.
261
+ - **Never silently update specs.** Every change — including creating a new feature PRD — requires user approval via the drift resolution flow.
187
262
  - **One discrepancy at a time.** Do not batch resolutions — the user decides each one individually.
188
263
  - **Be precise about the evidence.** Quote the spec, cite the file and line range where the code contradicts it. Vague drift reports ("the architecture is out of date") are not actionable.
189
- - **Prioritize by impact.** Present drifts that would cause incorrect implementation or confused future work first. Cosmetic drift comes last.
264
+ - **Prioritize by impact.** Present drifts that would cause incorrect implementation or confused future work first. Cosmetic drift comes last. Orphan Capabilities sit alongside Feature Drift in priority — both directly affect what `gspec-implement` will produce next.
190
265
  - **Treat the profile conservatively.** Profile drift usually reflects an intentional pivot and deserves a human decision, not an automatic spec update.
191
- - **Respect the scope hint.** If the user passes a hint like "audit the stack only", stick to it.
266
+ - **Respect the scope hint.** If the user passes a hint like "audit the stack only", stick to it. A scope hint of "audit features" includes Orphan Capability detection; a hint that excludes features (e.g. "audit the stack only") suppresses it.
192
267
 
193
268
  ---
194
269
 
@@ -186,6 +186,16 @@ When generating multiple features from a large request:
186
186
 
187
187
  ---
188
188
 
189
+ ## After Writing the PRD
190
+
191
+ After saving each PRD, end your response with a brief next-step pointer:
192
+
193
+ > *For larger features, run `/gspec-tasks <feature-slug>` to produce an ordered task plan with explicit dependencies and parallel-execution markers before running `/gspec-implement`. Trivial features can skip straight to `/gspec-implement`.*
194
+
195
+ This is a one-line nudge, not a prompt — do not generate the tasks file from this skill, and do not block the user on it.
196
+
197
+ ---
198
+
189
199
  ## Tone & Style
190
200
 
191
201
  - Clear, neutral, product-led