create-quiver 0.9.1 → 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 (245) hide show
  1. package/BACKLOG.md +16 -17
  2. package/CHANGELOG.md +34 -0
  3. package/README.md +419 -330
  4. package/README_FOR_AI.md +93 -56
  5. package/ROADMAP.md +22 -11
  6. package/docs/AI_CONTEXT.md.template +2 -0
  7. package/docs/AI_ONBOARDING_PROMPT.md.template +36 -19
  8. package/docs/COMMANDS.md.template +73 -1
  9. package/docs/CONTEXTO.md.template +2 -0
  10. package/docs/DECISIONS.md.template +1 -0
  11. package/docs/GITFLOW_PR_GUIDE.md.template +11 -0
  12. package/docs/INDEX.md.template +20 -18
  13. package/docs/STANDARD.md.template +1 -1
  14. package/docs/STATUS.md.template +1 -0
  15. package/docs/SUPPORT_MATRIX.md.template +6 -2
  16. package/docs/TROUBLESHOOTING.md.template +79 -1
  17. package/docs/WORKFLOW.md.template +26 -18
  18. package/package.json +24 -2
  19. package/package.template.json +24 -7
  20. package/scripts/check-pr-readiness.sh +1 -1
  21. package/scripts/check-scope.sh +0 -1
  22. package/scripts/check-slice-readiness.sh +3 -4
  23. package/scripts/init-docs.sh +53 -6
  24. package/scripts/package-quiver.sh +18 -2
  25. package/specs/quiver-v20-ai-cli-orchestration/EVIDENCE_REPORT.md +23 -0
  26. package/specs/quiver-v20-ai-cli-orchestration/EXECUTION_PLAN.md +57 -0
  27. package/specs/quiver-v20-ai-cli-orchestration/SPEC.md +202 -0
  28. package/specs/quiver-v20-ai-cli-orchestration/STATUS.md +35 -0
  29. package/specs/quiver-v20-ai-cli-orchestration/pr.md +100 -0
  30. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +30 -0
  31. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
  32. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-00-spec-foundation/slice.json +54 -0
  33. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-01-ai-provider-runner/CLOSURE_BRIEF.md +39 -0
  34. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-01-ai-provider-runner/EXECUTION_BRIEF.md +63 -0
  35. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-01-ai-provider-runner/slice.json +55 -0
  36. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-02-context-packs-token-budget/CLOSURE_BRIEF.md +40 -0
  37. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-02-context-packs-token-budget/EXECUTION_BRIEF.md +60 -0
  38. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-02-context-packs-token-budget/slice.json +54 -0
  39. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-03-ai-phase-gated-planner/CLOSURE_BRIEF.md +43 -0
  40. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-03-ai-phase-gated-planner/EXECUTION_BRIEF.md +62 -0
  41. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-03-ai-phase-gated-planner/slice.json +62 -0
  42. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-04-spec-slice-handoff-pr-generation/CLOSURE_BRIEF.md +36 -0
  43. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-04-spec-slice-handoff-pr-generation/EXECUTION_BRIEF.md +63 -0
  44. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-04-spec-slice-handoff-pr-generation/slice.json +59 -0
  45. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-05-execution-plan-parallel-worktrees/CLOSURE_BRIEF.md +32 -0
  46. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-05-execution-plan-parallel-worktrees/EXECUTION_BRIEF.md +61 -0
  47. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-05-execution-plan-parallel-worktrees/slice.json +59 -0
  48. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-06-ai-execute-slice-scope-enforcement/CLOSURE_BRIEF.md +36 -0
  49. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-06-ai-execute-slice-scope-enforcement/EXECUTION_BRIEF.md +64 -0
  50. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-06-ai-execute-slice-scope-enforcement/slice.json +65 -0
  51. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-07-github-pr-preflight/CLOSURE_BRIEF.md +36 -0
  52. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-07-github-pr-preflight/EXECUTION_BRIEF.md +66 -0
  53. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-07-github-pr-preflight/slice.json +63 -0
  54. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-08-docs-smokes-release-readiness/CLOSURE_BRIEF.md +35 -0
  55. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-08-docs-smokes-release-readiness/EXECUTION_BRIEF.md +64 -0
  56. package/specs/quiver-v20-ai-cli-orchestration/slices/slice-08-docs-smokes-release-readiness/slice.json +77 -0
  57. package/specs/quiver-v21-ai-first-layout/EVIDENCE_REPORT.md +31 -0
  58. package/specs/quiver-v21-ai-first-layout/EXECUTION_PLAN.md +185 -0
  59. package/specs/quiver-v21-ai-first-layout/SPEC.md +212 -0
  60. package/specs/quiver-v21-ai-first-layout/STATUS.md +37 -0
  61. package/specs/quiver-v21-ai-first-layout/pr.md +110 -0
  62. package/specs/quiver-v21-ai-first-layout/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +30 -0
  63. package/specs/quiver-v21-ai-first-layout/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +63 -0
  64. package/specs/quiver-v21-ai-first-layout/slices/slice-00-spec-foundation/slice.json +45 -0
  65. package/specs/quiver-v21-ai-first-layout/slices/slice-01-init-profiles-dry-run/CLOSURE_BRIEF.md +31 -0
  66. package/specs/quiver-v21-ai-first-layout/slices/slice-01-init-profiles-dry-run/EXECUTION_BRIEF.md +59 -0
  67. package/specs/quiver-v21-ai-first-layout/slices/slice-01-init-profiles-dry-run/slice.json +57 -0
  68. package/specs/quiver-v21-ai-first-layout/slices/slice-02-internal-layout-template-resolver/CLOSURE_BRIEF.md +32 -0
  69. package/specs/quiver-v21-ai-first-layout/slices/slice-02-internal-layout-template-resolver/EXECUTION_BRIEF.md +60 -0
  70. package/specs/quiver-v21-ai-first-layout/slices/slice-02-internal-layout-template-resolver/slice.json +58 -0
  71. package/specs/quiver-v21-ai-first-layout/slices/slice-03-generation-profiles-visible-contract/CLOSURE_BRIEF.md +34 -0
  72. package/specs/quiver-v21-ai-first-layout/slices/slice-03-generation-profiles-visible-contract/EXECUTION_BRIEF.md +61 -0
  73. package/specs/quiver-v21-ai-first-layout/slices/slice-03-generation-profiles-visible-contract/slice.json +64 -0
  74. package/specs/quiver-v21-ai-first-layout/slices/slice-04-analyze-scan-relocation/CLOSURE_BRIEF.md +32 -0
  75. package/specs/quiver-v21-ai-first-layout/slices/slice-04-analyze-scan-relocation/EXECUTION_BRIEF.md +58 -0
  76. package/specs/quiver-v21-ai-first-layout/slices/slice-04-analyze-scan-relocation/slice.json +64 -0
  77. package/specs/quiver-v21-ai-first-layout/slices/slice-05-empty-specs-layout-doctor/CLOSURE_BRIEF.md +32 -0
  78. package/specs/quiver-v21-ai-first-layout/slices/slice-05-empty-specs-layout-doctor/EXECUTION_BRIEF.md +60 -0
  79. package/specs/quiver-v21-ai-first-layout/slices/slice-05-empty-specs-layout-doctor/slice.json +65 -0
  80. package/specs/quiver-v21-ai-first-layout/slices/slice-06-legacy-migration-optional-assets/CLOSURE_BRIEF.md +31 -0
  81. package/specs/quiver-v21-ai-first-layout/slices/slice-06-legacy-migration-optional-assets/EXECUTION_BRIEF.md +62 -0
  82. package/specs/quiver-v21-ai-first-layout/slices/slice-06-legacy-migration-optional-assets/slice.json +66 -0
  83. package/specs/quiver-v21-ai-first-layout/slices/slice-07-docs-guidance-alignment/CLOSURE_BRIEF.md +33 -0
  84. package/specs/quiver-v21-ai-first-layout/slices/slice-07-docs-guidance-alignment/EXECUTION_BRIEF.md +61 -0
  85. package/specs/quiver-v21-ai-first-layout/slices/slice-07-docs-guidance-alignment/slice.json +67 -0
  86. package/specs/quiver-v21-ai-first-layout/slices/slice-08-smokes-release-readiness/CLOSURE_BRIEF.md +35 -0
  87. package/specs/quiver-v21-ai-first-layout/slices/slice-08-smokes-release-readiness/EXECUTION_BRIEF.md +66 -0
  88. package/specs/quiver-v21-ai-first-layout/slices/slice-08-smokes-release-readiness/slice.json +62 -0
  89. package/specs/quiver-v22-guided-ai-workflow/EVIDENCE_REPORT.md +58 -0
  90. package/specs/quiver-v22-guided-ai-workflow/EXECUTION_PLAN.md +88 -0
  91. package/specs/quiver-v22-guided-ai-workflow/SPEC.md +228 -0
  92. package/specs/quiver-v22-guided-ai-workflow/STATUS.md +42 -0
  93. package/specs/quiver-v22-guided-ai-workflow/pr.md +104 -0
  94. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +35 -0
  95. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
  96. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/slice.json +51 -0
  97. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/CLOSURE_BRIEF.md +31 -0
  98. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/EXECUTION_BRIEF.md +58 -0
  99. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/slice.json +55 -0
  100. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/CLOSURE_BRIEF.md +30 -0
  101. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/EXECUTION_BRIEF.md +57 -0
  102. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/slice.json +57 -0
  103. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/CLOSURE_BRIEF.md +32 -0
  104. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/EXECUTION_BRIEF.md +56 -0
  105. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/slice.json +56 -0
  106. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/CLOSURE_BRIEF.md +33 -0
  107. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/EXECUTION_BRIEF.md +56 -0
  108. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/slice.json +58 -0
  109. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/CLOSURE_BRIEF.md +32 -0
  110. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/EXECUTION_BRIEF.md +56 -0
  111. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/slice.json +54 -0
  112. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/CLOSURE_BRIEF.md +32 -0
  113. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/EXECUTION_BRIEF.md +58 -0
  114. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/slice.json +57 -0
  115. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/CLOSURE_BRIEF.md +32 -0
  116. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/EXECUTION_BRIEF.md +58 -0
  117. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/slice.json +55 -0
  118. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/CLOSURE_BRIEF.md +32 -0
  119. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/EXECUTION_BRIEF.md +58 -0
  120. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/slice.json +53 -0
  121. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/CLOSURE_BRIEF.md +33 -0
  122. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/EXECUTION_BRIEF.md +59 -0
  123. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/slice.json +59 -0
  124. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +34 -0
  125. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +58 -0
  126. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/slice.json +60 -0
  127. package/specs/quiver-v23-guided-flow-productization/EVIDENCE_REPORT.md +80 -0
  128. package/specs/quiver-v23-guided-flow-productization/EXECUTION_PLAN.md +80 -0
  129. package/specs/quiver-v23-guided-flow-productization/SPEC.md +203 -0
  130. package/specs/quiver-v23-guided-flow-productization/STATUS.md +39 -0
  131. package/specs/quiver-v23-guided-flow-productization/pr.md +119 -0
  132. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +30 -0
  133. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
  134. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/slice.json +51 -0
  135. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/CLOSURE_BRIEF.md +33 -0
  136. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/EXECUTION_BRIEF.md +35 -0
  137. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/slice.json +56 -0
  138. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/CLOSURE_BRIEF.md +31 -0
  139. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/EXECUTION_BRIEF.md +29 -0
  140. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/slice.json +55 -0
  141. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/CLOSURE_BRIEF.md +33 -0
  142. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/EXECUTION_BRIEF.md +29 -0
  143. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/slice.json +54 -0
  144. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/CLOSURE_BRIEF.md +32 -0
  145. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/EXECUTION_BRIEF.md +30 -0
  146. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/slice.json +59 -0
  147. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/CLOSURE_BRIEF.md +31 -0
  148. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/EXECUTION_BRIEF.md +29 -0
  149. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/slice.json +53 -0
  150. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/CLOSURE_BRIEF.md +33 -0
  151. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/EXECUTION_BRIEF.md +30 -0
  152. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/slice.json +54 -0
  153. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/CLOSURE_BRIEF.md +33 -0
  154. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/EXECUTION_BRIEF.md +30 -0
  155. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/slice.json +55 -0
  156. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/CLOSURE_BRIEF.md +32 -0
  157. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/EXECUTION_BRIEF.md +30 -0
  158. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/slice.json +55 -0
  159. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/CLOSURE_BRIEF.md +33 -0
  160. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/EXECUTION_BRIEF.md +34 -0
  161. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/slice.json +57 -0
  162. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +33 -0
  163. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +32 -0
  164. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/slice.json +63 -0
  165. package/specs/quiver-v24-dx-onboarding-hardening/EVIDENCE_REPORT.md +55 -0
  166. package/specs/quiver-v24-dx-onboarding-hardening/EXECUTION_PLAN.md +43 -0
  167. package/specs/quiver-v24-dx-onboarding-hardening/SPEC.md +149 -0
  168. package/specs/quiver-v24-dx-onboarding-hardening/STATUS.md +31 -0
  169. package/specs/quiver-v24-dx-onboarding-hardening/pr.md +76 -0
  170. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +31 -0
  171. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +52 -0
  172. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/slice.json +51 -0
  173. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/CLOSURE_BRIEF.md +38 -0
  174. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/EXECUTION_BRIEF.md +53 -0
  175. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/slice.json +55 -0
  176. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/CLOSURE_BRIEF.md +33 -0
  177. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/EXECUTION_BRIEF.md +50 -0
  178. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/slice.json +52 -0
  179. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/CLOSURE_BRIEF.md +33 -0
  180. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/EXECUTION_BRIEF.md +50 -0
  181. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/slice.json +53 -0
  182. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/CLOSURE_BRIEF.md +33 -0
  183. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/EXECUTION_BRIEF.md +50 -0
  184. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/slice.json +70 -0
  185. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/CLOSURE_BRIEF.md +36 -0
  186. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/EXECUTION_BRIEF.md +49 -0
  187. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/slice.json +52 -0
  188. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/CLOSURE_BRIEF.md +43 -0
  189. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/EXECUTION_BRIEF.md +53 -0
  190. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/slice.json +60 -0
  191. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/CLOSURE_BRIEF.md +32 -0
  192. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/EXECUTION_BRIEF.md +50 -0
  193. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/slice.json +51 -0
  194. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/CLOSURE_BRIEF.md +34 -0
  195. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/EXECUTION_BRIEF.md +52 -0
  196. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/slice.json +54 -0
  197. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/CLOSURE_BRIEF.md +34 -0
  198. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/EXECUTION_BRIEF.md +51 -0
  199. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/slice.json +59 -0
  200. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +33 -0
  201. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +54 -0
  202. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/slice.json +76 -0
  203. package/src/create-quiver/commands/ai.js +915 -0
  204. package/src/create-quiver/commands/demo.js +22 -0
  205. package/src/create-quiver/commands/evidence.js +37 -0
  206. package/src/create-quiver/commands/flow.js +561 -0
  207. package/src/create-quiver/commands/graph.js +14 -1
  208. package/src/create-quiver/commands/next.js +28 -0
  209. package/src/create-quiver/commands/plan.js +6 -3
  210. package/src/create-quiver/commands/prepare.js +236 -0
  211. package/src/create-quiver/commands/spec.js +133 -0
  212. package/src/create-quiver/index.js +1096 -96
  213. package/src/create-quiver/lib/agent-profiles.js +148 -0
  214. package/src/create-quiver/lib/ai/context-packs.js +170 -0
  215. package/src/create-quiver/lib/ai/execution-plan.js +614 -0
  216. package/src/create-quiver/lib/ai/executor.js +682 -0
  217. package/src/create-quiver/lib/ai/github.js +525 -0
  218. package/src/create-quiver/lib/ai/onboarding-template.js +365 -0
  219. package/src/create-quiver/lib/ai/phase-gates.js +72 -0
  220. package/src/create-quiver/lib/ai/plan-review.js +283 -0
  221. package/src/create-quiver/lib/ai/preflight.js +58 -0
  222. package/src/create-quiver/lib/ai/prompt-transport.js +81 -0
  223. package/src/create-quiver/lib/ai/prompts.js +39 -0
  224. package/src/create-quiver/lib/ai/providers.js +315 -0
  225. package/src/create-quiver/lib/ai/safety.js +156 -0
  226. package/src/create-quiver/lib/ai/spec-generator.js +314 -0
  227. package/src/create-quiver/lib/ai/spec-templates.js +715 -0
  228. package/src/create-quiver/lib/approvals.js +350 -0
  229. package/src/create-quiver/lib/demo.js +657 -0
  230. package/src/create-quiver/lib/doctor.js +348 -0
  231. package/src/create-quiver/lib/evidence.js +115 -0
  232. package/src/create-quiver/lib/git.js +21 -0
  233. package/src/create-quiver/lib/init-docs.js +545 -23
  234. package/src/create-quiver/lib/init-layout.js +451 -0
  235. package/src/create-quiver/lib/lifecycle.js +8 -2
  236. package/src/create-quiver/lib/package-safety.js +117 -0
  237. package/src/create-quiver/lib/paths.js +63 -2
  238. package/src/create-quiver/lib/project-scan.js +66 -0
  239. package/src/create-quiver/lib/readiness.js +87 -18
  240. package/src/create-quiver/lib/scope.js +125 -0
  241. package/src/create-quiver/lib/slice-graph.js +7 -0
  242. package/src/create-quiver/lib/slice.js +59 -16
  243. package/src/create-quiver/lib/spec-worktrees.js +349 -0
  244. package/src/create-quiver/lib/state.js +18 -1
  245. package/src/create-quiver/lib/template-resolver.js +74 -0
