create-quiver 0.10.0 → 0.12.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 (165) hide show
  1. package/BACKLOG.md +16 -17
  2. package/CHANGELOG.md +34 -0
  3. package/README.md +174 -39
  4. package/README_FOR_AI.md +48 -24
  5. package/ROADMAP.md +22 -11
  6. package/docs/AI_CONTEXT.md.template +2 -0
  7. package/docs/AI_ONBOARDING_PROMPT.md.template +25 -18
  8. package/docs/COMMANDS.md.template +59 -11
  9. package/docs/CONTEXTO.md.template +2 -0
  10. package/docs/DECISIONS.md.template +1 -0
  11. package/docs/INDEX.md.template +20 -18
  12. package/docs/STATUS.md.template +1 -0
  13. package/docs/SUPPORT_MATRIX.md.template +2 -2
  14. package/docs/TROUBLESHOOTING.md.template +50 -0
  15. package/docs/WORKFLOW.md.template +25 -17
  16. package/package.json +19 -2
  17. package/package.template.json +13 -1
  18. package/scripts/init-docs.sh +11 -4
  19. package/scripts/package-quiver.sh +18 -2
  20. package/specs/quiver-v22-guided-ai-workflow/EVIDENCE_REPORT.md +58 -0
  21. package/specs/quiver-v22-guided-ai-workflow/EXECUTION_PLAN.md +88 -0
  22. package/specs/quiver-v22-guided-ai-workflow/SPEC.md +228 -0
  23. package/specs/quiver-v22-guided-ai-workflow/STATUS.md +42 -0
  24. package/specs/quiver-v22-guided-ai-workflow/pr.md +104 -0
  25. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +35 -0
  26. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
  27. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/slice.json +51 -0
  28. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/CLOSURE_BRIEF.md +31 -0
  29. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/EXECUTION_BRIEF.md +58 -0
  30. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/slice.json +55 -0
  31. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/CLOSURE_BRIEF.md +30 -0
  32. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/EXECUTION_BRIEF.md +57 -0
  33. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/slice.json +57 -0
  34. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/CLOSURE_BRIEF.md +32 -0
  35. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/EXECUTION_BRIEF.md +56 -0
  36. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/slice.json +56 -0
  37. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/CLOSURE_BRIEF.md +33 -0
  38. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/EXECUTION_BRIEF.md +56 -0
  39. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/slice.json +58 -0
  40. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/CLOSURE_BRIEF.md +32 -0
  41. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/EXECUTION_BRIEF.md +56 -0
  42. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/slice.json +54 -0
  43. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/CLOSURE_BRIEF.md +32 -0
  44. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/EXECUTION_BRIEF.md +58 -0
  45. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/slice.json +57 -0
  46. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/CLOSURE_BRIEF.md +32 -0
  47. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/EXECUTION_BRIEF.md +58 -0
  48. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/slice.json +55 -0
  49. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/CLOSURE_BRIEF.md +32 -0
  50. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/EXECUTION_BRIEF.md +58 -0
  51. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/slice.json +53 -0
  52. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/CLOSURE_BRIEF.md +33 -0
  53. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/EXECUTION_BRIEF.md +59 -0
  54. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/slice.json +59 -0
  55. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +34 -0
  56. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +58 -0
  57. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/slice.json +60 -0
  58. package/specs/quiver-v23-guided-flow-productization/EVIDENCE_REPORT.md +80 -0
  59. package/specs/quiver-v23-guided-flow-productization/EXECUTION_PLAN.md +80 -0
  60. package/specs/quiver-v23-guided-flow-productization/SPEC.md +203 -0
  61. package/specs/quiver-v23-guided-flow-productization/STATUS.md +39 -0
  62. package/specs/quiver-v23-guided-flow-productization/pr.md +119 -0
  63. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +30 -0
  64. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
  65. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/slice.json +51 -0
  66. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/CLOSURE_BRIEF.md +33 -0
  67. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/EXECUTION_BRIEF.md +35 -0
  68. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/slice.json +56 -0
  69. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/CLOSURE_BRIEF.md +31 -0
  70. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/EXECUTION_BRIEF.md +29 -0
  71. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/slice.json +55 -0
  72. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/CLOSURE_BRIEF.md +33 -0
  73. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/EXECUTION_BRIEF.md +29 -0
  74. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/slice.json +54 -0
  75. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/CLOSURE_BRIEF.md +32 -0
  76. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/EXECUTION_BRIEF.md +30 -0
  77. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/slice.json +59 -0
  78. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/CLOSURE_BRIEF.md +31 -0
  79. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/EXECUTION_BRIEF.md +29 -0
  80. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/slice.json +53 -0
  81. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/CLOSURE_BRIEF.md +33 -0
  82. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/EXECUTION_BRIEF.md +30 -0
  83. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/slice.json +54 -0
  84. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/CLOSURE_BRIEF.md +33 -0
  85. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/EXECUTION_BRIEF.md +30 -0
  86. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/slice.json +55 -0
  87. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/CLOSURE_BRIEF.md +32 -0
  88. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/EXECUTION_BRIEF.md +30 -0
  89. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/slice.json +55 -0
  90. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/CLOSURE_BRIEF.md +33 -0
  91. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/EXECUTION_BRIEF.md +34 -0
  92. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/slice.json +57 -0
  93. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +33 -0
  94. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +32 -0
  95. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/slice.json +63 -0
  96. package/specs/quiver-v24-dx-onboarding-hardening/EVIDENCE_REPORT.md +55 -0
  97. package/specs/quiver-v24-dx-onboarding-hardening/EXECUTION_PLAN.md +43 -0
  98. package/specs/quiver-v24-dx-onboarding-hardening/SPEC.md +149 -0
  99. package/specs/quiver-v24-dx-onboarding-hardening/STATUS.md +31 -0
  100. package/specs/quiver-v24-dx-onboarding-hardening/pr.md +76 -0
  101. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +31 -0
  102. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +52 -0
  103. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/slice.json +51 -0
  104. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/CLOSURE_BRIEF.md +38 -0
  105. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/EXECUTION_BRIEF.md +53 -0
  106. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/slice.json +55 -0
  107. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/CLOSURE_BRIEF.md +33 -0
  108. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/EXECUTION_BRIEF.md +50 -0
  109. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/slice.json +52 -0
  110. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/CLOSURE_BRIEF.md +33 -0
  111. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/EXECUTION_BRIEF.md +50 -0
  112. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/slice.json +53 -0
  113. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/CLOSURE_BRIEF.md +33 -0
  114. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/EXECUTION_BRIEF.md +50 -0
  115. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/slice.json +70 -0
  116. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/CLOSURE_BRIEF.md +36 -0
  117. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/EXECUTION_BRIEF.md +49 -0
  118. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/slice.json +52 -0
  119. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/CLOSURE_BRIEF.md +43 -0
  120. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/EXECUTION_BRIEF.md +53 -0
  121. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/slice.json +60 -0
  122. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/CLOSURE_BRIEF.md +32 -0
  123. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/EXECUTION_BRIEF.md +50 -0
  124. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/slice.json +51 -0
  125. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/CLOSURE_BRIEF.md +34 -0
  126. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/EXECUTION_BRIEF.md +52 -0
  127. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/slice.json +54 -0
  128. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/CLOSURE_BRIEF.md +34 -0
  129. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/EXECUTION_BRIEF.md +51 -0
  130. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/slice.json +59 -0
  131. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +33 -0
  132. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +54 -0
  133. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/slice.json +76 -0
  134. package/src/create-quiver/commands/ai.js +508 -35
  135. package/src/create-quiver/commands/demo.js +22 -0
  136. package/src/create-quiver/commands/evidence.js +37 -0
  137. package/src/create-quiver/commands/flow.js +561 -0
  138. package/src/create-quiver/commands/graph.js +14 -1
  139. package/src/create-quiver/commands/next.js +28 -0
  140. package/src/create-quiver/commands/plan.js +6 -3
  141. package/src/create-quiver/commands/prepare.js +236 -0
  142. package/src/create-quiver/commands/spec.js +133 -0
  143. package/src/create-quiver/index.js +688 -25
  144. package/src/create-quiver/lib/agent-profiles.js +148 -0
  145. package/src/create-quiver/lib/ai/context-packs.js +12 -0
  146. package/src/create-quiver/lib/ai/execution-plan.js +370 -10
  147. package/src/create-quiver/lib/ai/executor.js +376 -17
  148. package/src/create-quiver/lib/ai/github.js +196 -0
  149. package/src/create-quiver/lib/ai/onboarding-template.js +365 -0
  150. package/src/create-quiver/lib/ai/plan-review.js +283 -0
  151. package/src/create-quiver/lib/ai/providers.js +1 -0
  152. package/src/create-quiver/lib/ai/safety.js +5 -0
  153. package/src/create-quiver/lib/ai/spec-templates.js +2 -2
  154. package/src/create-quiver/lib/approvals.js +350 -0
  155. package/src/create-quiver/lib/demo.js +657 -0
  156. package/src/create-quiver/lib/doctor.js +234 -0
  157. package/src/create-quiver/lib/evidence.js +115 -0
  158. package/src/create-quiver/lib/init-docs.js +284 -17
  159. package/src/create-quiver/lib/init-layout.js +26 -1
  160. package/src/create-quiver/lib/lifecycle.js +6 -0
  161. package/src/create-quiver/lib/package-safety.js +117 -0
  162. package/src/create-quiver/lib/readiness.js +85 -18
  163. package/src/create-quiver/lib/slice-graph.js +1 -0
  164. package/src/create-quiver/lib/slice.js +8 -8
  165. package/src/create-quiver/lib/spec-worktrees.js +349 -0
