create-quiver 0.10.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 (242) hide show
  1. package/BACKLOG.md +16 -17
  2. package/CHANGELOG.md +78 -0
  3. package/README.md +208 -41
  4. package/README_FOR_AI.md +50 -24
  5. package/ROADMAP.md +34 -11
  6. package/docs/AI_CONTEXT.md.template +2 -0
  7. package/docs/AI_ONBOARDING_PROMPT.md.template +31 -18
  8. package/docs/COMMANDS.md.template +90 -16
  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 +6 -1
  13. package/docs/SUPPORT_MATRIX.md.template +2 -2
  14. package/docs/TROUBLESHOOTING.md.template +50 -0
  15. package/docs/WORKFLOW.md.template +27 -17
  16. package/package.json +27 -4
  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/specs/quiver-v25-ai-first-lifecycle-orchestrator/EVIDENCE_REPORT.md +293 -0
  135. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/EXECUTION_PLAN.md +58 -0
  136. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/SPEC.md +242 -0
  137. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/STATUS.md +35 -0
  138. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/pr.md +77 -0
  139. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +34 -0
  140. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +52 -0
  141. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/slice.json +52 -0
  142. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/CLOSURE_BRIEF.md +36 -0
  143. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/EXECUTION_BRIEF.md +52 -0
  144. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/slice.json +56 -0
  145. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/CLOSURE_BRIEF.md +43 -0
  146. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/EXECUTION_BRIEF.md +54 -0
  147. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/slice.json +52 -0
  148. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/CLOSURE_BRIEF.md +35 -0
  149. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/EXECUTION_BRIEF.md +53 -0
  150. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/slice.json +54 -0
  151. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/CLOSURE_BRIEF.md +34 -0
  152. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/EXECUTION_BRIEF.md +54 -0
  153. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/slice.json +52 -0
  154. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/CLOSURE_BRIEF.md +34 -0
  155. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/EXECUTION_BRIEF.md +54 -0
  156. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/slice.json +53 -0
  157. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/CLOSURE_BRIEF.md +33 -0
  158. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/EXECUTION_BRIEF.md +56 -0
  159. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/slice.json +55 -0
  160. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/CLOSURE_BRIEF.md +33 -0
  161. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/EXECUTION_BRIEF.md +54 -0
  162. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/slice.json +52 -0
  163. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/CLOSURE_BRIEF.md +39 -0
  164. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/EXECUTION_BRIEF.md +56 -0
  165. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/slice.json +53 -0
  166. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/CLOSURE_BRIEF.md +38 -0
  167. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/EXECUTION_BRIEF.md +57 -0
  168. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/slice.json +52 -0
  169. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/CLOSURE_BRIEF.md +39 -0
  170. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/EXECUTION_BRIEF.md +55 -0
  171. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/slice.json +56 -0
  172. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/CLOSURE_BRIEF.md +36 -0
  173. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/EXECUTION_BRIEF.md +54 -0
  174. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/slice.json +53 -0
  175. package/specs/quiver-v26-0121-smoke-hardening/EVIDENCE_REPORT.md +208 -0
  176. package/specs/quiver-v26-0121-smoke-hardening/EXECUTION_PLAN.md +57 -0
  177. package/specs/quiver-v26-0121-smoke-hardening/SPEC.md +137 -0
  178. package/specs/quiver-v26-0121-smoke-hardening/STATUS.md +32 -0
  179. package/specs/quiver-v26-0121-smoke-hardening/pr.md +96 -0
  180. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/CLOSURE_BRIEF.md +35 -0
  181. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/EXECUTION_BRIEF.md +55 -0
  182. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/slice.json +73 -0
  183. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/CLOSURE_BRIEF.md +38 -0
  184. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/EXECUTION_BRIEF.md +51 -0
  185. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/slice.json +76 -0
  186. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/CLOSURE_BRIEF.md +37 -0
  187. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/EXECUTION_BRIEF.md +52 -0
  188. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/slice.json +75 -0
  189. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/CLOSURE_BRIEF.md +37 -0
  190. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/EXECUTION_BRIEF.md +53 -0
  191. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/slice.json +77 -0
  192. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/CLOSURE_BRIEF.md +35 -0
  193. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/EXECUTION_BRIEF.md +52 -0
  194. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/slice.json +77 -0
  195. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/CLOSURE_BRIEF.md +34 -0
  196. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/EXECUTION_BRIEF.md +54 -0
  197. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/slice.json +84 -0
  198. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/CLOSURE_BRIEF.md +35 -0
  199. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/EXECUTION_BRIEF.md +53 -0
  200. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/slice.json +82 -0
  201. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/CLOSURE_BRIEF.md +35 -0
  202. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/EXECUTION_BRIEF.md +55 -0
  203. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/slice.json +92 -0
  204. package/src/create-quiver/commands/ai.js +1060 -37
  205. package/src/create-quiver/commands/demo.js +22 -0
  206. package/src/create-quiver/commands/evidence.js +37 -0
  207. package/src/create-quiver/commands/flow.js +562 -0
  208. package/src/create-quiver/commands/graph.js +19 -4
  209. package/src/create-quiver/commands/next.js +28 -0
  210. package/src/create-quiver/commands/plan.js +9 -6
  211. package/src/create-quiver/commands/prepare.js +236 -0
  212. package/src/create-quiver/commands/spec.js +133 -0
  213. package/src/create-quiver/index.js +1010 -31
  214. package/src/create-quiver/lib/actionable-error.js +27 -0
  215. package/src/create-quiver/lib/agent-profiles.js +148 -0
  216. package/src/create-quiver/lib/ai/context-packs.js +16 -0
  217. package/src/create-quiver/lib/ai/execution-plan.js +377 -11
  218. package/src/create-quiver/lib/ai/executor.js +633 -24
  219. package/src/create-quiver/lib/ai/export-state.js +534 -0
  220. package/src/create-quiver/lib/ai/github.js +279 -0
  221. package/src/create-quiver/lib/ai/onboarding-template.js +578 -0
  222. package/src/create-quiver/lib/ai/plan-review.js +286 -0
  223. package/src/create-quiver/lib/ai/providers.js +5 -3
  224. package/src/create-quiver/lib/ai/run-state.js +414 -0
  225. package/src/create-quiver/lib/ai/safety.js +5 -0
  226. package/src/create-quiver/lib/ai/spec-generator.js +12 -0
  227. package/src/create-quiver/lib/ai/spec-templates.js +80 -11
  228. package/src/create-quiver/lib/approvals.js +369 -0
  229. package/src/create-quiver/lib/demo.js +832 -0
  230. package/src/create-quiver/lib/doctor.js +309 -0
  231. package/src/create-quiver/lib/evidence.js +115 -0
  232. package/src/create-quiver/lib/handoff.js +81 -12
  233. package/src/create-quiver/lib/init-docs.js +302 -17
  234. package/src/create-quiver/lib/init-layout.js +34 -1
  235. package/src/create-quiver/lib/json.js +53 -3
  236. package/src/create-quiver/lib/lifecycle.js +6 -0
  237. package/src/create-quiver/lib/package-safety.js +117 -0
  238. package/src/create-quiver/lib/readiness.js +103 -21
  239. package/src/create-quiver/lib/scope.js +50 -7
  240. package/src/create-quiver/lib/slice-graph.js +138 -37
  241. package/src/create-quiver/lib/slice.js +14 -9
  242. package/src/create-quiver/lib/spec-worktrees.js +363 -0