@@ -3,16 +3,39 @@ const os = require('os');
3
3
  const path = require('path');
4
4
  const { execFileSync } = require('child_process');
5
5
  const { checkHandoff, scaffoldHandoff } = require('./lib/handoff');
6
- const { collectDoctorWarnings } = require('./lib/doctor');
6
+ const {
7
+ applyDoctorFixPlan,
8
+ buildDoctorFixPlan,
9
+ collectDoctorReport,
10
+ formatDoctorFixPlan,
11
+ } = require('./lib/doctor');
12
+ const { runAgent: runAiAgent, runApprovalStatus: runAiApprovalStatus, runApprove: runAiApprove, runDoctor: runAiDoctor, runExecutePlan: runAiExecutePlan, runExecuteSlice: runAiExecuteSlice, runOnboard, runPlan: runAiPlan, runPrepareContext: runAiPrepareContext, runPr: runAiPr, runPromptSlice: runAiPromptSlice, runReviewPlan: runAiReviewPlan } = require('./commands/ai');
13
+ const { runDemo } = require('./commands/demo');
14
+ const { runPrepare } = require('./commands/prepare');
15
+ const { runEvidence } = require('./commands/evidence');
16
+ const { runFlow } = require('./commands/flow');
7
17
  const { runGraph } = require('./commands/graph');
8
18
  const { runNext } = require('./commands/next');
9
19
  const { runPlan } = require('./commands/plan');
10
- const { initializeProjectDocs, installSelfAsDevDep } = require('./lib/init-docs');
20
+ const { runCreateSpec } = require('./commands/spec');
21
+ const { buildInitLayout, formatInitLayoutPlan } = require('./lib/init-layout');
22
+ const { initializeProjectDocs, installSelfAsDevDep, refreshAiContextDoc } = require('./lib/init-docs');
11
23
  const { checkPrReadiness, checkScope, checkSliceReadiness } = require('./lib/readiness');
12
24
  const { cleanupSlice, refreshActiveSlicesBoard, startSlice } = require('./lib/lifecycle');
25
+ const { buildSpecStatus, closeSpecWorktree, formatSpecCloseResult, formatSpecStartResult, formatSpecStatus, startSpecWorktree } = require('./lib/spec-worktrees');
26
+ const { getContextPathExclusionReason } = require('./lib/ai/safety');
13
27
  const { relativePosixPath, resolveTargetRoot } = require('./lib/paths');
