create-quiver 0.12.0 → 0.12.1

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 (109) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +49 -17
  3. package/README_FOR_AI.md +31 -29
  4. package/ROADMAP.md +15 -3
  5. package/docs/AI_ONBOARDING_PROMPT.md.template +7 -1
  6. package/docs/COMMANDS.md.template +44 -18
  7. package/docs/STATUS.md.template +5 -1
  8. package/docs/WORKFLOW.md.template +13 -11
  9. package/package.json +9 -3
  10. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/EVIDENCE_REPORT.md +293 -0
  11. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/EXECUTION_PLAN.md +58 -0
  12. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/SPEC.md +242 -0
  13. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/STATUS.md +35 -0
  14. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/pr.md +77 -0
  15. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +34 -0
  16. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +52 -0
  17. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/slice.json +52 -0
  18. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/CLOSURE_BRIEF.md +36 -0
  19. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/EXECUTION_BRIEF.md +52 -0
  20. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/slice.json +56 -0
  21. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/CLOSURE_BRIEF.md +43 -0
  22. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/EXECUTION_BRIEF.md +54 -0
  23. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/slice.json +52 -0
  24. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/CLOSURE_BRIEF.md +35 -0
  25. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/EXECUTION_BRIEF.md +53 -0
  26. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/slice.json +54 -0
  27. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/CLOSURE_BRIEF.md +34 -0
  28. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/EXECUTION_BRIEF.md +54 -0
  29. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/slice.json +52 -0
  30. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/CLOSURE_BRIEF.md +34 -0
  31. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/EXECUTION_BRIEF.md +54 -0
  32. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/slice.json +53 -0
  33. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/CLOSURE_BRIEF.md +33 -0
  34. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/EXECUTION_BRIEF.md +56 -0
  35. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/slice.json +55 -0
  36. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/CLOSURE_BRIEF.md +33 -0
  37. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/EXECUTION_BRIEF.md +54 -0
  38. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/slice.json +52 -0
  39. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/CLOSURE_BRIEF.md +39 -0
  40. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/EXECUTION_BRIEF.md +56 -0
  41. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/slice.json +53 -0
  42. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/CLOSURE_BRIEF.md +38 -0
  43. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/EXECUTION_BRIEF.md +57 -0
  44. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/slice.json +52 -0
  45. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/CLOSURE_BRIEF.md +39 -0
  46. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/EXECUTION_BRIEF.md +55 -0
  47. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/slice.json +56 -0
  48. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/CLOSURE_BRIEF.md +36 -0
  49. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/EXECUTION_BRIEF.md +54 -0
  50. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/slice.json +53 -0
  51. package/specs/quiver-v26-0121-smoke-hardening/EVIDENCE_REPORT.md +208 -0
  52. package/specs/quiver-v26-0121-smoke-hardening/EXECUTION_PLAN.md +57 -0
  53. package/specs/quiver-v26-0121-smoke-hardening/SPEC.md +137 -0
  54. package/specs/quiver-v26-0121-smoke-hardening/STATUS.md +32 -0
  55. package/specs/quiver-v26-0121-smoke-hardening/pr.md +96 -0
  56. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/CLOSURE_BRIEF.md +35 -0
  57. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/EXECUTION_BRIEF.md +55 -0
  58. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/slice.json +73 -0
  59. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/CLOSURE_BRIEF.md +38 -0
  60. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/EXECUTION_BRIEF.md +51 -0
  61. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/slice.json +76 -0
  62. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/CLOSURE_BRIEF.md +37 -0
  63. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/EXECUTION_BRIEF.md +52 -0
  64. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/slice.json +75 -0
  65. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/CLOSURE_BRIEF.md +37 -0
  66. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/EXECUTION_BRIEF.md +53 -0
  67. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/slice.json +77 -0
  68. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/CLOSURE_BRIEF.md +35 -0
  69. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/EXECUTION_BRIEF.md +52 -0
  70. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/slice.json +77 -0
  71. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/CLOSURE_BRIEF.md +34 -0
  72. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/EXECUTION_BRIEF.md +54 -0
  73. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/slice.json +84 -0
  74. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/CLOSURE_BRIEF.md +35 -0
  75. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/EXECUTION_BRIEF.md +53 -0
  76. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/slice.json +82 -0
  77. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/CLOSURE_BRIEF.md +35 -0
  78. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/EXECUTION_BRIEF.md +55 -0
  79. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/slice.json +92 -0
  80. package/src/create-quiver/commands/ai.js +577 -27
  81. package/src/create-quiver/commands/flow.js +6 -5
  82. package/src/create-quiver/commands/graph.js +6 -4
  83. package/src/create-quiver/commands/plan.js +3 -3
  84. package/src/create-quiver/index.js +328 -12
  85. package/src/create-quiver/lib/actionable-error.js +27 -0
  86. package/src/create-quiver/lib/agent-profiles.js +1 -1
  87. package/src/create-quiver/lib/ai/context-packs.js +4 -0
  88. package/src/create-quiver/lib/ai/execution-plan.js +7 -1
  89. package/src/create-quiver/lib/ai/executor.js +270 -20
  90. package/src/create-quiver/lib/ai/export-state.js +534 -0
  91. package/src/create-quiver/lib/ai/github.js +83 -0
  92. package/src/create-quiver/lib/ai/onboarding-template.js +215 -2
  93. package/src/create-quiver/lib/ai/plan-review.js +5 -2
  94. package/src/create-quiver/lib/ai/providers.js +4 -3
  95. package/src/create-quiver/lib/ai/run-state.js +414 -0
  96. package/src/create-quiver/lib/ai/spec-generator.js +12 -0
  97. package/src/create-quiver/lib/ai/spec-templates.js +78 -9
  98. package/src/create-quiver/lib/approvals.js +22 -3
  99. package/src/create-quiver/lib/demo.js +189 -14
  100. package/src/create-quiver/lib/doctor.js +75 -0
  101. package/src/create-quiver/lib/handoff.js +81 -12
  102. package/src/create-quiver/lib/init-docs.js +24 -6
  103. package/src/create-quiver/lib/init-layout.js +8 -0
  104. package/src/create-quiver/lib/json.js +53 -3
  105. package/src/create-quiver/lib/readiness.js +18 -3
  106. package/src/create-quiver/lib/scope.js +50 -7
  107. package/src/create-quiver/lib/slice-graph.js +138 -38
  108. package/src/create-quiver/lib/slice.js +6 -1
  109. package/src/create-quiver/lib/spec-worktrees.js +16 -2