@@ -1,8 +1,14 @@
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');
7
+ const {
8
+ buildQuiverConfig,
9
+ buildQuiverInternalGitignore,
10
+ resolveInitPackageScripts,
11
+ } = require('./init-layout');
6
12
 
7
13
  const NEW_LAYOUT_REQUIRED_PATHS = [
8
14
  'README.md',
@@ -26,6 +32,13 @@ const LEGACY_LAYOUT_PROBES = [
26
32
  'docs/PROJECT_SCAN.json',
27
33
  ];
28
34
 
35
+ const ROOT_GITIGNORE_DEFAULTS = [
36
+ 'node_modules/',
37
+ '.DS_Store',
38
+ 'dist/',
39
+ 'coverage/',
40
+ ];
41
+
29
42
  function readTextIfExists(filePath) {
30
43
  if (!fs.existsSync(filePath)) {
31
44
  return null;
@@ -34,6 +47,34 @@ function readTextIfExists(filePath) {
34
47
  return fs.readFileSync(filePath, 'utf8');
35
48
  }
36
49
 
50
+ function normalizeIgnorePattern(line) {
51
+ const trimmed = line.trim();
52
+ if (!trimmed || trimmed.startsWith('#')) {
53
+ return trimmed;
54
+ }
55
+
56
+ return trimmed.replace(/\/+$/g, '');
57
+ }
58
+
59
+ function missingLineDefaults(existingText, defaults) {
60
+ const seen = new Set(
61
+ String(existingText || '')
62
+ .split(/\r?\n/)
63
+ .map(normalizeIgnorePattern)
64
+ .filter(Boolean),
65
+ );
66
+
67
+ return defaults.filter((line) => !seen.has(normalizeIgnorePattern(line)));
68
+ }
69
+
70
+ function appendMissingLines(filePath, lines) {
71
+ const existingText = readTextIfExists(filePath) || '';
72
+ const trimmed = existingText.replace(/\s+$/g, '');
73
+ const prefix = trimmed.length > 0 ? `${trimmed}\n` : '';
74
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
75
+ fs.writeFileSync(filePath, `${prefix}${lines.join('\n')}\n`);
76
+ }
77
+
37
78
  function countNonEmptyLines(text) {
38
79
  return String(text || '')
39
80
  .split(/\r?\n/)
@@ -210,6 +251,82 @@ function countStackInfoLeaks(projectRoot) {
210
251
  return leaks;
211
252
  }
212
253
 
254
+ function collectGeneratedMarkdownFiles(projectRoot) {
255
+ const files = [];
256
+ const rootFiles = ['README.md', 'AGENTS.md'];
257
+
258
+ for (const file of rootFiles) {
259
+ const absolutePath = path.join(projectRoot, file);
260
+ if (fs.existsSync(absolutePath)) {
261
+ files.push(absolutePath);
262
+ }
263
+ }
264
+
265
+ const docsDir = path.join(projectRoot, 'docs');
266
+ if (!fs.existsSync(docsDir)) {
267
+ return files;
268
+ }
269
+
270
+ const walk = (dirPath) => {
271
+ for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
272
+ const fullPath = path.join(dirPath, entry.name);
273
+ if (entry.isDirectory()) {
274
+ walk(fullPath);
275
+ } else if (entry.isFile() && entry.name.endsWith('.md')) {
276
+ files.push(fullPath);
277
+ }
278
+ }
279
+ };
280
+
281
+ walk(docsDir);
282
+
283
+ return files;
284
+ }
285
+
286
+ function isExternalLink(target) {
287
+ return /^(?:[a-z][a-z0-9+.-]*:|#)/i.test(target);
288
+ }
289
+
290
+ function normalizeMarkdownLinkTarget(target) {
291
+ return target
292
+ .trim()
293
+ .replace(/^<|>$/g, '')
294
+ .split('#')[0]
295
+ .trim();
296
+ }
297
+
298
+ function collectMissingMarkdownLinks(projectRoot) {
299
+ const missing = [];
300
+ const linkPattern = /!?\[[^\]]*]\(([^)]+)\)/g;
301
+
302
+ for (const filePath of collectGeneratedMarkdownFiles(projectRoot)) {
303
+ const text = readTextIfExists(filePath);
304
+ if (!text) {
305
+ continue;
306
+ }
307
+
308
+ let match;
309
+ while ((match = linkPattern.exec(text)) !== null) {
310
+ const target = normalizeMarkdownLinkTarget(match[1]);
311
+ if (!target || isExternalLink(target)) {
312
+ continue;
313
+ }
314
+
315
+ const resolved = path.resolve(path.dirname(filePath), target);
316
+ const relativeToRoot = path.relative(projectRoot, resolved);
317
+ if (relativeToRoot.startsWith('..') || path.isAbsolute(relativeToRoot)) {
318
+ continue;
319
+ }
320
+
321
+ if (!fs.existsSync(resolved)) {
322
+ missing.push(`${normalizeRelativePath(projectRoot, filePath)} -> ${target}`);
323
+ }
324
+ }
325
+ }
326
+
327
+ return missing;
328
+ }
329
+
213
330
  function collectLayoutReport(projectRoot) {
214
331
  const hasStateMetadata = hasInitializedStateMetadata(readState(projectRoot));
215
332
  const realSlices = readAllSlices(projectRoot);
@@ -276,6 +393,116 @@ function collectLayoutReport(projectRoot) {
276
393
  };
277
394
  }
278
395
 
396
+ function buildDoctorFixPlan(projectRoot) {
397
+ const fixes = [];
398
+ const rootGitignorePath = path.join(projectRoot, '.gitignore');
399
+ const rootGitignoreText = readTextIfExists(rootGitignorePath) || '';
400
+ const missingRootGitignoreLines = missingLineDefaults(rootGitignoreText, ROOT_GITIGNORE_DEFAULTS);
401
+ if (!fs.existsSync(rootGitignorePath)) {
402
+ fixes.push({
403
+ type: 'append-lines',
404
+ path: '.gitignore',
405
+ description: 'Create root .gitignore with safe Quiver defaults.',
406
+ lines: ROOT_GITIGNORE_DEFAULTS,
407
+ });
408
+ } else if (missingRootGitignoreLines.length > 0) {
409
+ fixes.push({
410
+ type: 'append-lines',
411
+ path: '.gitignore',
412
+ description: `Merge missing root .gitignore defaults: ${missingRootGitignoreLines.join(', ')}.`,
413
+ lines: missingRootGitignoreLines,
414
+ });
415
+ }
416
+
417
+ const quiverGitignorePath = path.join(projectRoot, '.quiver', '.gitignore');
418
+ const quiverGitignoreText = readTextIfExists(quiverGitignorePath) || '';
419
+ const quiverDefaults = buildQuiverInternalGitignore().split(/\r?\n/).filter(Boolean);
420
+ const missingQuiverLines = missingLineDefaults(quiverGitignoreText, quiverDefaults);
421
+ if (!fs.existsSync(quiverGitignorePath)) {
422
+ fixes.push({
423
+ type: 'write-json-or-text',
424
+ path: '.quiver/.gitignore',
425
+ description: 'Create internal .quiver/.gitignore for local AI state.',
426
+ content: buildQuiverInternalGitignore(),
427
+ });
428
+ } else if (missingQuiverLines.length > 0) {
429
+ fixes.push({
430
+ type: 'append-lines',
431
+ path: '.quiver/.gitignore',
432
+ description: `Merge missing .quiver/.gitignore defaults: ${missingQuiverLines.join(', ')}.`,
433
+ lines: missingQuiverLines,
434
+ });
435
+ }
436
+
437
+ const configPath = path.join(projectRoot, '.quiver', 'config.json');
438
+ if (!fs.existsSync(configPath)) {
439
+ fixes.push({
440
+ type: 'write-json-or-text',
441
+ path: '.quiver/config.json',
442
+ description: 'Create missing Quiver config metadata.',
443
+ content: `${JSON.stringify(buildQuiverConfig(), null, 2)}\n`,
444
+ });
445
+ }
446
+
447
+ const packageJsonPath = path.join(projectRoot, 'package.json');
448
+ if (fs.existsSync(packageJsonPath)) {
449
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
450
+ const scripts = packageJson.scripts && typeof packageJson.scripts === 'object' ? packageJson.scripts : {};
451
+ const expectedScripts = resolveInitPackageScripts('default');
452
+ const missingScripts = Object.entries(expectedScripts)
453
+ .filter(([name]) => (name.startsWith('quiver:') || name === 'check-handoff') && typeof scripts[name] !== 'string');
454
+
455
+ if (missingScripts.length > 0) {
456
+ fixes.push({
457
+ type: 'merge-package-scripts',
458
+ path: 'package.json',
459
+ description: `Add missing package scripts: ${missingScripts.map(([name]) => name).join(', ')}.`,
460
+ scripts: Object.fromEntries(missingScripts),
461
+ });
462
+ }
463
+ }
464
+
465
+ return fixes;
466
+ }
467
+
468
+ function applyDoctorFixPlan(projectRoot, fixes) {
469
+ for (const fix of fixes) {
470
+ const targetPath = path.join(projectRoot, fix.path);
471
+ if (fix.type === 'append-lines') {
472
+ appendMissingLines(targetPath, fix.lines);
473
+ continue;
474
+ }
475
+
476
+ if (fix.type === 'write-json-or-text') {
477
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
478
+ fs.writeFileSync(targetPath, fix.content);
479
+ continue;
480
+ }
481
+
482
+ if (fix.type === 'merge-package-scripts') {
483
+ const packageJson = JSON.parse(fs.readFileSync(targetPath, 'utf8'));
484
+ packageJson.scripts = {
485
+ ...(packageJson.scripts || {}),
486
+ ...fix.scripts,
487
+ };
488
+ fs.writeFileSync(targetPath, `${JSON.stringify(packageJson, null, 2)}\n`);
489
+ }
490
+ }
491
+ }
492
+
493
+ function formatDoctorFixPlan(fixes, { dryRun = false } = {}) {
494
+ const lines = [dryRun ? 'Quiver doctor fix dry-run' : 'Quiver doctor fix'];
495
+ if (fixes.length === 0) {
496
+ lines.push('- No safe fixes to apply.');
497
+ } else {
498
+ for (const fix of fixes) {
499
+ lines.push(`- ${dryRun ? 'Would update' : 'Updated'} ${fix.path}: ${fix.description}`);
500
+ }
501
+ }
502
+ lines.push('');
503
+ return lines.join('\n');
504
+ }
505
+
279
506
  function collectDoctorReport(projectRoot) {
280
507
  const layout = collectLayoutReport(projectRoot);
281
508
  const warnings = collectDoctorWarnings(projectRoot);
@@ -286,6 +513,75 @@ function collectDoctorReport(projectRoot) {
286
513
  };
287
514
  }
288
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
+
289
585
  function collectDoctorWarnings(projectRoot) {
290
586
  const warnings = [];
291
587
 
@@ -316,11 +612,24 @@ function collectDoctorWarnings(projectRoot) {
316
612
  warnings.push(`stack information appears outside docs/PROJECT_MAP.md: ${leakIssues.join(', ')}`);
317
613
  }
318
614
 
615
+ const missingLinks = collectMissingMarkdownLinks(projectRoot);
616
+ for (const issue of missingLinks) {
617
+ warnings.push(`missing local docs link: ${issue}`);
618
+ }
619
+
620
+ for (const issue of collectEnvironmentWarnings(projectRoot)) {
621
+ warnings.push(issue);
622
+ }
623
+
319
624
  return warnings;
320
625
  }
321
626
 
322
627
  module.exports = {
628
+ applyDoctorFixPlan,
629
+ buildDoctorFixPlan,
323
630
  collectDoctorReport,
631
+ collectEnvironmentWarnings,
324
632
  collectDoctorWarnings,
325
633
  collectLayoutReport,
634
+ formatDoctorFixPlan,
326
635
  };
@@ -0,0 +1,115 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { spawnSync } = require('node:child_process');
4
+
5
+ const DEFAULT_OUTPUT_LIMIT = 4000;
6
+
7
+ function redactSecrets(text) {
8
+ return String(text || '')
9
+ .replace(/(authorization:\s*bearer\s+)[^\s`'"]+/gi, '$1[REDACTED]')
10
+ .replace(/\b((?:api[_-]?key|token|secret|password|passwd|pwd)[A-Z0-9_-]*\s*[:=]\s*)[^\s`'"]+/gi, '$1[REDACTED]')
11
+ .replace(/\b(npm_[A-Za-z0-9]{20,})\b/g, '[REDACTED_NPM_TOKEN]');
12
+ }
13
+
14
+ function truncateText(text, maxLength = DEFAULT_OUTPUT_LIMIT) {
15
+ const value = String(text || '');
16
+ if (value.length <= maxLength) {
17
+ return {
18
+ text: value,
19
+ truncated: false,
20
+ };
21
+ }
22
+
23
+ return {
24
+ text: `${value.slice(0, maxLength)}\n[... truncated ${value.length - maxLength} chars ...]`,
25
+ truncated: true,
26
+ };
27
+ }
28
+
29
+ function quoteCommandPart(value) {
30
+ const part = String(value || '');
31
+ return /\s/.test(part) ? JSON.stringify(part) : part;
32
+ }
33
+
34
+ function formatCommand(commandArgs) {
35
+ return commandArgs.map(quoteCommandPart).join(' ');
36
+ }
37
+
38
+ function defaultEvidencePath(repoRoot, startedAt = new Date()) {
39
+ const stamp = startedAt.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z');
40
+ return path.join(repoRoot, '.quiver', 'evidence', `evidence-${stamp}.md`);
41
+ }
42
+
43
+ function renderEvidenceMarkdown(record) {
44
+ return `# Quiver Evidence
45
+
46
+ - Command: \`${record.command}\`
47
+ - Exit code: ${record.exit_code}
48
+ - Duration ms: ${record.duration_ms}
49
+ - Started at: ${record.started_at}
50
+ - Finished at: ${record.finished_at}
51
+ - Output truncated: ${record.output_truncated ? 'yes' : 'no'}
52
+
53
+ ## Stdout
54
+
55
+ \`\`\`\`text
56
+ ${record.stdout || ''}
57
+ \`\`\`\`
58
+
59
+ ## Stderr
60
+
61
+ \`\`\`\`text
62
+ ${record.stderr || ''}
63
+ \`\`\`\`
64
+ `;
65
+ }
66
+
67
+ function runEvidenceCommand(repoRoot, commandArgs, options = {}) {
68
+ if (!Array.isArray(commandArgs) || commandArgs.length === 0) {
69
+ throw new Error('create-quiver: evidence run requires a command after --');
70
+ }
71
+
72
+ const startedAtDate = new Date();
73
+ const started = Date.now();
74
+ const result = (options.spawnSync || spawnSync)(commandArgs[0], commandArgs.slice(1), {
75
+ cwd: repoRoot,
76
+ encoding: 'utf8',
77
+ shell: false,
78
+ });
79
+ const finishedAtDate = new Date();
80
+ const duration = Date.now() - started;
81
+ const exitCode = typeof result.status === 'number' ? result.status : 1;
82
+ const stdout = truncateText(redactSecrets(result.stdout || ''), options.maxOutput || DEFAULT_OUTPUT_LIMIT);
83
+ const stderr = truncateText(redactSecrets(result.stderr || result.error?.message || ''), options.maxOutput || DEFAULT_OUTPUT_LIMIT);
84
+ const record = {
85
+ command: redactSecrets(formatCommand(commandArgs)),
86
+ duration_ms: duration,
87
+ exit_code: exitCode,
88
+ finished_at: finishedAtDate.toISOString(),
89
+ output_truncated: stdout.truncated || stderr.truncated,
90
+ stderr: stderr.text,
91
+ stdout: stdout.text,
92
+ started_at: startedAtDate.toISOString(),
93
+ };
94
+ const outputPath = options.outputPath
95
+ ? path.resolve(repoRoot, options.outputPath)
96
+ : defaultEvidencePath(repoRoot, startedAtDate);
97
+
98
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
99
+ fs.writeFileSync(outputPath, renderEvidenceMarkdown(record));
100
+
101
+ return {
102
+ exitCode,
103
+ outputPath,
104
+ record,
105
+ };
106
+ }
107
+
108
+ module.exports = {
109
+ DEFAULT_OUTPUT_LIMIT,
110
+ defaultEvidencePath,
111
+ redactSecrets,
112
+ renderEvidenceMarkdown,
113
+ runEvidenceCommand,
114
+ truncateText,
115
+ };
@@ -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
  };