@@ -205,6 +205,57 @@ function writeFrontMatter(filePath, fields) {
205
205
  return nextContent;
206
206
  }
207
207
 
208
+ const ROOT_GITIGNORE_DEFAULTS = [
209
+ 'node_modules/',
210
+ '.DS_Store',
211
+ 'dist/',
212
+ 'coverage/',
213
+ ];
214
+
215
+ function normalizeGitignorePattern(line) {
216
+ const trimmed = line.trim();
217
+ if (!trimmed || trimmed.startsWith('#')) {
218
+ return trimmed;
219
+ }
220
+
221
+ return trimmed.replace(/\/+$/g, '');
222
+ }
223
+
224
+ function mergeLineList(existingText, defaults) {
225
+ const existingLines = existingText
226
+ .split(/\r?\n/)
227
+ .filter((line, index, lines) => line.length > 0 || index < lines.length - 1);
228
+ const seen = new Set(existingLines.map(normalizeGitignorePattern).filter(Boolean));
229
+ const nextLines = [...existingLines];
230
+
231
+ for (const line of defaults) {
232
+ const normalized = normalizeGitignorePattern(line);
233
+ if (!seen.has(normalized)) {
234
+ nextLines.push(line);
235
+ seen.add(normalized);
236
+ }
237
+ }
238
+
239
+ return `${nextLines.join('\n').replace(/\s+$/g, '')}\n`;
240
+ }
241
+
242
+ function mergeRootGitignore(projectRoot) {
243
+ const gitignorePath = path.join(projectRoot, '.gitignore');
244
+ const exists = fs.existsSync(gitignorePath);
245
+ const existingText = exists
246
+ ? fs.readFileSync(gitignorePath, 'utf8')
247
+ : '';
248
+
249
+ ensureDir(path.dirname(gitignorePath));
250
+ fs.writeFileSync(gitignorePath, mergeLineList(existingText, ROOT_GITIGNORE_DEFAULTS));
251
+ return exists ? 'merged' : 'created';
252
+ }
253
+
254
+ function resolvePackageName(projectRoot, options = {}) {
255
+ return options.projectSlug
256
+ || toProjectSlug(options.projectName || path.basename(projectRoot) || 'Quiver Project');
257
+ }
258
+
208
259
  function mergePackageJson(projectRoot, templateRoot, options = {}) {
209
260
  const packageTemplate = path.join(templateRoot, 'package.template.json');
210
261
  const packageJsonPath = path.join(projectRoot, 'package.json');
@@ -218,13 +269,17 @@ function mergePackageJson(projectRoot, templateRoot, options = {}) {
218
269
 
219
270
  if (!fs.existsSync(packageJsonPath)) {
220
271
  const template = JSON.parse(fs.readFileSync(packageTemplate, 'utf8'));
272
+ template.name = resolvePackageName(projectRoot, options);
221
273
  template.scripts = scripts;
222
274
  fs.writeFileSync(packageJsonPath, `${JSON.stringify(template, null, 2)}\n`);
223
275
  return 'created';
224
276
  }
225
277
 
226
278
  const existing = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
227
- const template = JSON.parse(fs.readFileSync(packageTemplate, 'utf8'));
279
+
280
+ if (typeof existing.name !== 'string' || existing.name.trim().length === 0) {
281
+ existing.name = resolvePackageName(projectRoot, options);
282
+ }
228
283
 
229
284
  existing.scripts = {
230
285
  ...(existing.scripts || {}),
@@ -259,16 +314,22 @@ npx create-quiver next
259
314
  Use \`AGENTS.md\` first, then \`docs/AI_CONTEXT.md\` and \`docs/AI_ONBOARDING_PROMPT.md\` for the working contract.
260
315
 
261
316
  \`\`\`bash
317
+ npm run quiver:prepare -- --dry-run
262
318
  npm run quiver:ai:onboard -- --dry-run
263
319
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
264
- npm run quiver:ai:plan -- --phase technical-plan --input acceptance-approved.md --dry-run
265
- npm run quiver:ai:plan -- --phase spec --input technical-plan-approved.md --dry-run
320
+ npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
321
+ npm run quiver:ai:plan -- --phase technical-plan --dry-run
322
+ npm run quiver:ai:review-plan -- --dry-run
323
+ npm run quiver:ai:approve -- --phase technical-plan --version <n>
324
+ npm run quiver:spec:create -- --dry-run
266
325
  \`\`\`
267
326
 
268
327
  When a real spec exists, execute one approved slice at a time:
269
328
 
270
329
  \`\`\`bash
271
- npm run quiver:ai:execute-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run
330
+ npm run quiver:ai:prompt-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run
331
+ npm run quiver:ai:execute-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run --commit
332
+ npm run quiver:ai:execute-plan -- --dry-run --commit --mode delegated
272
333
  \`\`\`
273
334
 
274
335
  ## Documentation
@@ -302,21 +363,27 @@ After \`analyze\`, use \`docs/PROJECT_MAP.md\` for the detected stack, package m
302
363
 
303
364
  ## AI-First Workflow
304
365
 
305
- Quiver keeps the visible contract small: start with \`README.md\`, \`AGENTS.md\`, and \`docs/\`. Specs and slices should be created only after a real requirement and an approved technical plan.
366
+ Quiver keeps the visible contract small: start with \`README.md\`, \`AGENTS.md\`, and \`docs/\`. Specs and slices should be created only after a real requirement and a reviewed, approved technical plan.
306
367
 
307
368
  Use dry-runs before spending model tokens:
308
369
 
309
370
  \`\`\`bash
371
+ npm run quiver:prepare -- --dry-run
310
372
  npm run quiver:ai:onboard -- --dry-run
311
373
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
312
- npm run quiver:ai:plan -- --phase technical-plan --input acceptance-approved.md --dry-run
313
- npm run quiver:ai:plan -- --phase spec --input technical-plan-approved.md --dry-run
374
+ npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
375
+ npm run quiver:ai:plan -- --phase technical-plan --dry-run
376
+ npm run quiver:ai:review-plan -- --dry-run
377
+ npm run quiver:ai:approve -- --phase technical-plan --version <n>
378
+ npm run quiver:spec:create -- --dry-run
314
379
  \`\`\`
315
380
 
316
381
  When a real spec exists, execute one approved slice at a time:
317
382
 
318
383
  \`\`\`bash
319
- npm run quiver:ai:execute-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run
384
+ npm run quiver:ai:prompt-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run
385
+ npm run quiver:ai:execute-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run --commit
386
+ npm run quiver:ai:execute-plan -- --dry-run --commit --mode delegated
320
387
  \`\`\`
321
388
 
322
389
  ## Project NPM Scripts
@@ -325,13 +392,25 @@ The generated project includes \`quiver:*\` npm scripts that call the Node CLI:
325
392
 
326
393
  \`\`\`bash
327
394
  npm run quiver:analyze
395
+ npm run quiver:prepare -- --dry-run
328
396
  npm run quiver:plan
329
397
  npm run quiver:graph
330
398
  npm run quiver:next
331
399
  npm run quiver:doctor
332
400
  npm run quiver:ai:onboard -- --dry-run
333
401
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
334
- npm run quiver:ai:execute-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run
402
+ npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
403
+ npm run quiver:ai:plan -- --phase technical-plan --dry-run
404
+ npm run quiver:ai:review-plan -- --dry-run
405
+ npm run quiver:ai:approve -- --phase technical-plan --version <n>
406
+ npm run quiver:spec:create -- --dry-run
407
+ npm run quiver:ai:prompt-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run
408
+ npm run quiver:ai:execute-slice -- --slice specs/<spec-slug>/slices/<slice-id>/slice.json --dry-run --commit
409
+ npm run quiver:ai:execute-plan -- --dry-run --commit --mode delegated
410
+ npm run quiver:ai:pr -- --dry-run --input specs/<spec-slug>/pr.md --ssh-host-alias github-work --identity-file ~/.ssh/github-work
411
+ npm run quiver:spec:start -- specs/<spec-slug>
412
+ npm run quiver:spec:status -- specs/<spec-slug>
413
+ npm run quiver:spec:close -- specs/<spec-slug> --dry-run
335
414
  \`\`\`
336
415
 
337
416
  ## Documentation
@@ -388,12 +467,19 @@ Quiver is designed for an AI-first workflow: a planner agent reads the project c
388
467
  Start with dry-runs so you can inspect the provider, role, context pack, and invocation before spending model tokens:
389
468
 
390
469
  \`\`\`bash
470
+ npm run quiver:prepare -- --dry-run
391
471
  npm run quiver:ai:onboard -- --dry-run
392
472
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
393
- npm run quiver:ai:plan -- --phase technical-plan --input acceptance-approved.md --dry-run
394
- npm run quiver:ai:plan -- --phase spec --input technical-plan-approved.md --dry-run
395
- npm run quiver:ai:execute-slice -- --slice specs/${projectSlug}/slices/slice-01/slice.json --dry-run
396
- npm run quiver:ai:pr -- --dry-run --ssh-host-alias github-work --identity-file ~/.ssh/github-work
473
+ npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
474
+ npm run quiver:ai:plan -- --phase technical-plan --dry-run
475
+ npm run quiver:ai:review-plan -- --dry-run
476
+ npm run quiver:ai:approve -- --phase technical-plan --version <n>
477
+ npm run quiver:spec:create -- --dry-run
478
+ npm run quiver:spec:start -- specs/${projectSlug}
479
+ npm run quiver:ai:prompt-slice -- --slice specs/${projectSlug}/slices/slice-01/slice.json --dry-run
480
+ npm run quiver:ai:execute-slice -- --slice specs/${projectSlug}/slices/slice-01/slice.json --dry-run --commit
481
+ npm run quiver:ai:execute-plan -- --dry-run --commit --mode delegated
482
+ npm run quiver:ai:pr -- --dry-run --input specs/${projectSlug}/pr.md --ssh-host-alias github-work --identity-file ~/.ssh/github-work
397
483
  \`\`\`
398
484
 
399
485
  Remove \`--dry-run\` only after the phase output is approved and the local provider CLI is ready.
@@ -404,15 +490,26 @@ The generated project includes \`quiver:*\` npm scripts that call the Node CLI a
404
490
 
405
491
  \`\`\`bash
406
492
  npm run quiver:analyze
493
+ npm run quiver:prepare -- --dry-run
407
494
  npm run quiver:plan
408
495
  npm run quiver:graph
409
496
  npm run quiver:next
410
497
  npm run quiver:doctor
411
498
  npm run quiver:ai:onboard -- --dry-run
412
499
  npm run quiver:ai:plan -- --phase acceptance --input requirements.md --dry-run
413
- npm run quiver:ai:execute-slice -- --slice specs/${projectSlug}/slices/slice-01/slice.json --dry-run
500
+ npm run quiver:ai:approve -- --phase acceptance --input acceptance-approved.md
501
+ npm run quiver:ai:plan -- --phase technical-plan --dry-run
502
+ npm run quiver:ai:review-plan -- --dry-run
503
+ npm run quiver:ai:approve -- --phase technical-plan --version <n>
504
+ npm run quiver:spec:create -- --dry-run
505
+ npm run quiver:ai:prompt-slice -- --slice specs/${projectSlug}/slices/slice-01/slice.json --dry-run
506
+ npm run quiver:ai:execute-slice -- --slice specs/${projectSlug}/slices/slice-01/slice.json --dry-run --commit
507
+ npm run quiver:ai:execute-plan -- --dry-run --commit --mode delegated
414
508
  npm run quiver:ai:doctor -- --dry-run --ssh-host-alias github-work --identity-file ~/.ssh/github-work
415
- npm run quiver:ai:pr -- --dry-run --ssh-host-alias github-work --identity-file ~/.ssh/github-work
509
+ npm run quiver:ai:pr -- --dry-run --input specs/${projectSlug}/pr.md --ssh-host-alias github-work --identity-file ~/.ssh/github-work
510
+ npm run quiver:spec:start -- specs/${projectSlug}
511
+ npm run quiver:spec:status -- specs/${projectSlug}
512
+ npm run quiver:spec:close -- specs/${projectSlug} --dry-run
416
513
  npm run quiver:migrate
417
514
  npm run quiver:start-slice -- specs/${projectSlug}/slices/slice-01/slice.json
418
515
  npm run quiver:check-slice -- specs/${projectSlug}/slices/slice-01/slice.json
@@ -425,7 +522,8 @@ npm run quiver:refresh-active-slices
425
522
 
426
523
  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.
427
524
  The \`quiver:next\` script points to the next ready slice and can auto-start it behind a confirmation prompt.
428
- The \`quiver:ai:*\` scripts standardize planner/executor AI flows. Use dry-run first: onboarding and planning dry-runs do not require provider auth, while \`quiver:ai:pr -- --dry-run\` validates \`gh\`, GitFlow docs, branch/worktree state, and SSH inputs without creating a PR.
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.
526
+ Use \`quiver:spec:create\`, \`quiver:spec:start\`, \`quiver:spec:status\`, and \`quiver:spec:close\` for one spec generation and worktree per spec.
429
527
  Use \`npx create-quiver next --all-ready\` when you want the full ready level instead of a single suggestion.
430
528
  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.
431
529
  \`npm run quiver:migrate\` is only for projects that were already initialized by Quiver.
@@ -502,7 +600,7 @@ Record durable decisions in \`docs/DECISIONS.md\` so future AI agents do not re-
502
600
 
503
601
  ## First Slice Workflow
504
602
 
505
- Use this section only for projects generated with the full compatibility layout. In the default AI-first layout, create real specs and slices with \`npx create-quiver ai plan --phase spec\` after acceptance criteria and the technical plan are approved.
603
+ Use this section only for projects generated with the full compatibility layout. In the default AI-first layout, create real specs and slices with \`npx create-quiver spec create\` after acceptance criteria are approved and the technical plan is reviewed and approved.
506
604
 
507
605
  1. Review or refine specs/${projectSlug}/SPEC.md.
508
606
  2. Create the first slice from specs/${projectSlug}/slices/slice-template/slice.json.
@@ -541,6 +639,19 @@ Use this section only for projects generated with the full compatibility layout.
541
639
  `;
542
640
  }
543
641
 
642
+ function buildFullProfileIndexAppendix(projectSlug) {
643
+ return `## Full Profile Extras
644
+
645
+ - **Multi-agent workflow** - \`./MULTI_AGENT_WORKFLOW.md\`
646
+ - **Quick AI context** - \`./ai/QUICK.md\`
647
+ - **Standard AI context** - \`./ai/STANDARD.md\`
648
+ - **Deep AI context** - \`./ai/DEEP.md\`
649
+ - **Spec starter assets** - \`../specs/${projectSlug}/\`
650
+ - **Tool notes** - \`./tools/\`
651
+ - **Archive** - \`./archive/\`
652
+ `;
653
+ }
654
+
544
655
  function initializeProjectDocs(options) {
545
656
  const {
546
657
  projectRoot,
@@ -598,6 +709,9 @@ function initializeProjectDocs(options) {
598
709
  fs.writeFileSync(internalPaths.gitignorePath, buildQuiverInternalGitignore());
599
710
  operations.push({ source: 'Quiver internal gitignore', destination: '.quiver/.gitignore', result: 'updated' });
600
711
 
712
+ const rootGitignoreResult = mergeRootGitignore(projectRoot);
713
+ operations.push({ source: 'root gitignore defaults', destination: '.gitignore', result: rootGitignoreResult });
714
+
601
715
  if (includeTemplates) {
602
716
  fs.mkdirSync(internalPaths.templatesDir, { recursive: true });
603
717
  fs.cpSync(templateRoot, internalPaths.templatesDir, {
@@ -691,6 +805,17 @@ function initializeProjectDocs(options) {
691
805
  operations.push({ source, destination, result });
692
806
  }
693
807
 
808
+ const indexPath = path.join(projectRoot, 'docs', 'INDEX.md');
809
+ const indexWasCreated = operations.some((operation) => (
810
+ operation.destination === 'docs/INDEX.md'
811
+ && (operation.result === 'created' || operation.result === 'created-with-frontmatter')
812
+ ));
813
+ if (profile === 'full' && indexWasCreated && fs.existsSync(indexPath)) {
814
+ const currentIndex = fs.readFileSync(indexPath, 'utf8').replace(/\s+$/g, '');
815
+ fs.writeFileSync(indexPath, `${currentIndex}\n\n${buildFullProfileIndexAppendix(replacements.projectSlug)}`);
816
+ operations.push({ source: 'full profile index appendix', destination: 'docs/INDEX.md', result: 'updated' });
817
+ }
818
+
694
819
  const binaryCopies = [
695
820
  ['docs/UI_STANDARDS.md', 'docs/UI_STANDARDS.md'],
696
821
  ['docs/MOCK_DATA_GUIDE.md', 'docs/MOCK_DATA_GUIDE.md'],
@@ -765,6 +890,8 @@ function initializeProjectDocs(options) {
765
890
  legacyScripts,
766
891
  migrateMode,
767
892
  profile,
893
+ projectName,
894
+ projectSlug: replacements.projectSlug,
768
895
  });
769
896
  operations.push({ source: 'package.template.json', destination: 'package.json', result: packageResult });
770
897
 
@@ -963,8 +1090,148 @@ function installSelfAsDevDep(projectRoot, version) {
963
1090
  }
964
1091
  }
965
1092
 
1093
+ function normalizeSkippedReason(reason) {
1094
+ if (!reason) {
1095
+ return 'excluded path';
1096
+ }
1097
+
1098
+ if (reason === 'env-file') {
1099
+ return 'env files';
1100
+ }
1101
+
1102
+ if (reason === 'git-metadata') {
1103
+ return '.git metadata';
1104
+ }
1105
+
1106
+ if (reason === 'hidden-directory') {
1107
+ return 'hidden directories';
1108
+ }
1109
+
1110
+ if (reason.startsWith('secret-file:')) {
1111
+ return 'secret files';
1112
+ }
1113
+
1114
+ if (reason.startsWith('unsafe-segment:')) {
1115
+ const segment = reason.slice('unsafe-segment:'.length);
1116
+ const dependencySegments = new Set(['node_modules', '.pnpm-store', '.npm', '.yarn']);
1117
+ const outputSegments = new Set(['dist', 'build', 'coverage', 'out', 'tmp', 'temp', 'cache', '.cache', '.turbo', '.next', '.nuxt', '.parcel-cache', 'generated', 'gen', 'artifacts', 'reports', 'vendor', 'target']);
1118
+
1119
+ if (segment === '.quiver') {
1120
+ return 'local AI state';
1121
+ }
1122
+
1123
+ if (dependencySegments.has(segment)) {
1124
+ return 'dependency folders';
1125
+ }
1126
+
1127
+ if (outputSegments.has(segment)) {
1128
+ return 'generated/output/cache folders';
1129
+ }
1130
+
1131
+ return segment;
1132
+ }
1133
+
1134
+ return reason;
1135
+ }
1136
+
1137
+ function summarizeSkippedPaths(skippedPathDetails = [], skippedPaths = []) {
1138
+ const counts = new Map();
1139
+
1140
+ const items = Array.isArray(skippedPathDetails) && skippedPathDetails.length > 0
1141
+ ? skippedPathDetails
1142
+ : skippedPaths.map((item) => ({ path: item, reason: 'excluded path' }));
1143
+
1144
+ for (const item of items) {
1145
+ const label = normalizeSkippedReason(item.reason);
1146
+ counts.set(label, (counts.get(label) || 0) + 1);
1147
+ }
1148
+
1149
+ return Array.from(counts.entries()).map(([label, count]) => ({ label, count }));
1150
+ }
1151
+
1152
+ function renderAiContextDoc(scan, options = {}) {
1153
+ const projectName = scan?.project?.name || 'Quiver Project';
1154
+ const projectSlug = options.projectSlug || toProjectSlug(projectName);
1155
+ const stack = scan?.stack || {};
1156
+ const commands = scan?.commands || {};
1157
+ const common = commands.common || {};
1158
+ const summaries = summarizeSkippedPaths(scan?.skipped_path_details, scan?.skipped_paths);
1159
+ const risks = Array.isArray(scan?.risks) ? scan.risks : [];
1160
+ const hasReadme = scan?.docs?.has_readme ? 'yes' : 'no';
1161
+ const hasWorkflow = scan?.ci?.has_ci ? 'yes' : 'no';
1162
+ const sourceDirs = Array.isArray(scan?.structure?.source_directories) ? scan.structure.source_directories : [];
1163
+
1164
+ const lines = [];
1165
+ lines.push(`# ${projectName} AI Context`);
1166
+ lines.push('');
1167
+ lines.push('This file is refreshed by `npx create-quiver analyze`.');
1168
+ lines.push('Use `docs/PROJECT_MAP.md` for stack and command details, and `.quiver/scans/PROJECT_SCAN.json` only when raw analyzer data is needed.');
1169
+ lines.push('');
1170
+ lines.push('## Snapshot');
1171
+ lines.push(`- Primary stack: ${stack.primary || 'unknown'}`);
1172
+ lines.push('- Package manager source: `docs/PROJECT_MAP.md`');
1173
+ lines.push(`- Install: ${commands.install || 'not defined'}`);
1174
+ lines.push(`- Dev: ${common.dev || 'not defined'}`);
1175
+ lines.push(`- Build: ${common.build || 'not defined'}`);
1176
+ lines.push(`- Test: ${common.test || 'not defined'}`);
1177
+ lines.push(`- README present: ${hasReadme}`);
1178
+ lines.push(`- GitHub Actions workflows: ${hasWorkflow}`);
1179
+ lines.push(`- Source directories: ${sourceDirs.length > 0 ? sourceDirs.join(', ') : 'none detected'}`);
1180
+ lines.push('');
1181
+ lines.push('## Read First');
1182
+ lines.push('- `docs/PROJECT_MAP.md`');
1183
+ lines.push('- `docs/WORKFLOW.md`');
1184
+ lines.push('- `docs/AI_ONBOARDING_PROMPT.md`');
1185
+ lines.push('- `docs/CONTEXTO.md`');
1186
+ lines.push('- `docs/DECISIONS.md`');
1187
+ lines.push(`- specs/${projectSlug}/SPEC.md`);
1188
+ lines.push('');
1189
+ lines.push('## Assumptions and Missing Info');
1190
+ if (risks.length > 0) {
1191
+ for (const risk of risks) {
1192
+ lines.push(`- ${risk}`);
1193
+ }
1194
+ } else {
1195
+ lines.push('- No major repository signals are missing.');
1196
+ }
1197
+ lines.push('- Do not infer product or business rules that are not present in the repository.');
1198
+ lines.push('');
1199
+ lines.push('## Exclusions');
1200
+ if (summaries.length > 0) {
1201
+ for (const item of summaries) {
1202
+ lines.push(`- ${item.label}: ${item.count}`);
1203
+ }
1204
+ } else {
1205
+ lines.push('- No exclusions were needed.');
1206
+ }
1207
+ lines.push('');
1208
+ lines.push('## Internal Artifacts');
1209
+ lines.push('- Visible source: `docs/PROJECT_MAP.md`');
1210
+ lines.push('- Internal raw scan: `.quiver/scans/PROJECT_SCAN.json`');
1211
+ lines.push('');
1212
+ const body = lines.join('\n');
1213
+ const frontMatter = serializeFrontMatter(buildFrontMatterFields({
1214
+ purpose: 'Agent-facing project context pack',
1215
+ appliesWhen: 'after analyze, onboarding, implementation, review',
1216
+ body,
1217
+ currentDate: options.currentDate || new Date().toISOString().slice(0, 10),
1218
+ }));
1219
+
1220
+ return `${frontMatter}\n\n${body}`;
1221
+ }
1222
+
1223
+ function refreshAiContextDoc(projectRoot, scan, options = {}) {
1224
+ const destinationPath = path.join(projectRoot, 'docs', 'AI_CONTEXT.md');
1225
+ fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
1226
+ fs.writeFileSync(destinationPath, `${renderAiContextDoc(scan, options)}\n`);
1227
+ return destinationPath;
1228
+ }
1229
+
966
1230
  module.exports = {
967
1231
  initializeProjectDocs,
1232
+ refreshAiContextDoc,
1233
+ renderAiContextDoc,
1234
+ summarizeSkippedPaths,
968
1235
  writeFrontMatter,
969
1236
  toProjectSlug,
970
1237
  detectPackageManager,
@@ -22,6 +22,7 @@ const CORE_VISIBLE_DIRECTORIES = ['docs', 'docs/ai', '.quiver', '.quiver/scans']
22
22
  const MINIMAL_VISIBLE_FILES = [
23
23
  'README.md',
24
24
  'AGENTS.md',
25
+ '.gitignore',
25
26
  'docs/AI_CONTEXT.md',
26
27
  'docs/AI_ONBOARDING_PROMPT.md',
27
28
  'docs/COMMANDS.md',
@@ -92,6 +93,7 @@ function quiverInternalPaths(projectRoot) {
92
93
  function buildQuiverInternalGitignore() {
93
94
  return [
94
95
  'cache/',
96
+ 'evidence/',
95
97
  'runs/',
96
98
  'worktrees/',
97
99
  '',
@@ -178,15 +180,28 @@ function resolveInitPackageScripts(profile, options = {}) {
178
180
  const baseScripts = {
179
181
  'quiver:migrate': 'npx create-quiver migrate',
180
182
  'quiver:analyze': 'npx create-quiver analyze',
183
+ 'quiver:flow': 'npx create-quiver flow',
184
+ 'quiver:prepare': 'npx create-quiver prepare',
181
185
  'quiver:plan': 'npx create-quiver plan',
182
186
  'quiver:graph': 'npx create-quiver graph',
183
187
  'quiver:next': 'npx create-quiver next',
184
188
  'quiver:doctor': 'npx create-quiver doctor',
189
+ 'quiver:evidence': 'npx create-quiver evidence',
190
+ 'quiver:ai:agent': 'npx create-quiver ai agent',
185
191
  'quiver:ai:onboard': 'npx create-quiver ai onboard',
192
+ 'quiver:ai:prepare-context': 'npx create-quiver ai prepare-context',
186
193
  'quiver:ai:plan': 'npx create-quiver ai plan',
194
+ 'quiver:ai:review-plan': 'npx create-quiver ai review-plan',
195
+ 'quiver:ai:approve': 'npx create-quiver ai approve',
196
+ 'quiver:ai:prompt-slice': 'npx create-quiver ai prompt-slice',
187
197
  'quiver:ai:execute-slice': 'npx create-quiver ai execute-slice',
198
+ 'quiver:ai:execute-plan': 'npx create-quiver ai execute-plan',
188
199
  'quiver:ai:pr': 'npx create-quiver ai pr',
189
200
  'quiver:ai:doctor': 'npx create-quiver ai doctor',
201
+ 'quiver:spec:create': 'npx create-quiver spec create',
202
+ 'quiver:spec:start': 'npx create-quiver spec start',
203
+ 'quiver:spec:status': 'npx create-quiver spec status',
204
+ 'quiver:spec:close': 'npx create-quiver spec close',
190
205
  'quiver:start-slice': 'npx create-quiver start-slice',
191
206
  'quiver:check-slice': 'npx create-quiver check-slice',
192
207
  'quiver:check-pr': 'npx create-quiver check-pr',
@@ -259,7 +274,17 @@ function buildInitLayout(projectRoot, options = {}) {
259
274
  }
260
275
 
261
276
  for (const file of visibleFiles) {
262
- pushPlannedOperation(operations, projectRoot, file, 'file', file === 'package.json' ? 'update' : 'create', file === 'package.json' ? 'prepare package metadata and scripts' : 'core visible contract file', profile, 'visible');
277
+ const updateMode = file === 'package.json' || file === '.gitignore';
278
+ pushPlannedOperation(
279
+ operations,
280
+ projectRoot,
281
+ file,
282
+ 'file',
283
+ updateMode ? 'update' : 'create',
284
+ updateMode ? 'prepare project metadata or ignored paths' : 'core visible contract file',
285
+ profile,
286
+ 'visible',
287
+ );
263
288
  }
264
289
 
265
290
  if (profile === 'full') {
@@ -4,6 +4,7 @@ const { branchDelete, catFileExists, currentBranch, fetchBranch, fetchRemote, ha
4
4
  const { parseJsonWithComments } = require('./json');
5
5
  const { writeFrontMatter } = require('./init-docs');
6
6
  const { relativePosixPath, resolveTargetRoot } = require('./paths');
7
+ const { ensureSpecSliceZeroComplete } = require('./spec-worktrees');
7
8
  const { activeSlicePath, renderActiveSlice, resolveSliceContext, safeBranchName, toAlias, validateSliceMetaForStart, worktreesRootForRepo } = require('./slice');
8
9
 
9
10
  function ensureDir(dirPath) {
@@ -299,6 +300,11 @@ function startSlice(sliceInput, options = {}) {
299
300
  const repoRoot = runGit(['rev-parse', '--show-toplevel'], process.cwd());
300
301
  const slice = resolveSliceContext(repoRoot, sliceInput);
301
302
  slice.repoRoot = repoRoot;
303
+
304
+ if (!slice.isBaseline) {
305
+ ensureSpecSliceZeroComplete(repoRoot, slice.specDirAbs);
306
+ }
307
+
302
308
  validateSliceMetaForStart(slice);
303
309
 
304
310
  if (slice.status === 'blocked') {
@@ -0,0 +1,117 @@
1
+ const PACKAGE_PREFIX = 'package/';
2
+
3
+ const SAFETY_RULES = [
4
+ {
5
+ code: 'env-file',
6
+ match(relativePath) {
7
+ return /(^|\/)\.env($|[./])/.test(relativePath);
8
+ },
9
+ },
10
+ {
11
+ code: 'npm-credentials',
12
+ match(relativePath) {
13
+ return /(^|\/)\.npmrc$/.test(relativePath) || /(^|\/)\.npm(\/|$)/.test(relativePath);
14
+ },
15
+ },
16
+ {
17
+ code: 'ai-tool-state',
18
+ match(relativePath) {
19
+ return /(^|\/)\.(claude|codex|quiver)(\/|$)/.test(relativePath);
20
+ },
21
+ },
22
+ {
23
+ code: 'worktree-state',
24
+ match(relativePath) {
25
+ return /(^|\/)\.worktrees(\/|$)/.test(relativePath);
26
+ },
27
+ },
28
+ {
29
+ code: 'worktree-context',
30
+ match(relativePath) {
31
+ return /(^|\/)WORKTREE_CONTEXT\.md$/.test(relativePath);
32
+ },
33
+ },
34
+ {
35
+ code: 'demo-output',
36
+ match(relativePath) {
37
+ return relativePath === 'quiver-spec-viewer' || relativePath.startsWith('quiver-spec-viewer/');
38
+ },
39
+ },
40
+ ];
41
+
42
+ function normalizeTarballPath(inputPath) {
43
+ return String(inputPath || '')
44
+ .trim()
45
+ .replace(/\\/g, '/')
46
+ .replace(/^\.\//, '')
47
+ .replace(/\/{2,}/g, '/');
48
+ }
49
+
50
+ function stripPackagePrefix(inputPath) {
51
+ const normalizedPath = normalizeTarballPath(inputPath);
52
+
53
+ if (normalizedPath.startsWith(PACKAGE_PREFIX)) {
54
+ return normalizedPath.slice(PACKAGE_PREFIX.length);
55
+ }
56
+
57
+ return normalizedPath;
58
+ }
59
+
60
+ function collectPackageSafetyViolations(paths) {
61
+ const violations = [];
62
+ const seen = new Set();
63
+
64
+ for (const rawPath of paths || []) {
65
+ const normalizedPath = normalizeTarballPath(rawPath);
66
+ const relativePath = stripPackagePrefix(normalizedPath);
67
+
68
+ for (const rule of SAFETY_RULES) {
69
+ if (!rule.match(relativePath)) {
70
+ continue;
71
+ }
72
+
73
+ const key = `${rule.code}:${normalizedPath}`;
74
+ if (seen.has(key)) {
75
+ continue;
76
+ }
77
+
78
+ seen.add(key);
79
+ violations.push({
80
+ code: rule.code,
81
+ path: normalizedPath,
82
+ });
83
+ }
84
+ }
85
+
86
+ return violations;
87
+ }
88
+
89
+ function formatPackageSafetyViolations(violations) {
90
+ return violations
91
+ .map((violation) => `${violation.path} [${violation.code}]`)
92
+ .join(', ');
93
+ }
94
+
95
+ function assertPackageSafety(paths) {
96
+ const violations = collectPackageSafetyViolations(paths);
97
+
98
+ if (violations.length === 0) {
99
+ return {
100
+ ok: true,
101
+ violations,
102
+ };
103
+ }
104
+
105
+ const error = new Error(`PACKAGE_SAFETY_FAILED: unsafe tarball contents detected: ${formatPackageSafetyViolations(violations)}`);
106
+ error.code = 'PACKAGE_SAFETY_FAILED';
107
+ error.violations = violations;
108
+ throw error;
109
+ }
110
+
111
+ module.exports = {
112
+ assertPackageSafety,
113
+ collectPackageSafetyViolations,
114
+ formatPackageSafetyViolations,
115
+ normalizeTarballPath,
116
+ stripPackagePrefix,
117
+ };