28
+ const {
29
+ CURRENT_SCAN_RELATIVE_PATH,
30
+ PROJECT_MAP_RELATIVE_PATH,
31
+ hasProjectScanArtifact,
32
+ projectScanPaths,
33
+ writeProjectScanJson,
34
+ } = require('./lib/project-scan');
35
+ const { resolveTemplateRoot } = require('./lib/template-resolver');
14
36
  const {
15
37
  hasQuiverInitializationEvidence,
38
+ inspectLegacyMigrationLayout,
16
39
  readState,
17
40
  updateStateForAnalyze,
18
41
  updateStateForMigrate,
@@ -24,15 +47,74 @@ function formatError(message) {
24
47
  return `create-quiver: ${message}`;
25
48
  }
26
49
 
50
+ const SUPPORTED_COMMAND_MODES = new Set([
51
+ 'init',
52
+ 'flow',
53
+ 'plan',
54
+ 'graph',
55
+ 'next',
56
+ 'doctor',
57
+ 'prepare',
58
+ 'analyze',
59
+ 'migrate',
60
+ 'start-slice',
61
+ 'check-slice',
62
+ 'check-pr',
63
+ 'check-handoff',
64
+ 'new-handoff',
65
+ 'cleanup-slice',
66
+ 'check-scope',
67
+ 'refresh-active-slices',
68
+ 'spec',
69
+ 'evidence',
70
+ 'demo',
71
+ 'ai',
72
+ ]);
73
+
74
+ const SUPPORTED_AI_COMMANDS = new Set([
75
+ 'agent',
76
+ 'approve',
77
+ 'approval-status',
78
+ 'approvals',
79
+ 'doctor',
80
+ 'execute-plan',
81
+ 'execute-slice',
82
+ 'executor-prompt',
83
+ 'onboard',
84
+ 'plan',
85
+ 'prepare-context',
86
+ 'pr',
87
+ 'prompt-slice',
88
+ 'review-plan',
89
+ ]);
90
+
91
+ const SUPPORTED_SPEC_COMMANDS = new Set(['close', 'create', 'start', 'status']);
92
+ const SUPPORTED_DEMO_COMMANDS = new Set(['create']);
93
+
94
+ function unsupportedCommandMessage(commandName) {
95
+ return [
96
+ `unsupported command: ${commandName}`,
97
+ 'Run: npx create-quiver --help',
98
+ `If you meant to initialize a project, use: npx create-quiver init --name "${commandName}"`,
99
+ 'If this command exists in newer docs, update create-quiver and rerun the command.',
100
+ ].join('\n');
101
+ }
102
+
27
103
  function printUsage() {
28
104
  console.log(`Usage:
29
105
  npx create-quiver [options]
106
+ npx create-quiver init [options]
30
107
  npx create-quiver analyze [options]
108
+ npx create-quiver flow [options]
31
109
  npx create-quiver plan [options]
110
+ npx create-quiver ai <task> [options]
111
+ npx create-quiver ai agent <set|list|show> [role] [options]
112
+ npx create-quiver ai prepare-context [options]
32
113
  npx create-quiver graph [options]
33
114
  npx create-quiver next [options]
34
115
  npx create-quiver migrate [options]
35
116
  npx create-quiver doctor [options]
117
+ npx create-quiver prepare [options]
36
118
  npx create-quiver start-slice [options] <slice.json>
37
119
  npx create-quiver check-slice [options] <slice.json>
38
120
  npx create-quiver check-pr <slice.json>
@@ -41,6 +123,12 @@ function printUsage() {
41
123
  npx create-quiver cleanup-slice [options] <slice.json>
42
124
  npx create-quiver check-scope [options] <slice.json>
43
125
  npx create-quiver refresh-active-slices
126
+ npx create-quiver spec create [options]
127
+ npx create-quiver spec start <spec-dir>
128
+ npx create-quiver spec status <spec-dir>
129
+ npx create-quiver spec close <spec-dir>
130
+ npx create-quiver evidence run [options] -- <command>
131
+ npx create-quiver demo create spec-viewer [options]
44
132
 
45
133
  Options:
46
134
  -n, --name <project-name> Project name to generate
@@ -50,18 +138,63 @@ Options:
50
138
  --show-conflicts Show shared file paths in graph output
51
139
  --level <n> Restrict graph output to one level
52
140
  --json Emit machine-readable JSON
141
+ --include-completed Include completed slices in plan, graph, or next history output
53
142
  --only-ready Show only slices with no pending dependencies
54
143
  --all-ready List every ready slice returned by next
55
144
  --auto-start Prompt for confirmation and run start-slice on next
145
+ --local For check-slice, run structural validation without remote/base checks
56
146
  --unicode Prefer Unicode output when supported
147
+ --minimal Plan or run the minimal init profile
148
+ --full Plan or run the full compatibility init profile
149
+ --legacy-scripts Include legacy Bash wrappers in init profile
150
+ --include-templates Export packaged templates in init profile
151
+ --dry-run Preview init, prepare, spec create, demo, or AI work without executing writes/providers
152
+ --fix For doctor, apply safe non-destructive repairs
153
+ --execute For ai execute-plan, run the planned slices instead of printing commands
154
+ --create For ai pr, create the PR after preflight instead of printing the plan only
155
+ --commit For ai execute-slice, commit validated slice changes after provider, scope, and tests pass
156
+ --allow-dirty For ai execute-slice, allow pre-existing dirty files and ignore them for scope diff
157
+ --mode <name> Execution mode for ai execute-plan (auto, manual, delegated)
158
+ --provider <name> Provider CLI to preflight for prepare or AI commands
159
+ --model <label> Free-form model label for AI agent profiles
160
+ --version <n> Draft version to approve for AI planner phases
161
+ --ssh-host-alias <name> SSH host alias to validate for prepare or AI commands
162
+ --identity-file <path> SSH identity file to validate for prepare or AI commands
163
+ --remote <name> Git remote name for check-slice or AI PR checks
164
+ --base <branch> Base branch for check-slice, ai pr, or spec close (default: main)
165
+ --output <file> Output file for evidence run
166
+ --max-output <n> Maximum stdout/stderr chars per evidence section
167
+ --title <text> Override PR title for ai pr create
57
168
  -y, --yes Skip prompts and use the provided inputs
58
169
  -h, --help Show this help message
59
170
 
60
171
  Examples:
172
+ npx create-quiver init --name "My Project"
173
+ npx create-quiver init --name "My Project" --dry-run
61
174
  npx create-quiver --name "My Project"
62
175
  npx create-quiver --name "My Project" --dir ./my-project
176
+ cd ./my-project && npx create-quiver flow
63
177
  cd ./my-project && npx create-quiver analyze
64
178
  cd ./my-project && npx create-quiver plan --json
179
+ cd ./my-project && npx create-quiver ai onboard --dry-run
180
+ cd ./my-project && npx create-quiver ai prepare-context --dry-run
181
+ cd ./my-project && npx create-quiver ai agent set planner --provider codex --model gpt-5.5
182
+ cd ./my-project && npx create-quiver ai agent list
183
+ cd ./my-project && npx create-quiver ai plan --phase acceptance --input requirements.md --dry-run
184
+ cd ./my-project && npx create-quiver ai approve --phase acceptance --input acceptance.md
185
+ cd ./my-project && npx create-quiver ai plan --phase technical-plan --dry-run
186
+ cd ./my-project && npx create-quiver ai review-plan --dry-run
187
+ cd ./my-project && npx create-quiver ai approve --phase technical-plan --version 1
188
+ cd ./my-project && npx create-quiver spec create --dry-run
189
+ cd ./my-project && npx create-quiver ai approvals
190
+ cd ./my-project && npx create-quiver ai prompt-slice --slice specs/my-project/slices/slice-01/slice.json --dry-run
191
+ cd ./my-project && npx create-quiver ai execute-slice --slice specs/my-project/slices/slice-01/slice.json --dry-run
192
+ cd ./my-project && npx create-quiver ai execute-slice --slice specs/my-project/slices/slice-01/slice.json --commit
193
+ cd ./my-project && npx create-quiver ai execute-plan --dry-run --commit
194
+ cd ./my-project && npx create-quiver ai doctor --dry-run --ssh-host-alias github-work --identity-file ~/.ssh/github-work
195
+ cd ./my-project && npx create-quiver ai pr --dry-run --ssh-host-alias github-work --identity-file ~/.ssh/github-work
196
+ cd ./my-project && npx create-quiver ai pr --create --input specs/my-project/pr.md --ssh-host-alias github-work --identity-file ~/.ssh/github-work
197
+ cd ./my-project && npx create-quiver prepare --dry-run --provider codex --ssh-host-alias github-work --identity-file ~/.ssh/github-work
65
198
  cd ./my-project && npx create-quiver graph --show-conflicts
66
199
  cd ./my-project && npx create-quiver graph --format mermaid
67
200
  cd ./my-project && npx create-quiver graph --format dot
@@ -78,6 +211,11 @@ Examples:
78
211
  cd ./my-project && npx create-quiver cleanup-slice specs/my-project/slices/slice-01/slice.json
79
212
  cd ./my-project && npx create-quiver check-scope specs/my-project/slices/slice-01/slice.json
80
213
  cd ./my-project && npx create-quiver refresh-active-slices
214
+ cd ./my-project && npx create-quiver spec start specs/my-project
215
+ cd ./my-project && npx create-quiver spec status specs/my-project
216
+ cd ./my-project && npx create-quiver spec close specs/my-project --dry-run
217
+ cd ./my-project && npx create-quiver evidence run -- npm test
218
+ cd ./my-project && npx create-quiver demo create spec-viewer --dry-run
81
219
  node bin/create-quiver.js doctor --dir ./my-project
82
220
  `);
83
221
  }
@@ -86,17 +224,22 @@ function parseArgs(argv) {
86
224
  const result = {
87
225
  help: false,
88
226
  force: false,
227
+ explicitInit: false,
89
228
  mode: 'init',
90
229
  allowDraft: false,
230
+ checkSliceLocal: false,
91
231
  closeBaseline: false,
92
232
  discard: false,
233
+ doctorFix: false,
93
234
  dryRun: false,
94
235
  gate: 'execution',
95
236
  projectName: '',
96
237
  targetDir: '.',
238
+ targetDirExplicit: false,
97
239
  strict: false,
98
240
  strictOverlap: false,
99
241
  json: false,
242
+ includeCompleted: false,
100
243
  onlyReady: false,
101
244
  allReady: false,
102
245
  autoStart: false,
@@ -105,13 +248,60 @@ function parseArgs(argv) {
105
248
  showConflicts: false,
106
249
  level: null,
107
250
  unicode: false,
251
+ aiCommand: '',
252
+ aiAgentCommand: '',
253
+ aiAgentRole: '',
254
+ aiPhase: 'acceptance',
255
+ aiProvider: 'codex',
256
+ aiProviderExplicit: false,
257
+ aiModel: '',
258
+ aiLabel: '',
259
+ aiVersion: '',
260
+ prepareProvider: '',
261
+ aiRole: '',
262
+ aiContext: '',
263
+ aiInput: '',
264
+ aiSlice: '',
265
+ aiTimeout: null,
266
+ aiCommit: false,
267
+ aiAllowDirty: false,
268
+ aiExecute: false,
269
+ aiExecutionMode: 'auto',
270
+ aiCreate: false,
271
+ aiBaseBranch: 'main',
272
+ baseBranchExplicit: false,
273
+ aiTitle: '',
274
+ aiSshHostAlias: '',
275
+ aiIdentityFile: '',
276
+ aiRemote: 'origin',
277
+ initFull: false,
278
+ initIncludeTemplates: false,
279
+ initLegacyScripts: false,
280
+ initMinimal: false,
281
+ specCommand: '',
282
+ demoCommand: '',
283
+ demoName: '',
284
+ evidenceCommand: '',
285
+ evidenceArgs: [],
286
+ evidenceOutput: '',
287
+ evidenceMaxOutput: null,
108
288
  };
109
289
 
110
290
  const args = [...argv];
111
- const commandModes = new Set(['plan', 'graph', 'next', 'doctor', 'analyze', 'migrate', 'start-slice', 'check-slice', 'check-pr', 'check-handoff', 'new-handoff', 'cleanup-slice', 'check-scope', 'refresh-active-slices']);
112
- if (commandModes.has(args[0])) {
291
+ if (SUPPORTED_COMMAND_MODES.has(args[0])) {
113
292
  result.mode = args[0];
293
+ result.explicitInit = args[0] === 'init';
114
294
  args.shift();
295
+ if (result.mode === 'spec') {
296
+ result.specCommand = args.shift() || '';
297
+ }
298
+ if (result.mode === 'evidence') {
299
+ result.evidenceCommand = args.shift() || '';
300
+ }
301
+ if (result.mode === 'demo') {
302
+ result.demoCommand = args.shift() || '';
303
+ result.demoName = args.shift() || '';
304
+ }
115
305
  } else if (args[0] === '--analyze') {
116
306
  result.mode = 'analyze';
117
307
  args.shift();
@@ -127,6 +317,8 @@ function parseArgs(argv) {
127
317
  } else if (args[0] === '--new-handoff') {
128
318
  result.mode = 'new-handoff';
129
319
  args.shift();
320
+ } else if (args[0] && !args[0].startsWith('-')) {
321
+ throw new Error(formatError(unsupportedCommandMessage(args[0])));
130
322
  }
131
323
 
132
324
  const positional = [];
@@ -134,6 +326,11 @@ function parseArgs(argv) {
134
326
  for (let index = 0; index < args.length; index += 1) {
135
327
  const arg = args[index];
136
328
 
329
+ if (arg === '--') {
330
+ result.evidenceArgs = args.slice(index + 1);
331
+ break;
332
+ }
333
+
137
334
  if (arg === '-h' || arg === '--help') {
138
335
  result.help = true;
139
336
  continue;
@@ -174,6 +371,11 @@ function parseArgs(argv) {
174
371
  continue;
175
372
  }
176
373
 
374
+ if (arg === '--local') {
375
+ result.checkSliceLocal = true;
376
+ continue;
377
+ }
378
+
177
379
  if (arg === '--close-baseline') {
178
380
  result.closeBaseline = true;
179
381
  continue;
@@ -184,11 +386,65 @@ function parseArgs(argv) {
184
386
  continue;
185
387
  }
186
388
 
389
+ if (arg === '--fix') {
390
+ result.doctorFix = true;
391
+ continue;
392
+ }
393
+
187
394
  if (arg === '--dry-run') {
188
395
  result.dryRun = true;
189
396
  continue;
190
397
  }
191
398
 
399
+ if (arg === '--commit') {
400
+ result.aiCommit = true;
401
+ continue;
402
+ }
403
+
404
+ if (arg === '--execute') {
405
+ result.aiExecute = true;
406
+ continue;
407
+ }
408
+
409
+ if (arg === '--create') {
410
+ result.aiCreate = true;
411
+ continue;
412
+ }
413
+
414
+ if (arg === '--mode') {
415
+ const value = args[++index];
416
+ if (!value) {
417
+ throw new Error(formatError('missing value for --mode'));
418
+ }
419
+ result.aiExecutionMode = value;
420
+ continue;
421
+ }
422
+
423
+ if (arg === '--allow-dirty') {
424
+ result.aiAllowDirty = true;
425
+ continue;
426
+ }
427
+
428
+ if (arg === '--minimal') {
429
+ result.initMinimal = true;
430
+ continue;
431
+ }
432
+
433
+ if (arg === '--full') {
434
+ result.initFull = true;
435
+ continue;
436
+ }
437
+
438
+ if (arg === '--legacy-scripts') {
439
+ result.initLegacyScripts = true;
440
+ continue;
441
+ }
442
+
443
+ if (arg === '--include-templates') {
444
+ result.initIncludeTemplates = true;
445
+ continue;
446
+ }
447
+
192
448
  if (arg === '--strict') {
193
449
  result.strict = true;
194
450
  continue;
@@ -204,6 +460,11 @@ function parseArgs(argv) {
204
460
  continue;
205
461
  }
206
462
 
463
+ if (arg === '--include-completed') {
464
+ result.includeCompleted = true;
465
+ continue;
466
+ }
467
+
207
468
  if (arg === '--show-conflicts') {
208
469
  result.showConflicts = true;
209
470
  continue;
@@ -251,6 +512,170 @@ function parseArgs(argv) {
251
512
  continue;
252
513
  }
253
514
 
515
+ if (arg === '--provider') {
516
+ const value = args[++index];
517
+ if (!value) {
518
+ throw new Error(formatError('missing value for --provider'));
519
+ }
520
+ result.aiProvider = value;
521
+ result.prepareProvider = value;
522
+ result.aiProviderExplicit = true;
523
+ continue;
524
+ }
525
+
526
+ if (arg === '--model') {
527
+ const value = args[++index];
528
+ if (!value) {
529
+ throw new Error(formatError('missing value for --model'));
530
+ }
531
+ result.aiModel = value;
532
+ continue;
533
+ }
534
+
535
+ if (arg === '--label') {
536
+ const value = args[++index];
537
+ if (!value) {
538
+ throw new Error(formatError('missing value for --label'));
539
+ }
540
+ result.aiLabel = value;
541
+ continue;
542
+ }
543
+
544
+ if (arg === '--version') {
545
+ const value = args[++index];
546
+ if (!value) {
547
+ throw new Error(formatError('missing value for --version'));
548
+ }
549
+ result.aiVersion = value;
550
+ continue;
551
+ }
552
+
553
+ if (arg === '--role') {
554
+ const value = args[++index];
555
+ if (!value) {
556
+ throw new Error(formatError('missing value for --role'));
557
+ }
558
+ result.aiRole = value;
559
+ continue;
560
+ }
561
+
562
+ if (arg === '--context') {
563
+ const value = args[++index];
564
+ if (!value) {
565
+ throw new Error(formatError('missing value for --context'));
566
+ }
567
+ result.aiContext = value;
568
+ continue;
569
+ }
570
+
571
+ if (arg === '--input') {
572
+ const value = args[++index];
573
+ if (!value) {
574
+ throw new Error(formatError('missing value for --input'));
575
+ }
576
+ result.aiInput = value;
577
+ continue;
578
+ }
579
+
580
+ if (arg === '--slice') {
581
+ const value = args[++index];
582
+ if (!value) {
583
+ throw new Error(formatError('missing value for --slice'));
584
+ }
585
+ result.aiSlice = value;
586
+ continue;
587
+ }
588
+
589
+ if (arg === '--timeout') {
590
+ const value = args[++index];
591
+ if (typeof value === 'undefined') {
592
+ throw new Error(formatError('missing value for --timeout'));
593
+ }
594
+ const parsed = Number.parseInt(value, 10);
595
+ if (!Number.isInteger(parsed) || parsed <= 0) {
596
+ throw new Error(formatError('invalid value for --timeout'));
597
+ }
598
+ result.aiTimeout = parsed;
599
+ continue;
600
+ }
601
+
602
+ if (arg === '--ssh-host-alias') {
603
+ const value = args[++index];
604
+ if (!value) {
605
+ throw new Error(formatError('missing value for --ssh-host-alias'));
606
+ }
607
+ result.aiSshHostAlias = value;
608
+ continue;
609
+ }
610
+
611
+ if (arg === '--identity-file') {
612
+ const value = args[++index];
613
+ if (!value) {
614
+ throw new Error(formatError('missing value for --identity-file'));
615
+ }
616
+ result.aiIdentityFile = value;
617
+ continue;
618
+ }
619
+
620
+ if (arg === '--remote') {
621
+ const value = args[++index];
622
+ if (!value) {
623
+ throw new Error(formatError('missing value for --remote'));
624
+ }
625
+ result.aiRemote = value;
626
+ continue;
627
+ }
628
+
629
+ if (arg === '--base') {
630
+ const value = args[++index];
631
+ if (!value) {
632
+ throw new Error(formatError('missing value for --base'));
633
+ }
634
+ result.aiBaseBranch = value;
635
+ result.baseBranchExplicit = true;
636
+ continue;
637
+ }
638
+
639
+ if (arg === '--output') {
640
+ const value = args[++index];
641
+ if (!value) {
642
+ throw new Error(formatError('missing value for --output'));
643
+ }
644
+ result.evidenceOutput = value;
645
+ continue;
646
+ }
647
+
648
+ if (arg === '--max-output') {
649
+ const value = args[++index];
650
+ if (typeof value === 'undefined') {
651
+ throw new Error(formatError('missing value for --max-output'));
652
+ }
653
+ const parsed = Number.parseInt(value, 10);
654
+ if (!Number.isInteger(parsed) || parsed <= 0) {
655
+ throw new Error(formatError('invalid value for --max-output'));
656
+ }
657
+ result.evidenceMaxOutput = parsed;
658
+ continue;
659
+ }
660
+
661
+ if (arg === '--title') {
662
+ const value = args[++index];
663
+ if (!value) {
664
+ throw new Error(formatError('missing value for --title'));
665
+ }
666
+ result.aiTitle = value;
667
+ continue;
668
+ }
669
+
670
+ if (arg === '--phase') {
671
+ const value = args[++index];
672
+ if (!value) {
673
+ throw new Error(formatError('missing value for --phase'));
674
+ }
675
+ result.aiPhase = value;
676
+ continue;
677
+ }
678
+
254
679
  if (arg === '--spec') {
255
680
  const value = args[++index];
256
681
  if (!value) {
@@ -284,6 +709,7 @@ function parseArgs(argv) {
284
709
  throw new Error(formatError('missing value for --dir'));
285
710
  }
286
711
  result.targetDir = value;
712
+ result.targetDirExplicit = true;
287
713
  continue;
288
714
  }
289
715
 
@@ -306,10 +732,78 @@ function parseArgs(argv) {
306
732
  if (positional.length > 0) {
307
733
  throw new Error(formatError('plan does not accept positional arguments; use --spec <slug>'));
308
734
  }
735
+ } else if (result.mode === 'flow') {
736
+ if (positional.length > 0) {
737
+ throw new Error(formatError('flow does not accept positional arguments'));
738
+ }
739
+ } else if (result.mode === 'ai') {
740
+ if (!result.aiCommand && positional.length > 0) {
741
+ result.aiCommand = positional.shift();
742
+ }
743
+ if (result.aiCommand === 'agent') {
744
+ if (!result.aiAgentCommand && positional.length > 0) {
745
+ result.aiAgentCommand = positional.shift();
746
+ }
747
+ if (!result.aiAgentRole && positional.length > 0) {
748
+ result.aiAgentRole = positional.shift();
749
+ }
750
+ }
751
+ if (positional.length > 0) {
752
+ throw new Error(formatError('ai does not accept extra positional arguments'));
753
+ }
754
+ } else if (result.mode === 'prepare') {
755
+ if (positional.length > 0) {
756
+ throw new Error(formatError('prepare does not accept positional arguments'));
757
+ }
309
758
  } else if (result.mode === 'refresh-active-slices') {
310
759
  if (positional.length > 0) {
311
760
  throw new Error(formatError('refresh-active-slices does not accept positional arguments'));
312
761
  }
762
+ } else if (result.mode === 'spec') {
763
+ if (!result.specCommand && positional.length > 0) {
764
+ result.specCommand = positional.shift();
765
+ }
766
+ if (!result.specCommand) {
767
+ throw new Error(formatError('missing spec subcommand. Use: npx create-quiver spec <create|start|status|close>'));
768
+ }
769
+ if (result.specCommand !== 'create' && positional.length > 0) {
770
+ result.targetDir = positional.shift();
771
+ }
772
+ if (result.specCommand === 'create' && positional.length > 0) {
773
+ throw new Error(formatError('spec create does not accept positional arguments; use --input <file> or --spec <slug>'));
774
+ }
775
+ } else if (result.mode === 'evidence') {
776
+ if (!result.evidenceCommand && positional.length > 0) {
777
+ result.evidenceCommand = positional.shift();
778
+ }
779
+ if (!result.evidenceCommand) {
780
+ throw new Error(formatError('missing evidence subcommand. Use: npx create-quiver evidence run -- <command>'));
781
+ }
782
+ if (result.evidenceCommand !== 'run') {
783
+ throw new Error(formatError(`unsupported evidence subcommand: ${result.evidenceCommand}. Supported tasks: run`));
784
+ }
785
+ if (positional.length > 0) {
786
+ throw new Error(formatError('evidence run does not accept positional arguments before --'));
787
+ }
788
+ } else if (result.mode === 'demo') {
789
+ if (!result.demoCommand && positional.length > 0) {
790
+ result.demoCommand = positional.shift();
791
+ }
792
+ if (!result.demoName && positional.length > 0) {
793
+ result.demoName = positional.shift();
794
+ }
795
+ if (!result.demoCommand) {
796
+ throw new Error(formatError('missing demo subcommand. Use: npx create-quiver demo create spec-viewer'));
797
+ }
798
+ if (!SUPPORTED_DEMO_COMMANDS.has(result.demoCommand)) {
799
+ throw new Error(formatError(`unsupported demo subcommand: ${result.demoCommand}. Supported tasks: create`));
800
+ }
801
+ if (result.demoName !== 'spec-viewer') {
802
+ throw new Error(formatError(`unsupported demo: ${result.demoName || '(missing)'}. Supported demos: spec-viewer`));
803
+ }
804
+ if (positional.length > 0) {
805
+ throw new Error(formatError('demo create spec-viewer does not accept positional target paths; use --dir <target-dir>'));
806
+ }
313
807
  } else {
314
808
  if (positional.length > 0) {
315
809
  result.targetDir = positional.shift();
@@ -340,6 +834,43 @@ function runCommand(command, args, options = {}) {
340
834
  });
341
835
  }
342
836
 
837
+ function copyPackageFallback(packageRoot, tempRoot) {
838
+ const fallbackDir = path.join(tempRoot, 'package-fallback');
839
+ const ignoredRoots = new Set([
840
+ '.git',
841
+ '.worktrees',
842
+ 'examples',
843
+ 'package-lock.json',
844
+ 'tests',
845
+ ]);
846
+ const ignoredPrefixes = [
847
+ 'scripts/ci',
848
+ 'specs/quiver-v01',
849
+ 'specs/quiver-v02-bootstrap-hardening',
850
+ 'specs/quiver-v03-adoption-verification',
851
+ 'specs/quiver-v04-zero-friction-installation',
852
+ ];
853
+
854
+ fs.cpSync(packageRoot, fallbackDir, {
855
+ recursive: true,
856
+ filter: (sourcePath) => {
857
+ const relativePath = relativePosixPath(packageRoot, sourcePath);
858
+ if (!relativePath || relativePath === '.') {
859
+ return true;
860
+ }
861
+
862
+ const firstSegment = relativePath.split('/')[0];
863
+ if (ignoredRoots.has(firstSegment) || ignoredRoots.has(relativePath)) {
864
+ return false;
865
+ }
866
+
867
+ return !ignoredPrefixes.some((prefix) => relativePath === prefix || relativePath.startsWith(`${prefix}/`));
868
+ },
869
+ });
870
+
871
+ return fallbackDir;
872
+ }
873
+
343
874
  function packTemplate(packageRoot, tempRoot) {
344
875
  const packDir = path.join(tempRoot, 'pack');
345
876
  const extractDir = path.join(tempRoot, 'extract');
@@ -349,24 +880,32 @@ function packTemplate(packageRoot, tempRoot) {
349
880
  fs.mkdirSync(extractDir, { recursive: true });
350
881
  fs.mkdirSync(npmCache, { recursive: true });
351
882
 
352
- const packOutput = runCommand('npm', ['pack', '--json', '--pack-destination', packDir], {
353
- cwd: packageRoot,
354
- env: {
355
- ...process.env,
356
- npm_config_cache: npmCache,
357
- },
358
- });
883
+ try {
884
+ const packOutput = runCommand('npm', ['pack', '--json', '--pack-destination', packDir], {
885
+ cwd: packageRoot,
886
+ env: {
887
+ ...process.env,
888
+ npm_config_cache: npmCache,
889
+ },
890
+ });
359
891
 
360
- const packInfo = JSON.parse(packOutput.trim());
361
- const tarballPath = path.join(packDir, packInfo[0].filename);
892
+ const packInfo = JSON.parse(packOutput.trim());
893
+ const tarballPath = path.join(packDir, packInfo[0].filename);
362
894
 
363
- if (!fs.existsSync(tarballPath)) {
364
- throw new Error(formatError(`pack output not found at ${tarballPath}`));
365
- }
895
+ if (!fs.existsSync(tarballPath)) {
896
+ throw new Error(formatError(`pack output not found at ${tarballPath}`));
897
+ }
898
+
899
+ runCommand('tar', ['-xzf', tarballPath, '-C', extractDir]);
366
900
 
367
- runCommand('tar', ['-xzf', tarballPath, '-C', extractDir]);
901
+ return path.join(extractDir, 'package');
902
+ } catch (error) {
903
+ if (error && error.code === 'ENOENT') {
904
+ return copyPackageFallback(packageRoot, tempRoot);
905
+ }
368
906
 
369
- return path.join(extractDir, 'package');
907
+ throw error;
908
+ }
370
909
  }
371
910
 
372
911
  function ensureDir(dirPath) {
@@ -385,6 +924,10 @@ function copyTemplate(templateRoot, targetDir) {
385
924
  return docsTemplateDir;
386
925
  }
387
926
 
927
+ function exportTemplatesToLegacyRoot(templateRoot, targetDir) {
928
+ return copyTemplate(templateRoot, targetDir);
929
+ }
930
+
388
931
  function mergeDirectoryTree(sourceDir, targetDir) {
389
932
  if (!fs.existsSync(sourceDir)) {
390
933
  return;
@@ -399,12 +942,22 @@ function mergeDirectoryTree(sourceDir, targetDir) {
399
942
  });
400
943
  }
401
944
 
402
- function runInitDocs(repoRoot, projectName) {
945
+ function runInitDocs(repoRoot, projectName, options = {}) {
946
+ const templateRoot = options.templateRoot
947
+ ? { path: options.templateRoot }
948
+ : resolveTemplateRoot(repoRoot, {
949
+ packageRoot: path.resolve(__dirname, '../..'),
950
+ });
951
+
403
952
  initializeProjectDocs({
404
953
  projectRoot: repoRoot,
405
954
  projectName,
406
955
  cliVersion: CLI_VERSION,
956
+ includeTemplates: options.includeTemplates === true,
957
+ legacyScripts: options.legacyScripts === true,
407
958
  migrateMode: false,
959
+ profile: options.profile || 'default',
960
+ templateRoot: templateRoot.path,
408
961
  });
409
962
  }
410
963
 
@@ -426,6 +979,10 @@ function assertFilesExist(root, relativePaths) {
426
979
  }
427
980
 
428
981
  function assertExecutablesExist(root, relativePaths) {
982
+ if (process.platform === 'win32') {
983
+ return [];
984
+ }
985
+
429
986
  return relativePaths.filter((relativePath) => {
430
987
  const absolutePath = path.join(root, relativePath);
431
988
 
@@ -472,6 +1029,43 @@ function escapeMarkdownCell(value) {
472
1029
  return String(value).replace(/\|/g, '\\|');
473
1030
  }
474
1031
 
1032
+ function summarizeSkippedPaths(scan) {
1033
+ const details = Array.isArray(scan.skipped_path_details) && scan.skipped_path_details.length > 0
1034
+ ? scan.skipped_path_details
1035
+ : (Array.isArray(scan.skipped_paths) ? scan.skipped_paths.map((item) => ({ reason: 'excluded path', path: item })) : []);
1036
+ const counts = new Map();
1037
+ const dependencySegments = new Set(['node_modules', '.pnpm-store', '.npm', '.yarn']);
1038
+ const outputSegments = new Set(['dist', 'build', 'coverage', 'out', 'tmp', 'temp', 'cache', '.cache', '.turbo', '.next', '.nuxt', '.parcel-cache', 'generated', 'gen', 'artifacts', 'reports', 'vendor', 'target']);
1039
+
1040
+ for (const item of details) {
1041
+ const reason = item.reason || 'excluded path';
1042
+ let label = reason;
1043
+ if (reason === 'env-file') {
1044
+ label = 'env files';
1045
+ } else if (reason === 'git-metadata') {
1046
+ label = 'git metadata';
1047
+ } else if (reason === 'hidden-directory') {
1048
+ label = 'hidden directories';
1049
+ } else if (reason.startsWith('secret-file:')) {
1050
+ label = 'secret files';
1051
+ } else if (reason.startsWith('unsafe-segment:')) {
1052
+ const segment = reason.slice('unsafe-segment:'.length);
1053
+ if (segment === '.quiver') {
1054
+ label = 'local AI state';
1055
+ } else if (dependencySegments.has(segment)) {
1056
+ label = 'dependency folders';
1057
+ } else if (outputSegments.has(segment)) {
1058
+ label = 'generated/output/cache folders';
1059
+ } else {
1060
+ label = segment;
1061
+ }
1062
+ }
1063
+ counts.set(label, (counts.get(label) || 0) + 1);
1064
+ }
1065
+
1066
+ return Array.from(counts.entries()).map(([reason, count]) => ({ reason, count }));
1067
+ }
1068
+
475
1069
  function collectPackageManagers(projectRoot) {
476
1070
  const packageManagerField = readJsonIfExists(path.join(projectRoot, 'package.json'))?.packageManager;
477
1071
 
@@ -499,6 +1093,7 @@ function collectPackageManagers(projectRoot) {
499
1093
  function collectProjectFiles(projectRoot, maxDepth = 2) {
500
1094
  const files = [];
501
1095
  const skippedPaths = [];
1096
+ const skippedPathDetails = [];
502
1097
  const ignoredDirs = new Set([
503
1098
  '.git',
504
1099
  'node_modules',
@@ -515,6 +1110,12 @@ function collectProjectFiles(projectRoot, maxDepth = 2) {
515
1110
  ]);
516
1111
  const allowedHiddenDirs = new Set(['.github', '.vscode', '.devcontainer']);
517
1112
 
1113
+ function skipPath(relativePath, reason) {
1114
+ const normalized = relativePath.split(path.sep).join('/');
1115
+ skippedPaths.push(normalized);
1116
+ skippedPathDetails.push({ path: normalized, reason });
1117
+ }
1118
+
518
1119
  function walk(currentDir, depth, relativeDir = '') {
519
1120
  const entries = fs.readdirSync(currentDir, { withFileTypes: true });
520
1121
 
@@ -524,12 +1125,18 @@ function collectProjectFiles(projectRoot, maxDepth = 2) {
524
1125
 
525
1126
  if (entry.isDirectory()) {
526
1127
  if (ignoredDirs.has(entry.name)) {
527
- skippedPaths.push(entryRelativePath);
1128
+ skipPath(entryRelativePath, `unsafe-segment:${entry.name}`);
1129
+ continue;
1130
+ }
1131
+
1132
+ const directoryReason = getContextPathExclusionReason(entryRelativePath);
1133
+ if (directoryReason) {
1134
+ skipPath(entryRelativePath, directoryReason);
528
1135
  continue;
529
1136
  }
530
1137
 
531
1138
  if (entry.name.startsWith('.') && !allowedHiddenDirs.has(entry.name)) {
532
- skippedPaths.push(entryRelativePath);
1139
+ skipPath(entryRelativePath, 'hidden-directory');
533
1140
  continue;
534
1141
  }
535
1142
 
@@ -540,13 +1147,19 @@ function collectProjectFiles(projectRoot, maxDepth = 2) {
540
1147
  continue;
541
1148
  }
542
1149
 
1150
+ const fileReason = getContextPathExclusionReason(entryRelativePath);
1151
+ if (fileReason) {
1152
+ skipPath(entryRelativePath, fileReason);
1153
+ continue;
1154
+ }
1155
+
543
1156
  files.push(entryRelativePath);
544
1157
  }
545
1158
  }
546
1159
 
547
1160
  walk(projectRoot, 0);
548
1161
 
549
- return { files, skippedPaths };
1162
+ return { files, skipped_path_details: skippedPathDetails, skippedPaths };
550
1163
  }
551
1164
 
552
1165
  function collectRootEntries(projectRoot) {
@@ -594,6 +1207,7 @@ function collectLanguageSignals(files) {
594
1207
  }
595
1208
 
596
1209
  const languages = [];
1210
+ const seenLanguages = new Set();
597
1211
  const extToLanguage = new Map([
598
1212
  ['.ts', 'typescript'],
599
1213
  ['.tsx', 'typescript'],
@@ -619,14 +1233,90 @@ function collectLanguageSignals(files) {
619
1233
  ]);
620
1234
 
621
1235
  for (const [ext, language] of extToLanguage.entries()) {
622
- if (extensions.has(ext)) {
1236
+ if (extensions.has(ext) && !seenLanguages.has(language)) {
623
1237
  languages.push(language);
1238
+ seenLanguages.add(language);
624
1239
  }
625
1240
  }
626
1241
 
627
1242
  return languages;
628
1243
  }
629
1244
 
1245
+ function parseCreateQuiverScriptCommand(command) {
1246
+ const normalized = String(command || '').trim();
1247
+ const match = normalized.match(/^npx\s+create-quiver(?:@[^\s]+)?\s+(.+)$/);
1248
+ if (!match) {
1249
+ return null;
1250
+ }
1251
+
1252
+ const tokens = match[1].split(/\s+/).filter(Boolean);
1253
+ if (tokens.length === 0) {
1254
+ return null;
1255
+ }
1256
+
1257
+ return {
1258
+ commandName: tokens[0],
1259
+ subcommand: tokens[1] || '',
1260
+ };
1261
+ }
1262
+
1263
+ function findUnsupportedCreateQuiverScripts(scripts = {}) {
1264
+ const unsupported = [];
1265
+
1266
+ for (const [scriptName, command] of Object.entries(scripts)) {
1267
+ const parsed = parseCreateQuiverScriptCommand(command);
1268
+ if (!parsed) {
1269
+ continue;
1270
+ }
1271
+
1272
+ if (!SUPPORTED_COMMAND_MODES.has(parsed.commandName)) {
1273
+ unsupported.push({
1274
+ command,
1275
+ reason: `unsupported command "${parsed.commandName}"`,
1276
+ scriptName,
1277
+ });
1278
+ continue;
1279
+ }
1280
+
1281
+ if (parsed.commandName === 'ai' && !SUPPORTED_AI_COMMANDS.has(parsed.subcommand)) {
1282
+ unsupported.push({
1283
+ command,
1284
+ reason: `unsupported ai subcommand "${parsed.subcommand || '(missing)'}"`,
1285
+ scriptName,
1286
+ });
1287
+ continue;
1288
+ }
1289
+
1290
+ if (parsed.commandName === 'spec' && !SUPPORTED_SPEC_COMMANDS.has(parsed.subcommand)) {
1291
+ unsupported.push({
1292
+ command,
1293
+ reason: `unsupported spec subcommand "${parsed.subcommand || '(missing)'}"`,
1294
+ scriptName,
1295
+ });
1296
+ continue;
1297
+ }
1298
+
1299
+ if (parsed.commandName === 'demo' && !SUPPORTED_DEMO_COMMANDS.has(parsed.subcommand)) {
1300
+ unsupported.push({
1301
+ command,
1302
+ reason: `unsupported demo subcommand "${parsed.subcommand || '(missing)'}"`,
1303
+ scriptName,
1304
+ });
1305
+ }
1306
+ }
1307
+
1308
+ return unsupported;
1309
+ }
1310
+
1311
+ function detectNodeProject(files, rootEntries, packageJson, languages) {
1312
+ const hasPackageJson = Boolean(packageJson);
1313
+ const hasJavaScriptSignals = languages.some((language) => language === 'javascript' || language === 'typescript');
1314
+ const hasSourceDirectories = detectSourceDirectories(rootEntries).length > 0;
1315
+ const hasSourceFiles = files.some((file) => /\.(?:c|m)?jsx?$/i.test(file) || /\.(?:c|m)?tsx?$/i.test(file));
1316
+
1317
+ return hasJavaScriptSignals && (hasPackageJson || hasSourceDirectories || hasSourceFiles);
1318
+ }
1319
+
630
1320
  function collectWorkspaces(packageJson) {
631
1321
  if (!packageJson) {
632
1322
  return [];
@@ -756,6 +1446,11 @@ function detectFrameworks(projectRoot, files, rootEntries, packageJson) {
756
1446
  evidence.push({ framework: 'react', signals: ['react', 'typescript files'] });
757
1447
  }
758
1448
 
1449
+ if (frameworks.length === 0 && detectNodeProject(files, rootEntries, packageJson, languages)) {
1450
+ frameworks.push('node');
1451
+ evidence.push({ framework: 'node', signals: ['package.json', 'javascript or typescript source files'] });
1452
+ }
1453
+
759
1454
  const primary = frameworks[0] || 'unknown';
760
1455
 
761
1456
  return {
@@ -850,7 +1545,7 @@ function detectRisks(projectRoot, scan) {
850
1545
  function buildProjectScan(projectRoot) {
851
1546
  const packageJson = readJsonIfExists(path.join(projectRoot, 'package.json'));
852
1547
  const rootEntries = collectRootEntries(projectRoot);
853
- const { files, skippedPaths } = collectProjectFiles(projectRoot);
1548
+ const { files, skippedPaths, skipped_path_details } = collectProjectFiles(projectRoot);
854
1549
  const topLevelDirectories = rootEntries.filter((entry) => entry.type === 'directory' && !entry.name.startsWith('.')).map((entry) => entry.name);
855
1550
  const sourceDirectories = detectSourceDirectories(rootEntries);
856
1551
  const configFiles = detectConfigFiles(rootEntries);
@@ -908,6 +1603,7 @@ function buildProjectScan(projectRoot) {
908
1603
  },
909
1604
  risks: [],
910
1605
  skipped_paths: skippedPaths,
1606
+ skipped_path_details,
911
1607
  };
912
1608
 
913
1609
  scan.risks = detectRisks(projectRoot, scan);
@@ -931,8 +1627,8 @@ function renderProjectMap(scan) {
931
1627
  'docs/INDEX.md',
932
1628
  'docs/AI_CONTEXT.md',
933
1629
  'docs/DECISIONS.md',
934
- 'docs/PROJECT_SCAN.json',
935
- 'docs/PROJECT_MAP.md',
1630
+ CURRENT_SCAN_RELATIVE_PATH,
1631
+ PROJECT_MAP_RELATIVE_PATH,
936
1632
  'docs/AI_ONBOARDING_PROMPT.md',
937
1633
  'docs/CONTEXTO.md',
938
1634
  'docs/WORKFLOW.md',
@@ -952,8 +1648,7 @@ function renderProjectMap(scan) {
952
1648
  'README.md',
953
1649
  'docs/INDEX.md',
954
1650
  'docs/AI_CONTEXT.md',
955
- 'docs/PROJECT_SCAN.json',
956
- 'docs/PROJECT_MAP.md',
1651
+ PROJECT_MAP_RELATIVE_PATH,
957
1652
  hasDecisionLog ? 'docs/DECISIONS.md' : 'docs/DECISIONS.md (create with migrate if missing)',
958
1653
  'docs/CONTEXTO.md',
959
1654
  'docs/WORKFLOW.md',
@@ -993,7 +1688,7 @@ function renderProjectMap(scan) {
993
1688
  lines.push('## Entry Points');
994
1689
  lines.push(`- Project overview: ${scan.docs.has_readme ? 'README.md' : 'docs/CONTEXTO.md'}`);
995
1690
  lines.push(`- AI context: ${hasDecisionLog ? 'docs/AI_CONTEXT.md + docs/DECISIONS.md' : 'docs/AI_CONTEXT.md'}`);
996
- lines.push('- Analysis outputs: docs/PROJECT_SCAN.json, docs/PROJECT_MAP.md');
1691
+ lines.push(`- Analysis outputs: ${CURRENT_SCAN_RELATIVE_PATH}, ${PROJECT_MAP_RELATIVE_PATH}`);
997
1692
  lines.push(`- Workflow contract: docs/WORKFLOW.md`);
998
1693
  lines.push(`- Spec contract: specs/${projectSlug}/SPEC.md`);
999
1694
  if (sourceDirs.length > 0) {
@@ -1025,7 +1720,7 @@ function renderProjectMap(scan) {
1025
1720
  }
1026
1721
 
1027
1722
  const relevantScripts = Object.entries(scan.commands.scripts)
1028
- .filter(([name]) => /(^|:)(analyze|doctor|migrate|test|build|lint|dev|start|check)(:|$)|analyze|doctor|migrate|test|build|lint|dev|start|check/i.test(name))
1723
+ .filter(([name]) => /(^|:)(analyze|doctor|migrate|validate|test|build|lint|dev|start|check)(:|$)|analyze|doctor|migrate|validate|test|build|lint|dev|start|check/i.test(name))
1029
1724
  .slice(0, 12);
1030
1725
 
1031
1726
  if (relevantScripts.length > 0) {
@@ -1085,9 +1780,10 @@ function renderProjectMap(scan) {
1085
1780
 
1086
1781
  lines.push('');
1087
1782
  lines.push('## Skipped Paths');
1088
- if (scan.skipped_paths.length > 0) {
1089
- for (const skippedPath of scan.skipped_paths) {
1090
- lines.push(`- ${skippedPath}`);
1783
+ const skippedSummaries = summarizeSkippedPaths(scan);
1784
+ if (skippedSummaries.length > 0) {
1785
+ for (const skippedPath of skippedSummaries) {
1786
+ lines.push(`- ${skippedPath.reason}: ${skippedPath.count}`);
1091
1787
  }
1092
1788
  } else {
1093
1789
  lines.push('- None');
@@ -1095,10 +1791,8 @@ function renderProjectMap(scan) {
1095
1791
 
1096
1792
  lines.push('');
1097
1793
  lines.push('## Do Not Read First');
1098
- if (scan.skipped_paths.length > 0) {
1099
- for (const skippedPath of scan.skipped_paths) {
1100
- lines.push(`- ${skippedPath}`);
1101
- }
1794
+ if (skippedSummaries.length > 0) {
1795
+ lines.push('- Hidden, generated, secret, and cache paths are excluded from the analysis scan.');
1102
1796
  } else {
1103
1797
  lines.push('- None detected, but still prioritize docs and config files before source trees.');
1104
1798
  }
@@ -1108,16 +1802,13 @@ function renderProjectMap(scan) {
1108
1802
  }
1109
1803
 
1110
1804
  function writeProjectScanArtifacts(projectRoot, scan) {
1111
- const docsDir = path.join(projectRoot, 'docs');
1112
- ensureDir(docsDir);
1805
+ const scanPaths = projectScanPaths(projectRoot);
1806
+ ensureDir(path.dirname(scanPaths.projectMapPath));
1113
1807
 
1114
- const jsonPath = path.join(docsDir, 'PROJECT_SCAN.json');
1115
- const mdPath = path.join(docsDir, 'PROJECT_MAP.md');
1808
+ const jsonPath = writeProjectScanJson(projectRoot, scan);
1809
+ fs.writeFileSync(scanPaths.projectMapPath, `${renderProjectMap(scan)}\n`);
1116
1810
 
1117
- fs.writeFileSync(jsonPath, `${JSON.stringify(scan, null, 2)}\n`);
1118
- fs.writeFileSync(mdPath, `${renderProjectMap(scan)}\n`);
1119
-
1120
- return { jsonPath, mdPath };
1811
+ return { jsonPath, mdPath: scanPaths.projectMapPath };
1121
1812
  }
1122
1813
 
1123
1814
  function runAnalyze(targetDir) {
@@ -1129,11 +1820,13 @@ function runAnalyze(targetDir) {
1129
1820
 
1130
1821
  const scan = buildProjectScan(projectRoot);
1131
1822
  const artifacts = writeProjectScanArtifacts(projectRoot, scan);
1823
+ const aiContextPath = refreshAiContextDoc(projectRoot, scan);
1132
1824
  updateStateForAnalyze(projectRoot, CLI_VERSION);
1133
1825
 
1134
1826
  console.log(`Project analysis completed for ${projectRoot}`);
1135
1827
  console.log(`Wrote ${relativePosixPath(projectRoot, artifacts.jsonPath)}`);
1136
1828
  console.log(`Wrote ${relativePosixPath(projectRoot, artifacts.mdPath)}`);
1829
+ console.log(`Wrote ${relativePosixPath(projectRoot, aiContextPath)}`);
1137
1830
  console.log(`Detected primary stack: ${scan.stack.primary}`);
1138
1831
  console.log(`Detected package manager: ${scan.project.package_manager}`);
1139
1832
  }
@@ -1153,6 +1846,7 @@ function runMigrate(targetDir, options = {}) {
1153
1846
  const projectName = packageJson.name || path.basename(projectRoot) || 'Quiver Project';
1154
1847
  const packageRoot = path.resolve(__dirname, '../..');
1155
1848
  const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'quiver-migrate-'));
1849
+ const legacyLayout = inspectLegacyMigrationLayout(projectRoot);
1156
1850
 
1157
1851
  try {
1158
1852
  const templateRoot = packTemplate(packageRoot, tempRoot);
@@ -1161,7 +1855,10 @@ function runMigrate(targetDir, options = {}) {
1161
1855
  projectRoot,
1162
1856
  projectName,
1163
1857
  cliVersion: CLI_VERSION,
1858
+ legacyScripts: true,
1164
1859
  migrateMode: true,
1860
+ profile: 'full',
1861
+ templateRoot,
1165
1862
  });
1166
1863
  updateStateForMigrate(projectRoot, projectName, CLI_VERSION);
1167
1864
 
@@ -1176,12 +1873,15 @@ function runMigrate(targetDir, options = {}) {
1176
1873
 
1177
1874
  console.log(`Quiver migration completed for ${projectRoot}`);
1178
1875
  console.log('Missing workflow files were restored without overwriting existing project files.');
1876
+ if (legacyLayout.hasLegacyLayout) {
1877
+ console.log(`Legacy layout detected and preserved: ${legacyLayout.legacyPaths.join(', ')}`);
1878
+ }
1179
1879
  } finally {
1180
1880
  fs.rmSync(tempRoot, { recursive: true, force: true });
1181
1881
  }
1182
1882
  }
1183
1883
 
1184
- function runDoctor(targetDir) {
1884
+ function runDoctor(targetDir, options = {}) {
1185
1885
  const projectRoot = resolveTargetRoot(process.cwd(), targetDir);
1186
1886
 
1187
1887
  if (!fs.existsSync(projectRoot)) {
@@ -1192,47 +1892,53 @@ function runDoctor(targetDir) {
1192
1892
  throw new Error(formatError('doctor requires a project previously initialized by Quiver.\nRun init first: npx create-quiver --name "Project Name"'));
1193
1893
  }
1194
1894
 
1195
- const generatedSpecs = listGeneratedSpecDirs(projectRoot);
1196
- if (generatedSpecs.length !== 1) {
1197
- throw new Error(formatError(`expected exactly one generated spec directory, found ${generatedSpecs.length || 0}`));
1895
+ const fixPlan = buildDoctorFixPlan(projectRoot);
1896
+ if (options.fix) {
1897
+ if (options.dryRun) {
1898
+ console.log(formatDoctorFixPlan(fixPlan, { dryRun: true }));
1899
+ return;
1900
+ }
1901
+
1902
+ applyDoctorFixPlan(projectRoot, fixPlan);
1903
+ console.log(formatDoctorFixPlan(fixPlan));
1198
1904
  }
1199
1905
 
1200
- const projectSlug = generatedSpecs[0];
1201
- const requiredFiles = [
1906
+ const doctorReport = collectDoctorReport(projectRoot);
1907
+ const specSlugs = doctorReport.specSlugs;
1908
+ const specRequiredFiles = specSlugs.flatMap((projectSlug) => [
1909
+ `specs/${projectSlug}/SPEC.md`,
1910
+ `specs/${projectSlug}/STATUS.md`,
1911
+ `specs/${projectSlug}/EVIDENCE_REPORT.md`,
1912
+ ]);
1913
+ const newLayoutRequiredFiles = [
1202
1914
  'AGENTS.md',
1203
1915
  'README.md',
1204
- 'docs/INDEX.md',
1205
1916
  'docs/AI_CONTEXT.md',
1206
1917
  'docs/AI_ONBOARDING_PROMPT.md',
1207
- 'docs/CONTEXTO.md',
1918
+ 'docs/COMMANDS.md',
1208
1919
  'docs/WORKFLOW.md',
1209
- 'docs/SUPPORT_MATRIX.md',
1210
- 'docs/TROUBLESHOOTING.md',
1211
- 'docs/TESTING_GUIDE_FOR_AI.md',
1212
- 'docs/ai/PRINCIPLES.md',
1213
- 'docs/ai/RULES.yaml',
1214
- 'docs/ai/LESSONS.md',
1215
- `specs/${projectSlug}/SPEC.md`,
1216
- `specs/${projectSlug}/STATUS.md`,
1217
- `specs/${projectSlug}/EVIDENCE_REPORT.md`,
1218
1920
  'package.json',
1219
- '.github/pull_request_template.md',
1220
- '.github/ISSUE_TEMPLATE/bug_report.md',
1221
- '.github/ISSUE_TEMPLATE/feature_request.md',
1222
- '.github/workflows/ci.yml',
1223
- ];
1224
-
1225
- const requiredExecutables = [
1226
- 'tools/scripts/start-slice.sh',
1227
- 'tools/scripts/check-slice-readiness.sh',
1228
- 'tools/scripts/check-pr-readiness.sh',
1229
- 'tools/scripts/cleanup-slice.sh',
1230
- 'tools/scripts/check-scope.sh',
1921
+ '.quiver/state.json',
1922
+ '.quiver/config.json',
1923
+ '.quiver/.gitignore',
1924
+ ...specRequiredFiles,
1231
1925
  ];
1232
-
1926
+ const requiredFiles = doctorReport.layout === 'legacy'
1927
+ ? ['package.json', ...specRequiredFiles]
1928
+ : newLayoutRequiredFiles;
1929
+ const legacyScriptsDir = path.join(projectRoot, 'tools', 'scripts');
1930
+ const requiredExecutables = fs.existsSync(legacyScriptsDir)
1931
+ ? [
1932
+ 'tools/scripts/start-slice.sh',
1933
+ 'tools/scripts/check-slice-readiness.sh',
1934
+ 'tools/scripts/check-pr-readiness.sh',
1935
+ 'tools/scripts/cleanup-slice.sh',
1936
+ 'tools/scripts/check-scope.sh',
1937
+ ]
1938
+ : [];
1233
1939
  const missingFiles = assertFilesExist(projectRoot, requiredFiles);
1234
1940
  const nonExecutableScripts = assertExecutablesExist(projectRoot, requiredExecutables);
1235
- const pkg = loadPackageJson(projectRoot);
1941
+ const pkg = fs.existsSync(path.join(projectRoot, 'package.json')) ? loadPackageJson(projectRoot) : {};
1236
1942
  const workflowScriptGroups = [
1237
1943
  { label: 'migrate', node: 'quiver:migrate', legacy: 'migrate' },
1238
1944
  { label: 'start-slice', node: 'quiver:start-slice', legacy: 'start:slice' },
@@ -1250,8 +1956,21 @@ function runDoctor(targetDir) {
1250
1956
  .map((group) => group.label);
1251
1957
  const missingNodeNativeScripts = ['quiver:migrate', 'quiver:analyze', 'quiver:doctor']
1252
1958
  .filter((name) => typeof pkg.scripts?.[name] !== 'string');
1253
- const hasScanArtifacts = fs.existsSync(path.join(projectRoot, 'docs', 'PROJECT_SCAN.json'))
1254
- && fs.existsSync(path.join(projectRoot, 'docs', 'PROJECT_MAP.md'));
1959
+ const missingAiScripts = [
1960
+ 'quiver:ai:agent',
1961
+ 'quiver:ai:onboard',
1962
+ 'quiver:ai:plan',
1963
+ 'quiver:ai:review-plan',
1964
+ 'quiver:ai:approve',
1965
+ 'quiver:ai:prompt-slice',
1966
+ 'quiver:ai:execute-slice',
1967
+ 'quiver:ai:execute-plan',
1968
+ 'quiver:ai:pr',
1969
+ 'quiver:ai:doctor',
1970
+ ].filter((name) => typeof pkg.scripts?.[name] !== 'string');
1971
+ const unsupportedCreateQuiverScripts = findUnsupportedCreateQuiverScripts(pkg.scripts || {});
1972
+ const hasScanArtifacts = hasProjectScanArtifact(projectRoot)
1973
+ && fs.existsSync(path.join(projectRoot, PROJECT_MAP_RELATIVE_PATH));
1255
1974
  const quiverState = readState(projectRoot);
1256
1975
  const hasQuiverState = Boolean(quiverState);
1257
1976
  const stateWarnings = hasQuiverState ? [] : ['missing Quiver state metadata: .quiver/state.json'];
@@ -1260,24 +1979,41 @@ function runDoctor(targetDir) {
1260
1979
  ...nonExecutableScripts.map((file) => `missing executable bit: ${file}`),
1261
1980
  ...missingScripts.map((name) => `missing package.json script: ${name}`),
1262
1981
  ];
1263
- const softWarnings = collectDoctorWarnings(projectRoot);
1982
+ const softWarnings = doctorReport.warnings;
1264
1983
 
1265
1984
  if (migrationProblems.length > 0) {
1266
1985
  throw new Error(formatError(`doctor failed:\n- ${migrationProblems.join('\n- ')}\n- Run migration first: npx create-quiver migrate`));
1267
1986
  }
1268
1987
 
1269
1988
  console.log(`Quiver doctor passed for ${projectRoot}`);
1270
- console.log(`Generated project slug: ${projectSlug}`);
1989
+ console.log(`Layout: ${doctorReport.layout}`);
1990
+ if (specSlugs.length > 0) {
1991
+ console.log(`Specs: ${specSlugs.join(', ')}`);
1992
+ } else {
1993
+ console.log('Specs: none yet');
1994
+ }
1995
+ if (doctorReport.legacySignals.length > 0) {
1996
+ console.log(`Legacy signals: ${doctorReport.legacySignals.join(', ')}`);
1997
+ }
1271
1998
  console.log('Next steps:');
1999
+ for (const recommendation of doctorReport.recommendations) {
2000
+ console.log(`- ${recommendation}`);
2001
+ }
1272
2002
  for (const warning of stateWarnings) {
1273
2003
  console.log(`- Warning: ${warning}`);
1274
2004
  }
1275
2005
  for (const scriptName of missingNodeNativeScripts) {
1276
2006
  console.log(`- Warning: missing Node-native script: ${scriptName}`);
1277
2007
  }
2008
+ for (const scriptName of missingAiScripts) {
2009
+ console.log(`- Warning: missing AI orchestration script: ${scriptName}`);
2010
+ }
1278
2011
  if (legacyOnlyScripts.length > 0) {
1279
2012
  console.log(`- Warning: legacy Bash workflow scripts detected for ${legacyOnlyScripts.join(', ')}. Run npx create-quiver migrate to add quiver:* npm scripts.`);
1280
2013
  }
2014
+ for (const script of unsupportedCreateQuiverScripts) {
2015
+ console.log(`- Warning: package.json script ${script.scriptName} targets ${script.reason}: \`${script.command}\`. Update create-quiver or regenerate scripts with npx create-quiver migrate.`);
2016
+ }
1281
2017
  for (const warning of softWarnings) {
1282
2018
  console.log(`- Warning: ${warning}`);
1283
2019
  }
@@ -1289,20 +2025,23 @@ function runDoctor(targetDir) {
1289
2025
  console.log('- Ask your AI agent: Read AGENTS.md, then docs/AI_ONBOARDING_PROMPT.md and execute it.');
1290
2026
  }
1291
2027
  console.log('- Check the next ready slice: npx create-quiver next');
1292
- console.log(`- Start a slice: npx create-quiver start-slice specs/${projectSlug}/slices/slice-template/slice.json`);
1293
- console.log(`- Validate a slice: npx create-quiver check-slice specs/${projectSlug}/slices/slice-template/slice.json`);
1294
- console.log(`- Validate the PR gate: npx create-quiver check-pr specs/${projectSlug}/slices/slice-template/slice.json`);
2028
+ if (specSlugs.length > 0) {
2029
+ const projectSlug = specSlugs[0];
2030
+ console.log(`- Start a slice: npx create-quiver start-slice specs/${projectSlug}/slices/<slice-id>/slice.json`);
2031
+ console.log(`- Validate a slice: npx create-quiver check-slice specs/${projectSlug}/slices/<slice-id>/slice.json`);
2032
+ console.log(`- Validate the PR gate: npx create-quiver check-pr specs/${projectSlug}/slices/<slice-id>/slice.json`);
2033
+ } else {
2034
+ console.log('- Create real specs and slices only after acceptance criteria are approved and the technical plan is reviewed and approved.');
2035
+ }
1295
2036
  }
1296
2037
 
1297
2038
  function printInitNextSteps(targetDir, projectName) {
1298
- const projectSlug = toProjectSlug(projectName);
1299
-
1300
2039
  console.log('');
1301
2040
  console.log('Next steps:');
1302
- console.log(`- Review AGENTS.md, then ${path.join(targetDir, 'docs', 'INDEX.md')}`);
2041
+ console.log(`- Review AGENTS.md, then ${path.join(targetDir, 'docs', 'AI_ONBOARDING_PROMPT.md')}`);
1303
2042
  console.log(`- Review ${path.join(targetDir, 'docs', 'WORKFLOW.md')}`);
1304
- console.log(`- Create your first slice from ${path.join(targetDir, 'specs', projectSlug, 'slices', 'slice-template', 'slice.json')}`);
1305
- console.log(`- Launch slice work with npx create-quiver start-slice specs/${projectSlug}/slices/slice-template/slice.json`);
2043
+ console.log('- Analyze the project with npx create-quiver analyze');
2044
+ console.log('- Create real specs and slices after acceptance criteria are approved and the technical plan is reviewed and approved.');
1306
2045
  }
1307
2046
 
1308
2047
  async function run(argv) {
@@ -1318,8 +2057,16 @@ async function run(argv) {
1318
2057
  return;
1319
2058
  }
1320
2059
 
2060
+ if (args.mode === 'flow') {
2061
+ await runFlow(process.cwd(), {
2062
+ json: args.json,
2063
+ });
2064
+ return;
2065
+ }
2066
+
1321
2067
  if (args.mode === 'plan') {
1322
2068
  runPlan(process.cwd(), {
2069
+ includeCompleted: args.includeCompleted,
1323
2070
  json: args.json,
1324
2071
  onlyReady: args.onlyReady,
1325
2072
  specSlug: args.specSlug,
@@ -1328,12 +2075,170 @@ async function run(argv) {
1328
2075
  return;
1329
2076
  }
1330
2077
 
2078
+ if (args.mode === 'prepare') {
2079
+ await runPrepare(process.cwd(), {
2080
+ dryRun: args.dryRun,
2081
+ identityFile: args.aiIdentityFile || undefined,
2082
+ provider: args.prepareProvider || undefined,
2083
+ sshHostAlias: args.aiSshHostAlias || undefined,
2084
+ });
2085
+ return;
2086
+ }
2087
+
2088
+ if (args.mode === 'ai') {
2089
+ if (!args.aiCommand) {
2090
+ throw new Error(formatError('missing ai subcommand. Use: npx create-quiver ai onboard | prepare-context | plan | review-plan | approve | approvals | agent | prompt-slice | execute-slice | execute-plan | doctor | pr'));
2091
+ }
2092
+
2093
+ if (args.aiCommand === 'agent') {
2094
+ runAiAgent(process.cwd(), {
2095
+ command: args.aiAgentCommand,
2096
+ context: args.aiContext || undefined,
2097
+ label: args.aiLabel || undefined,
2098
+ model: args.aiModel || undefined,
2099
+ provider: args.aiProviderExplicit ? args.aiProvider : undefined,
2100
+ role: args.aiAgentRole || undefined,
2101
+ });
2102
+ return;
2103
+ }
2104
+
2105
+ if (args.aiCommand === 'onboard') {
2106
+ await runOnboard(process.cwd(), {
2107
+ context: args.aiContext || undefined,
2108
+ dryRun: args.dryRun,
2109
+ input: args.aiInput || undefined,
2110
+ provider: args.aiProvider,
2111
+ providerExplicit: args.aiProviderExplicit,
2112
+ role: args.aiRole,
2113
+ timeout: args.aiTimeout,
2114
+ });
2115
+ return;
2116
+ }
2117
+
2118
+ if (args.aiCommand === 'prepare-context') {
2119
+ await runAiPrepareContext(process.cwd(), {
2120
+ dryRun: args.dryRun,
2121
+ });
2122
+ return;
2123
+ }
2124
+
2125
+ if (args.aiCommand === 'plan') {
2126
+ await runAiPlan(process.cwd(), {
2127
+ context: args.aiContext || undefined,
2128
+ dryRun: args.dryRun,
2129
+ input: args.aiInput || undefined,
2130
+ phase: args.aiPhase,
2131
+ provider: args.aiProvider,
2132
+ providerExplicit: args.aiProviderExplicit,
2133
+ role: args.aiRole,
2134
+ specSlug: args.specSlug || undefined,
2135
+ timeout: args.aiTimeout,
2136
+ });
2137
+ return;
2138
+ }
2139
+
2140
+ if (args.aiCommand === 'review-plan') {
2141
+ await runAiReviewPlan(process.cwd(), {
2142
+ context: args.aiContext || undefined,
2143
+ dryRun: args.dryRun,
2144
+ input: args.aiInput || undefined,
2145
+ provider: args.aiProvider,
2146
+ providerExplicit: args.aiProviderExplicit,
2147
+ timeout: args.aiTimeout,
2148
+ });
2149
+ return;
2150
+ }
2151
+
2152
+ if (args.aiCommand === 'approve') {
2153
+ await runAiApprove(process.cwd(), {
2154
+ dryRun: args.dryRun,
2155
+ input: args.aiInput || undefined,
2156
+ phase: args.aiPhase,
2157
+ version: args.aiVersion || undefined,
2158
+ });
2159
+ return;
2160
+ }
2161
+
2162
+ if (args.aiCommand === 'approvals' || args.aiCommand === 'approval-status') {
2163
+ await runAiApprovalStatus(process.cwd());
2164
+ return;
2165
+ }
2166
+
2167
+ if (args.aiCommand === 'execute-slice') {
2168
+ await runAiExecuteSlice(process.cwd(), {
2169
+ allowDirty: args.aiAllowDirty,
2170
+ commit: args.aiCommit,
2171
+ context: args.aiContext || undefined,
2172
+ dryRun: args.dryRun,
2173
+ provider: args.aiProvider,
2174
+ providerExplicit: args.aiProviderExplicit,
2175
+ role: args.aiRole,
2176
+ slice: args.aiSlice || undefined,
2177
+ timeout: args.aiTimeout,
2178
+ });
2179
+ return;
2180
+ }
2181
+
2182
+ if (args.aiCommand === 'prompt-slice' || args.aiCommand === 'executor-prompt') {
2183
+ runAiPromptSlice(process.cwd(), {
2184
+ slice: args.aiSlice || undefined,
2185
+ });
2186
+ return;
2187
+ }
2188
+
2189
+ if (args.aiCommand === 'execute-plan') {
2190
+ await runAiExecutePlan(process.cwd(), {
2191
+ allowDirty: args.aiAllowDirty,
2192
+ commit: args.aiCommit,
2193
+ context: args.aiContext || undefined,
2194
+ dryRun: args.dryRun,
2195
+ execute: args.aiExecute,
2196
+ json: args.json,
2197
+ mode: args.aiExecutionMode,
2198
+ provider: args.aiProvider,
2199
+ providerExplicit: args.aiProviderExplicit,
2200
+ role: args.aiRole,
2201
+ specSlug: args.specSlug || undefined,
2202
+ timeout: args.aiTimeout,
2203
+ });
2204
+ return;
2205
+ }
2206
+
2207
+ if (args.aiCommand === 'doctor') {
2208
+ await runAiDoctor(process.cwd(), {
2209
+ dryRun: args.dryRun,
2210
+ remote: args.aiRemote || undefined,
2211
+ sshHostAlias: args.aiSshHostAlias || undefined,
2212
+ identityFile: args.aiIdentityFile || undefined,
2213
+ });
2214
+ return;
2215
+ }
2216
+
2217
+ if (args.aiCommand === 'pr') {
2218
+ await runAiPr(process.cwd(), {
2219
+ baseBranch: args.aiBaseBranch,
2220
+ create: args.aiCreate,
2221
+ dryRun: args.dryRun,
2222
+ input: args.aiInput || undefined,
2223
+ remote: args.aiRemote || undefined,
2224
+ sshHostAlias: args.aiSshHostAlias || undefined,
2225
+ identityFile: args.aiIdentityFile || undefined,
2226
+ title: args.aiTitle || undefined,
2227
+ });
2228
+ return;
2229
+ }
2230
+
2231
+ throw new Error(formatError(`unsupported ai subcommand: ${args.aiCommand}. Supported tasks: onboard, plan, review-plan, approve, approvals, agent, prompt-slice, execute-slice, execute-plan, doctor, pr`));
2232
+ }
2233
+
1331
2234
  if (args.mode === 'graph') {
1332
2235
  runGraph(process.cwd(), {
1333
2236
  format: args.format,
2237
+ includeCompleted: args.includeCompleted,
1334
2238
  json: args.json,
1335
2239
  level: args.level,
1336
2240
  showConflicts: args.showConflicts,
2241
+ specSlug: args.specSlug,
1337
2242
  unicode: args.unicode,
1338
2243
  });
1339
2244
  return;
@@ -1343,37 +2248,66 @@ async function run(argv) {
1343
2248
  await runNext(process.cwd(), {
1344
2249
  allReady: args.allReady,
1345
2250
  autoStart: args.autoStart,
2251
+ includeCompleted: args.includeCompleted,
1346
2252
  json: args.json,
1347
2253
  specSlug: args.specSlug,
1348
2254
  });
1349
2255
  return;
1350
2256
  }
1351
2257
 
2258
+ if (args.mode === 'evidence') {
2259
+ const result = runEvidence(process.cwd(), {
2260
+ command: args.evidenceArgs,
2261
+ maxOutput: args.evidenceMaxOutput || undefined,
2262
+ output: args.evidenceOutput || undefined,
2263
+ subcommand: args.evidenceCommand,
2264
+ });
2265
+ process.exitCode = result.exitCode;
2266
+ return;
2267
+ }
2268
+
2269
+ if (args.mode === 'demo') {
2270
+ const demoTarget = resolveTargetRoot(process.cwd(), args.targetDirExplicit ? args.targetDir : 'quiver-spec-viewer');
2271
+ runDemo({
2272
+ command: args.demoCommand,
2273
+ demo: args.demoName,
2274
+ dryRun: args.dryRun,
2275
+ targetRoot: demoTarget,
2276
+ });
2277
+ return;
2278
+ }
2279
+
1352
2280
  if (args.mode === 'migrate') {
1353
2281
  runMigrate(args.targetDir, { skipInstall: args.skipInstall });
1354
2282
  return;
1355
2283
  }
1356
2284
 
1357
2285
  if (args.mode === 'doctor') {
1358
- runDoctor(args.targetDir);
2286
+ runDoctor(args.targetDir, {
2287
+ dryRun: args.dryRun,
2288
+ fix: args.doctorFix,
2289
+ });
1359
2290
  return;
1360
2291
  }
1361
2292
 
1362
2293
  if (args.mode === 'start-slice') {
1363
- startSlice(path.resolve(process.cwd(), args.targetDir), { allowDraft: args.allowDraft });
2294
+ startSlice(args.targetDir, { allowDraft: args.allowDraft });
1364
2295
  return;
1365
2296
  }
1366
2297
 
1367
2298
  if (args.mode === 'check-slice') {
1368
- checkSliceReadiness(path.resolve(process.cwd(), args.targetDir), {
2299
+ checkSliceReadiness(args.targetDir, {
2300
+ baseBranch: args.baseBranchExplicit ? args.aiBaseBranch : '',
1369
2301
  gate: args.gate,
2302
+ local: args.checkSliceLocal,
2303
+ remote: args.aiRemote,
1370
2304
  strictOverlap: args.strictOverlap,
1371
2305
  });
1372
2306
  return;
1373
2307
  }
1374
2308
 
1375
2309
  if (args.mode === 'check-pr') {
1376
- checkPrReadiness(path.resolve(process.cwd(), args.targetDir));
2310
+ checkPrReadiness(args.targetDir);
1377
2311
  return;
1378
2312
  }
1379
2313
 
@@ -1397,7 +2331,7 @@ async function run(argv) {
1397
2331
  }
1398
2332
 
1399
2333
  if (args.mode === 'cleanup-slice') {
1400
- cleanupSlice(path.resolve(process.cwd(), args.targetDir), {
2334
+ cleanupSlice(args.targetDir, {
1401
2335
  closeBaseline: args.closeBaseline,
1402
2336
  discard: args.discard,
1403
2337
  dryRun: args.dryRun,
@@ -1407,7 +2341,7 @@ async function run(argv) {
1407
2341
  }
1408
2342
 
1409
2343
  if (args.mode === 'check-scope') {
1410
- checkScope(path.resolve(process.cwd(), args.targetDir), { strict: args.strict });
2344
+ checkScope(args.targetDir, { strict: args.strict });
1411
2345
  return;
1412
2346
  }
1413
2347
 
@@ -1417,17 +2351,81 @@ async function run(argv) {
1417
2351
  return;
1418
2352
  }
1419
2353
 
2354
+ if (args.mode === 'spec') {
2355
+ if (args.specCommand === 'create') {
2356
+ runCreateSpec(process.cwd(), {
2357
+ dryRun: args.dryRun,
2358
+ input: args.aiInput || undefined,
2359
+ specSlug: args.specSlug || undefined,
2360
+ });
2361
+ return;
2362
+ }
2363
+
2364
+ if (!args.targetDir || args.targetDir === '.') {
2365
+ throw new Error(formatError('missing spec directory. Use: npx create-quiver spec <start|status|close> <spec-dir>'));
2366
+ }
2367
+
2368
+ if (args.specCommand === 'start') {
2369
+ const report = startSpecWorktree(process.cwd(), args.targetDir);
2370
+ process.stdout.write(formatSpecStartResult(report));
2371
+ return;
2372
+ }
2373
+
2374
+ if (args.specCommand === 'status') {
2375
+ const report = buildSpecStatus(process.cwd(), args.targetDir);
2376
+ process.stdout.write(formatSpecStatus(report));
2377
+ return;
2378
+ }
2379
+
2380
+ if (args.specCommand === 'close') {
2381
+ const report = closeSpecWorktree(process.cwd(), args.targetDir, {
2382
+ baseBranch: args.aiBaseBranch,
2383
+ discard: args.discard,
2384
+ dryRun: args.dryRun,
2385
+ force: args.force,
2386
+ remote: args.aiRemote,
2387
+ });
2388
+ process.stdout.write(formatSpecCloseResult(report));
2389
+ return;
2390
+ }
2391
+
2392
+ throw new Error(formatError(`unsupported spec subcommand: ${args.specCommand}. Supported tasks: create, start, status, close`));
2393
+ }
2394
+
1420
2395
  const packageRoot = path.resolve(__dirname, '../..');
1421
2396
  const targetDir = resolveTargetRoot(process.cwd(), args.targetDir);
1422
2397
  const projectName = args.projectName || path.basename(targetDir) || 'Quiver Project';
2398
+ const initLayout = buildInitLayout(targetDir, {
2399
+ compatibilityAlias: !args.explicitInit,
2400
+ dryRun: args.dryRun,
2401
+ full: args.initFull,
2402
+ includeTemplates: args.initIncludeTemplates,
2403
+ legacyScripts: args.initLegacyScripts,
2404
+ minimal: args.initMinimal,
2405
+ projectName,
2406
+ skipInstall: args.skipInstall,
2407
+ });
2408
+
2409
+ if (args.dryRun) {
2410
+ console.log(formatInitLayoutPlan(initLayout));
2411
+ return;
2412
+ }
2413
+
1423
2414
  const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'quiver-create-'));
1424
2415
 
1425
2416
  try {
1426
2417
  ensureDir(targetDir);
1427
2418
 
1428
2419
  const templateRoot = packTemplate(packageRoot, tempRoot);
1429
- copyTemplate(templateRoot, targetDir);
1430
- runInitDocs(targetDir, projectName);
2420
+ if (initLayout.profile === 'full') {
2421
+ exportTemplatesToLegacyRoot(templateRoot, targetDir);
2422
+ }
2423
+ runInitDocs(targetDir, projectName, {
2424
+ includeTemplates: args.initIncludeTemplates,
2425
+ legacyScripts: args.initLegacyScripts,
2426
+ profile: initLayout.profile,
2427
+ templateRoot,
2428
+ });
1431
2429
 
1432
2430
  if (!args.skipInstall) {
1433
2431
  const installResult = installSelfAsDevDep(targetDir, CLI_VERSION);
@@ -1448,6 +2446,8 @@ async function run(argv) {
1448
2446
  module.exports = {
1449
2447
  runAnalyze,
1450
2448
  runDoctor,
2449
+ runFlow,
1451
2450
  runMigrate,
2451
+ runPrepare,
1452
2452
  run,
1453
2453
  };