@@ -1,6 +1,12 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const { toProjectSlug } = require('./init-layout');
3
+ const {
4
+ buildQuiverConfig,
5
+ buildQuiverInternalGitignore,
6
+ resolveInitPackageScripts,
7
+ toProjectSlug,
8
+ } = require('./init-layout');
9
+ const cliPackageJson = require('../../../package.json');
4
10
 
5
11
  const SPEC_VIEWER_DEMO = 'spec-viewer';
6
12
  const SPEC_VIEWER_PROJECT_NAME = 'Quiver Spec Viewer';
@@ -11,6 +17,14 @@ function createJson(data) {
11
17
  }
12
18
 
13
19
  function createSpecViewerFiles() {
20
+ const quiverScripts = {
21
+ ...resolveInitPackageScripts('default'),
22
+ 'quiver:plan': 'npx create-quiver plan --spec quiver-spec-viewer',
23
+ 'quiver:graph': 'npx create-quiver graph --spec quiver-spec-viewer',
24
+ 'quiver:next': 'npx create-quiver next --spec quiver-spec-viewer',
25
+ 'quiver:evidence': 'npx create-quiver evidence',
26
+ };
27
+
14
28
  return [
15
29
  {
16
30
  path: 'package.json',
@@ -22,13 +36,63 @@ function createSpecViewerFiles() {
22
36
  scripts: {
23
37
  start: 'node server.js',
24
38
  validate: 'node scripts/validate-demo.js',
25
- 'quiver:plan': 'npx create-quiver plan --spec quiver-spec-viewer',
26
- 'quiver:graph': 'npx create-quiver graph --spec quiver-spec-viewer',
27
- 'quiver:next': 'npx create-quiver next --spec quiver-spec-viewer',
28
- 'quiver:evidence': 'npx create-quiver evidence',
39
+ ...quiverScripts,
29
40
  },
30
41
  }),
31
42
  },
43
+ {
44
+ path: '.quiver/state.json',
45
+ content: createJson({
46
+ quiver_version: cliPackageJson.version || '0.0.0',
47
+ project_name: SPEC_VIEWER_PROJECT_NAME,
48
+ initialized_version: cliPackageJson.version || '0.0.0',
49
+ migrated_version: null,
50
+ last_initialized_at: '2026-05-23T00:00:00.000Z',
51
+ last_migration_at: null,
52
+ last_analysis_at: null,
53
+ demo: SPEC_VIEWER_DEMO,
54
+ }),
55
+ },
56
+ {
57
+ path: '.quiver/config.json',
58
+ content: createJson(buildQuiverConfig()),
59
+ },
60
+ {
61
+ path: '.quiver/.gitignore',
62
+ content: buildQuiverInternalGitignore(),
63
+ },
64
+ {
65
+ path: 'AGENTS.md',
66
+ content: `# Agents
67
+
68
+ Purpose
69
+
70
+ This demo is a small Quiver project used to inspect specs and slices.
71
+
72
+ ## Reading Budget
73
+
74
+ Start with README.md and the demo spec. Do not read generated or dependency folders.
75
+
76
+ ## Reading Order
77
+
78
+ 1. README.md
79
+ 2. docs/AI_ONBOARDING_PROMPT.md
80
+ 3. specs/quiver-spec-viewer/SPEC.md
81
+
82
+ ## Output Policy
83
+
84
+ Keep reports short and cite touched files.
85
+
86
+ ## Slice Execution Rules
87
+
88
+ Execute only the selected slice and keep changes inside its declared files.
89
+
90
+ ## Links
91
+
92
+ - docs/AI_ONBOARDING_PROMPT.md
93
+ - specs/quiver-spec-viewer/SPEC.md
94
+ `,
95
+ },
32
96
  {
33
97
  path: 'README.md',
34
98
  content: `# ${SPEC_VIEWER_PROJECT_NAME}
@@ -42,7 +106,19 @@ npm run validate
42
106
  npm start
43
107
  \`\`\`
44
108
 
45
- Open http://127.0.0.1:4173 after starting the server.
109
+ Open the URL printed by the server. It starts at http://127.0.0.1:4173 and automatically tries the next ports if that port is occupied.
110
+
111
+ To request a specific starting port:
112
+
113
+ \`\`\`bash
114
+ PORT=4300 npm start
115
+ \`\`\`
116
+
117
+ On Windows PowerShell:
118
+
119
+ \`\`\`powershell
120
+ $env:PORT = "4300"; npm start
121
+ \`\`\`
46
122
 
47
123
  ## Quiver workflow
48
124
 
@@ -51,6 +127,52 @@ Open http://127.0.0.1:4173 after starting the server.
51
127
  - The first implementation slice is \`slice-01-static-spec-viewer\`.
52
128
  - Use \`npm run quiver:plan\`, \`npm run quiver:graph\`, and \`npm run quiver:next\` to inspect execution order.
53
129
  - Use \`npm run quiver:evidence -- run -- npm run validate\` to capture validation evidence.
130
+ `,
131
+ },
132
+ {
133
+ path: 'docs/AI_CONTEXT.md',
134
+ content: `# Quiver Spec Viewer AI Context
135
+
136
+ This demo is a small static Quiver project. It exists to exercise Quiver specs, slices, validation, and diagnostics with minimal product code.
137
+
138
+ ## Relevant paths
139
+
140
+ - \`specs/quiver-spec-viewer/SPEC.md\`
141
+ - \`specs/quiver-spec-viewer/slices/\`
142
+ - \`src/\`
143
+ `,
144
+ },
145
+ {
146
+ path: 'docs/AI_ONBOARDING_PROMPT.md',
147
+ content: `# AI Onboarding Prompt
148
+
149
+ Read README.md, AGENTS.md, and specs/quiver-spec-viewer/SPEC.md.
150
+
151
+ Do not modify product files unless a slice explicitly asks for it.
152
+ `,
153
+ },
154
+ {
155
+ path: 'docs/COMMANDS.md',
156
+ content: `# Commands
157
+
158
+ | Command | Purpose |
159
+ |---|---|
160
+ | \`npm run validate\` | Validate required demo files. |
161
+ | \`npm start\` | Start the dependency-free static server. |
162
+ | \`npm run quiver:doctor\` | Run Quiver diagnostics. |
163
+ | \`npm run quiver:plan\` | Show demo slice execution order. |
164
+ | \`npm run quiver:graph\` | Show the demo slice graph. |
165
+ | \`npm run quiver:next\` | Suggest the next demo slice. |
166
+ `,
167
+ },
168
+ {
169
+ path: 'docs/WORKFLOW.md',
170
+ content: `# Workflow
171
+
172
+ 1. Validate the demo with \`npm run validate\`.
173
+ 2. Inspect the Quiver workflow with \`npm run quiver:plan\`, \`npm run quiver:graph\`, and \`npm run quiver:next\`.
174
+ 3. Execute only one slice at a time.
175
+ 4. Keep \`slice-00-docs-foundation\` as the documentary baseline.
54
176
  `,
55
177
  },
56
178
  {
@@ -60,14 +182,20 @@ const http = require('node:http');
60
182
  const path = require('node:path');
61
183
 
62
184
  const root = path.join(__dirname, 'src');
63
- const port = Number(process.env.PORT || 4173);
185
+ const startingPort = Number.parseInt(process.env.PORT || '4173', 10);
186
+ const maxPortAttempts = 10;
64
187
  const types = {
65
188
  '.css': 'text/css; charset=utf-8',
66
189
  '.html': 'text/html; charset=utf-8',
67
190
  '.js': 'text/javascript; charset=utf-8',
68
191
  };
69
192
 
70
- const server = http.createServer((request, response) => {
193
+ if (!Number.isInteger(startingPort) || startingPort < 1 || startingPort > 65535) {
194
+ console.error('Invalid PORT value. Use a number between 1 and 65535.');
195
+ process.exit(1);
196
+ }
197
+
198
+ function handleRequest(request, response) {
71
199
  const requestedPath = request.url === '/' ? '/index.html' : request.url;
72
200
  const filePath = path.normalize(path.join(root, requestedPath));
73
201
 
@@ -87,11 +215,31 @@ const server = http.createServer((request, response) => {
87
215
  response.writeHead(200, { 'Content-Type': types[path.extname(filePath)] || 'text/plain; charset=utf-8' });
88
216
  response.end(content);
89
217
  });
90
- });
218
+ }
91
219
 
92
- server.listen(port, '127.0.0.1', () => {
93
- console.log(\`Quiver Spec Viewer running at http://127.0.0.1:\${port}\`);
94
- });
220
+ function startServer(port, attempt = 0) {
221
+ const server = http.createServer(handleRequest);
222
+
223
+ server.on('error', (error) => {
224
+ if (error.code === 'EADDRINUSE' && attempt < maxPortAttempts) {
225
+ startServer(port + 1, attempt + 1);
226
+ return;
227
+ }
228
+
229
+ if (error.code === 'EADDRINUSE') {
230
+ console.error(\`Port \${port} is in use. Set PORT to a free port, for example: PORT=4300 npm start\`);
231
+ } else {
232
+ console.error(error.message);
233
+ }
234
+ process.exit(1);
235
+ });
236
+
237
+ server.listen(port, '127.0.0.1', () => {
238
+ console.log(\`Quiver Spec Viewer running at http://127.0.0.1:\${port}\`);
239
+ });
240
+ }
241
+
242
+ startServer(startingPort);
95
243
  `,
96
244
  },
97
245
  {
@@ -363,7 +511,16 @@ renderContent();
363
511
  const path = require('node:path');
364
512
 
365
513
  const required = [
514
+ '.quiver/config.json',
515
+ '.quiver/state.json',
516
+ '.quiver/.gitignore',
517
+ 'AGENTS.md',
366
518
  'README.md',
519
+ 'docs/AI_CONTEXT.md',
520
+ 'docs/AI_ONBOARDING_PROMPT.md',
521
+ 'docs/COMMANDS.md',
522
+ 'docs/WORKFLOW.md',
523
+ 'package.json',
367
524
  'server.js',
368
525
  'src/index.html',
369
526
  'src/styles.css',
@@ -380,6 +537,14 @@ if (missing.length > 0) {
380
537
  process.exit(1);
381
538
  }
382
539
 
540
+ const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
541
+ for (const scriptName of ['start', 'validate', 'quiver:doctor', 'quiver:plan', 'quiver:graph', 'quiver:next', 'quiver:evidence']) {
542
+ if (typeof packageJson.scripts?.[scriptName] !== 'string') {
543
+ console.error(\`Missing package script: \${scriptName}\`);
544
+ process.exit(1);
545
+ }
546
+ }
547
+
383
548
  console.log('Quiver Spec Viewer demo validated');
384
549
  `,
385
550
  },
@@ -477,7 +642,11 @@ This slice publishes the demo planning artifacts.
477
642
 
478
643
  Keep the Quiver Spec Viewer spec, status, evidence, and PR body available in the repo.
479
644
 
480
- ## Checklist
645
+ ## Acceptance Criteria
646
+
647
+ - Demo documentation artifacts exist.
648
+
649
+ ## Completion Checklist
481
650
 
482
651
  - [ ] Verify spec docs exist.
483
652
  - [ ] Run \`npm run validate\`.
@@ -535,7 +704,13 @@ The demo is intentionally static and dependency-free.
535
704
 
536
705
  Implement a small viewer for mocked Quiver specs and slices.
537
706
 
538
- ## Checklist
707
+ ## Acceptance Criteria
708
+
709
+ - Viewer shows title, spec list, and detail.
710
+ - Viewer supports loading, empty, error, and content states.
711
+ - Demo validates with npm run validate.
712
+
713
+ ## Completion Checklist
539
714
 
540
715
  - [ ] Keep the UI simple and readable.
541
716
  - [ ] Do not add heavy dependencies.
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
+ const { spawnSync } = require('child_process');
3
4
  const { readAllSlices } = require('./slice-graph');
4
5
  const { hasGeneratedProjectSpec, hasInitializedStateMetadata, readState } = require('./state');
5
6
  const { worktreeList } = require('./git');
@@ -512,6 +513,75 @@ function collectDoctorReport(projectRoot) {
512
513
  };
513
514
  }
514
515
 
516
+ function runEnvironmentProbe(command, args = [], options = {}) {
517
+ const runner = options.runner || spawnSync;
518
+ return runner(command, args, {
519
+ cwd: options.cwd,
520
+ encoding: 'utf8',
521
+ shell: false,
522
+ stdio: ['ignore', 'pipe', 'pipe'],
523
+ timeout: options.timeout || 3000,
524
+ });
525
+ }
526
+
527
+ function probeOk(command, args, options = {}) {
528
+ const result = runEnvironmentProbe(command, args, options);
529
+ if (result && result.error && result.error.code === 'ENOENT') {
530
+ return {
531
+ ok: false,
532
+ reason: 'missing',
533
+ };
534
+ }
535
+ return {
536
+ ok: Boolean(result && result.status === 0),
537
+ reason: result && result.error ? result.error.message : result && result.stderr ? String(result.stderr).trim() : '',
538
+ };
539
+ }
540
+
541
+ function collectEnvironmentWarnings(projectRoot, options = {}) {
542
+ const warnings = [];
543
+ const cwd = projectRoot;
544
+
545
+ const checks = [
546
+ ['node', ['--version'], 'Node.js is required to run create-quiver. Install Node 20+ and retry.'],
547
+ ['npm', ['--version'], 'npm is required for generated npm scripts and package smokes. Install npm or use a Node distribution that includes it.'],
548
+ ['git', ['--version'], 'git is required for specs, slices, worktrees, commits, and PR flow. Install git and retry.'],
549
+ ];
550
+
551
+ for (const [command, args, message] of checks) {
552
+ const check = probeOk(command, args, { ...options, cwd });
553
+ if (!check.ok) {
554
+ warnings.push(`${command} check failed: ${message}`);
555
+ }
556
+ }
557
+
558
+ const ghCheck = probeOk('gh', ['--version'], { ...options, cwd });
559
+ if (!ghCheck.ok) {
560
+ warnings.push('gh check failed: GitHub CLI is required for `ai pr` and `ai doctor`. macOS: brew install gh. Linux: use your distro package manager. Windows: winget install GitHub.cli.');
561
+ } else {
562
+ const authCheck = probeOk('gh', ['auth', 'status'], { ...options, cwd });
563
+ if (!authCheck.ok) {
564
+ warnings.push('gh auth check failed: run `gh auth login` before using `ai pr --create`.');
565
+ }
566
+ }
567
+
568
+ if (!process.env.SHELL && !process.env.ComSpec) {
569
+ warnings.push('shell check failed: no SHELL or ComSpec environment variable was detected.');
570
+ }
571
+
572
+ if (projectRoot.includes(' ')) {
573
+ warnings.push('path contains spaces: use quoted paths when copying manual commands.');
574
+ }
575
+
576
+ try {
577
+ fs.accessSync(projectRoot, fs.constants.W_OK);
578
+ } catch {
579
+ warnings.push('permission check failed: current user cannot write to the project root.');
580
+ }
581
+
582
+ return warnings;
583
+ }
584
+
515
585
  function collectDoctorWarnings(projectRoot) {
516
586
  const warnings = [];
517
587
 
@@ -547,6 +617,10 @@ function collectDoctorWarnings(projectRoot) {
547
617
  warnings.push(`missing local docs link: ${issue}`);
548
618
  }
549
619
 
620
+ for (const issue of collectEnvironmentWarnings(projectRoot)) {
621
+ warnings.push(issue);
622
+ }
623
+
550
624
  return warnings;
551
625
  }
552
626
 
@@ -554,6 +628,7 @@ module.exports = {
554
628
  applyDoctorFixPlan,
555
629
  buildDoctorFixPlan,
556
630
  collectDoctorReport,
631
+ collectEnvironmentWarnings,
557
632
  collectDoctorWarnings,
558
633
  collectLayoutReport,
559
634
  formatDoctorFixPlan,
@@ -10,6 +10,36 @@ const REQUIRED_HEADINGS = [
10
10
  '## Constraints',
11
11
  ];
12
12
 
13
+ const EXECUTION_BRIEF_REQUIRED_HEADINGS = [
14
+ {
15
+ label: 'context',
16
+ alternatives: ['## Context', '## Contexto'],
17
+ },
18
+ {
19
+ label: 'objective',
20
+ alternatives: ['## Objective', '## Objetivo'],
21
+ },
22
+ {
23
+ label: 'acceptance criteria',
24
+ alternatives: ['## Acceptance Criteria', '## Criterios de aceptacion', '## Criterios de aceptación'],
25
+ },
26
+ {
27
+ label: 'completion checklist',
28
+ alternatives: ['## Completion Checklist', '## Checklist de finalizacion', '## Checklist de finalización'],
29
+ },
30
+ ];
31
+
32
+ const CLOSURE_BRIEF_REQUIRED_HEADINGS = [
33
+ {
34
+ label: 'summary',
35
+ alternatives: ['## Summary', '## Summary of Work', '## Resumen de lo realizado'],
36
+ },
37
+ {
38
+ label: 'validation',
39
+ alternatives: ['## Validation', '## Validation Against Acceptance Criteria', '## Validacion contra criterios de aceptacion', '## Validación contra criterios de aceptación'],
40
+ },
41
+ ];
42
+
13
43
  const HANDOFF_TEMPLATE_PATH = path.resolve(__dirname, '..', '..', '..', 'specs', '[project-name]', 'HANDOFF.md.template');
14
44
 
15
45
  function normalizePosixPath(filePath, pathLib = path) {
@@ -21,19 +51,36 @@ function resolveHandoffPath(repoRoot, handoffInput, pathLib = path) {
21
51
  const relativePath = normalizePosixPath(pathLib.relative(repoRoot, absolutePath), pathLib);
22
52
 
23
53
  if (relativePath.startsWith('..') || pathLib.isAbsolute(relativePath)) {
24
- throw new Error(`create-quiver: handoff must live at specs/<spec-slug>/HANDOFF.md (got ${normalizePosixPath(handoffInput, pathLib)})`);
54
+ throw new Error(`create-quiver: handoff or brief must live under specs/<spec-slug>/ (got ${normalizePosixPath(handoffInput, pathLib)})`);
55
+ }
56
+
57
+ const handoffMatch = relativePath.match(/^(specs|specs-fix)\/([^/]+)\/HANDOFF\.md$/);
58
+ if (handoffMatch) {
59
+ return {
60
+ absolutePath,
61
+ relativePath,
62
+ specFamily: handoffMatch[1],
63
+ specSlug: handoffMatch[2],
64
+ kind: 'handoff',
65
+ label: 'Handoff',
66
+ };
25
67
  }
26
68
 
27
- const match = relativePath.match(/^specs\/([^/]+)\/HANDOFF\.md$/);
28
- if (!match) {
29
- throw new Error(`create-quiver: handoff must live at specs/<spec-slug>/HANDOFF.md (got ${relativePath})`);
69
+ const briefMatch = relativePath.match(/^(specs|specs-fix)\/([^/]+)\/slices\/([^/]+)\/(EXECUTION_BRIEF|CLOSURE_BRIEF)\.md$/);
70
+ if (briefMatch) {
71
+ const briefName = briefMatch[4];
72
+ return {
73
+ absolutePath,
74
+ relativePath,
75
+ specFamily: briefMatch[1],
76
+ specSlug: briefMatch[2],
77
+ sliceId: briefMatch[3],
78
+ kind: briefName === 'EXECUTION_BRIEF' ? 'execution-brief' : 'closure-brief',
79
+ label: briefName === 'EXECUTION_BRIEF' ? 'Execution brief' : 'Closure brief',
80
+ };
30
81
  }
31
82
 
32
- return {
33
- absolutePath,
34
- relativePath,
35
- specSlug: match[1],
36
- };
83
+ throw new Error(`create-quiver: handoff or brief must live at specs/<spec-slug>/HANDOFF.md or specs/<spec-slug>/slices/<slice-id>/EXECUTION_BRIEF.md|CLOSURE_BRIEF.md (got ${relativePath})`);
37
84
  }
38
85
 
39
86
  function readHandoffSections(text) {
@@ -49,17 +96,36 @@ function validateHandoffSections(text) {
49
96
  return REQUIRED_HEADINGS.filter((heading) => !sections.has(heading));
50
97
  }
51
98
 
99
+ function normalizeHeading(heading) {
100
+ return String(heading || '')
101
+ .normalize('NFD')
102
+ .replace(/[\u0300-\u036f]/g, '')
103
+ .trim()
104
+ .toLowerCase();
105
+ }
106
+
107
+ function validateBriefSections(text, kind) {
108
+ const sections = new Set(readHandoffSections(text).map(normalizeHeading));
109
+ const requiredGroups = kind === 'closure-brief' ? CLOSURE_BRIEF_REQUIRED_HEADINGS : EXECUTION_BRIEF_REQUIRED_HEADINGS;
110
+
111
+ return requiredGroups
112
+ .filter((group) => !group.alternatives.some((heading) => sections.has(normalizeHeading(heading))))
113
+ .map((group) => group.label);
114
+ }
115
+
52
116
  function checkHandoff(handoffInput, repoRoot = process.cwd()) {
53
117
  const resolved = resolveHandoffPath(repoRoot, handoffInput);
54
118
 
55
119
  if (!fs.existsSync(resolved.absolutePath)) {
56
- throw new Error(`create-quiver: missing handoff file: ${resolved.relativePath}`);
120
+ throw new Error(`create-quiver: missing ${resolved.label.toLowerCase()} file: ${resolved.relativePath}`);
57
121
  }
58
122
 
59
123
  const text = fs.readFileSync(resolved.absolutePath, 'utf8');
60
- const missingSections = validateHandoffSections(text);
124
+ const missingSections = resolved.kind === 'handoff'
125
+ ? validateHandoffSections(text)
126
+ : validateBriefSections(text, resolved.kind);
61
127
  if (missingSections.length > 0) {
62
- throw new Error(`create-quiver: handoff is missing required sections: ${missingSections.join(', ')}`);
128
+ throw new Error(`create-quiver: ${resolved.label.toLowerCase()} is missing required sections: ${missingSections.join(', ')}`);
63
129
  }
64
130
 
65
131
  return resolved;
@@ -95,10 +161,13 @@ function scaffoldHandoff(specSlug, repoRoot = process.cwd()) {
95
161
  }
96
162
 
97
163
  module.exports = {
164
+ CLOSURE_BRIEF_REQUIRED_HEADINGS,
165
+ EXECUTION_BRIEF_REQUIRED_HEADINGS,
98
166
  REQUIRED_HEADINGS,
99
167
  checkHandoff,
100
168
  readHandoffSections,
101
169
  scaffoldHandoff,
102
170
  resolveHandoffPath,
171
+ validateBriefSections,
103
172
  validateHandoffSections,
104
173
  };
@@ -316,8 +316,14 @@ Use \`AGENTS.md\` first, then \`docs/AI_CONTEXT.md\` and \`docs/AI_ONBOARDING_PR
316
316
  \`\`\`bash
317
317
  npm run quiver:prepare -- --dry-run
318
318
  npm run quiver:ai:onboard -- --dry-run
319
+ npm run quiver:ai:inspect
320
+ npm run quiver:ai:export -- --format json
321
+ npm run quiver:ai:specs
322
+ npm run quiver:ai:slices
323
+ npm run quiver:ai:trace
319
324
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
320
- npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
325
+ npm run quiver:ai:revise -- --phase acceptance --input feedback.md --dry-run
326
+ npm run quiver:ai:approve -- --phase acceptance --version <n>
321
327
  npm run quiver:ai:plan -- --phase technical-plan --dry-run
322
328
  npm run quiver:ai:review-plan -- --dry-run
323
329
  npm run quiver:ai:approve -- --phase technical-plan --version <n>
@@ -371,7 +377,8 @@ Use dry-runs before spending model tokens:
371
377
  npm run quiver:prepare -- --dry-run
372
378
  npm run quiver:ai:onboard -- --dry-run
373
379
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
374
- npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
380
+ npm run quiver:ai:revise -- --phase acceptance --input feedback.md --dry-run
381
+ npm run quiver:ai:approve -- --phase acceptance --version <n>
375
382
  npm run quiver:ai:plan -- --phase technical-plan --dry-run
376
383
  npm run quiver:ai:review-plan -- --dry-run
377
384
  npm run quiver:ai:approve -- --phase technical-plan --version <n>
@@ -397,9 +404,16 @@ npm run quiver:plan
397
404
  npm run quiver:graph
398
405
  npm run quiver:next
399
406
  npm run quiver:doctor
407
+ npm run quiver:ai:inspect
408
+ npm run quiver:ai:export -- --format json
409
+ npm run quiver:ai:export -- --format markdown
410
+ npm run quiver:ai:specs
411
+ npm run quiver:ai:slices
412
+ npm run quiver:ai:trace
400
413
  npm run quiver:ai:onboard -- --dry-run
401
414
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
402
- npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
415
+ npm run quiver:ai:revise -- --phase acceptance --input feedback.md --dry-run
416
+ npm run quiver:ai:approve -- --phase acceptance --version <n>
403
417
  npm run quiver:ai:plan -- --phase technical-plan --dry-run
404
418
  npm run quiver:ai:review-plan -- --dry-run
405
419
  npm run quiver:ai:approve -- --phase technical-plan --version <n>
@@ -470,7 +484,8 @@ Start with dry-runs so you can inspect the provider, role, context pack, and inv
470
484
  npm run quiver:prepare -- --dry-run
471
485
  npm run quiver:ai:onboard -- --dry-run
472
486
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
473
- npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
487
+ npm run quiver:ai:revise -- --phase acceptance --input feedback.md --dry-run
488
+ npm run quiver:ai:approve -- --phase acceptance --version <n>
474
489
  npm run quiver:ai:plan -- --phase technical-plan --dry-run
475
490
  npm run quiver:ai:review-plan -- --dry-run
476
491
  npm run quiver:ai:approve -- --phase technical-plan --version <n>
@@ -497,7 +512,8 @@ npm run quiver:next
497
512
  npm run quiver:doctor
498
513
  npm run quiver:ai:onboard -- --dry-run
499
514
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
500
- npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
515
+ npm run quiver:ai:revise -- --phase acceptance --input feedback.md --dry-run
516
+ npm run quiver:ai:approve -- --phase acceptance --version <n>
501
517
  npm run quiver:ai:plan -- --phase technical-plan --dry-run
502
518
  npm run quiver:ai:review-plan -- --dry-run
503
519
  npm run quiver:ai:approve -- --phase technical-plan --version <n>
@@ -515,6 +531,7 @@ npm run quiver:start-slice -- specs/${projectSlug}/slices/slice-01/slice.json
515
531
  npm run quiver:check-slice -- specs/${projectSlug}/slices/slice-01/slice.json
516
532
  npm run quiver:check-pr -- specs/${projectSlug}/slices/slice-01/slice.json
517
533
  npm run quiver:check-handoff -- specs/${projectSlug}/HANDOFF.md
534
+ npm run quiver:check-handoff -- specs/${projectSlug}/slices/slice-01/EXECUTION_BRIEF.md
518
535
  npm run quiver:cleanup-slice -- specs/${projectSlug}/slices/slice-01/slice.json
519
536
  npm run quiver:check-scope -- specs/${projectSlug}/slices/slice-01/slice.json
520
537
  npm run quiver:refresh-active-slices
@@ -522,13 +539,14 @@ npm run quiver:refresh-active-slices
522
539
 
523
540
  The \`quiver:graph\` script prints the tree view by default; use \`npx create-quiver graph --format mermaid\` for PR-ready Markdown and \`--format dot\` when you want Graphviz source.
524
541
  The \`quiver:next\` script points to the next ready slice and can auto-start it behind a confirmation prompt.
525
- The \`quiver:ai:*\` scripts standardize planner/executor AI flows. Use dry-run first: onboarding and planning dry-runs do not require provider auth, \`quiver:ai:execute-plan -- --dry-run --commit --mode manual\` prints manual prompts, \`--mode delegated\` prints safe waves, and \`quiver:ai:pr -- --dry-run\` validates \`gh\`, GitFlow docs, branch/worktree state, SSH inputs, and \`pr.md\` without creating a PR. Add \`--create\` only after reviewing the plan.
542
+ The \`quiver:ai:*\` scripts standardize planner/executor AI flows. Use dry-run first: onboarding and planning dry-runs do not require provider auth, \`quiver:ai:execute-plan -- --dry-run --commit --mode manual\` prints manual prompts, \`--mode delegated\` prints safe waves, \`quiver:ai:inspect\` shows lifecycle state, \`quiver:ai:export -- --format json|markdown\` emits dashboard/agent-friendly state, and \`quiver:ai:pr -- --dry-run\` validates \`gh\`, GitFlow docs, branch/worktree state, SSH inputs, and \`pr.md\` without creating a PR. Add \`--create\` only after reviewing the plan.
526
543
  Use \`quiver:spec:create\`, \`quiver:spec:start\`, \`quiver:spec:status\`, and \`quiver:spec:close\` for one spec generation and worktree per spec.
527
544
  Use \`npx create-quiver next --all-ready\` when you want the full ready level instead of a single suggestion.
528
545
  The legacy Bash wrappers remain in \`tools/scripts/\` for compatibility, but new project-level automation should prefer the \`quiver:*\` scripts and the direct \`npx create-quiver ...\` commands below.
529
546
  \`npm run quiver:migrate\` is only for projects that were already initialized by Quiver.
530
547
  \`npm run check-handoff -- specs/${projectSlug}/HANDOFF.md\` is available as a legacy-friendly alias for the handoff validator.
531
548
  If a new bounded transfer is needed, scaffold \`specs/${projectSlug}/HANDOFF.md\` with \`npx create-quiver new-handoff ${projectSlug}\` and validate it with \`npx create-quiver check-handoff specs/${projectSlug}/HANDOFF.md\`.
549
+ Use \`npx create-quiver check-handoff specs/${projectSlug}/slices/slice-01/EXECUTION_BRIEF.md\` or \`CLOSURE_BRIEF.md\` to validate the current per-slice brief contract.
532
550
  For exceptional context transfers between agents or phases, a dedicated \`HANDOFF.md\` can live alongside the usual spec and docs files.
533
551
 
534
552
  ## Cross-Platform Support
@@ -82,6 +82,7 @@ function quiverInternalPaths(projectRoot) {
82
82
  cacheDir: path.join(root, 'cache'),
83
83
  configPath: path.join(root, 'config.json'),
84
84
  gitignorePath: path.join(root, '.gitignore'),
85
+ locksDir: path.join(root, 'locks'),
85
86
  runsDir: path.join(root, 'runs'),
86
87
  scansDir: path.join(root, 'scans'),
87
88
  statePath: path.join(root, 'state.json'),
@@ -94,6 +95,7 @@ function buildQuiverInternalGitignore() {
94
95
  return [
95
96
  'cache/',
96
97
  'evidence/',
98
+ 'locks/',
97
99
  'runs/',
98
100
  'worktrees/',
99
101
  '',
@@ -188,9 +190,15 @@ function resolveInitPackageScripts(profile, options = {}) {
188
190
  'quiver:doctor': 'npx create-quiver doctor',
189
191
  'quiver:evidence': 'npx create-quiver evidence',
190
192
  'quiver:ai:agent': 'npx create-quiver ai agent',
193
+ 'quiver:ai:inspect': 'npx create-quiver ai inspect',
194
+ 'quiver:ai:export': 'npx create-quiver ai export',
195
+ 'quiver:ai:specs': 'npx create-quiver ai specs list',
196
+ 'quiver:ai:slices': 'npx create-quiver ai slices list',
197
+ 'quiver:ai:trace': 'npx create-quiver ai trace report',
191
198
  'quiver:ai:onboard': 'npx create-quiver ai onboard',
192
199
  'quiver:ai:prepare-context': 'npx create-quiver ai prepare-context',
193
200
  'quiver:ai:plan': 'npx create-quiver ai plan',
201
+ 'quiver:ai:revise': 'npx create-quiver ai revise',
194
202
  'quiver:ai:review-plan': 'npx create-quiver ai review-plan',
195
203
  'quiver:ai:approve': 'npx create-quiver ai approve',
196
204
  'quiver:ai:prompt-slice': 'npx create-quiver ai prompt-slice',