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
@@ -0,0 +1,915 @@
1
+ const fs = require('node:fs');
2
+ const path = require('node:path');
3
+
4
+ const { buildContextPackMetadata, normalizeRole } = require('../lib/ai/context-packs');
5
+ const { runExecuteSlice, runPromptSlice } = require('../lib/ai/executor');
6
+ const { runExecutePlan } = require('../lib/ai/execution-plan');
7
+ const { buildPrCreatePlan, formatPreflightReport, formatPrCreateReport, preflightGitHubPr, runGhPrCreate } = require('../lib/ai/github');
8
+ const { buildContextPreparationDrafts, buildPlannerOnboardingPrompt } = require('../lib/ai/onboarding-template');
9
+ const {
10
+ PLAN_REVIEW_PROMPT_SOURCE,
11
+ buildPlanReviewPrompt,
12
+ resolveReviewedTechnicalPlanInput,
13
+ resolveTechnicalPlanReviewInput,
14
+ savePlanReview,
15
+ summarizePlanReview,
16
+ } = require('../lib/ai/plan-review');
17
+ const { buildSpecGenerationManifest, describeSpecGeneration, generateSpecArtifacts } = require('../lib/ai/spec-generator');
18
+ const { buildProviderInvocation, runProvider } = require('../lib/ai/providers');
19
+ const {
20
+ agentProfilesPath,
21
+ getAgentProfile,
22
+ listAgentProfiles,
23
+ resolveProfileProvider,
24
+ setAgentProfile,
25
+ } = require('../lib/agent-profiles');
26
+ const {
27
+ PLANNER_APPROVAL_PHASES,
28
+ approvePlannerPhase,
29
+ resolveApprovedPlannerInput,
30
+ savePlannerDraft,
31
+ summarizePlannerApproval,
32
+ } = require('../lib/approvals');
33
+ const { assertPlannerPhaseReady, getPlannerPhaseDetails, normalizePlannerPhase, PlannerPhaseError } = require('../lib/ai/phase-gates');
34
+
35
+ const DEFAULT_ONBOARD_PROVIDER = 'codex';
36
+ const DEFAULT_ONBOARD_ROLE = 'planner';
37
+ const DEFAULT_ONBOARD_CONTEXT = 'full';
38
+ const DEFAULT_PLAN_PROVIDER = 'codex';
39
+ const DEFAULT_PLAN_ROLE = 'planner';
40
+ const DEFAULT_PLAN_CONTEXT = 'planning';
41
+ const DEFAULT_PLAN_PHASE = 'acceptance';
42
+
43
+ function formatError(message) {
44
+ return `create-quiver: ${message}`;
45
+ }
46
+
47
+ function readTextFile(filePath, repoRoot) {
48
+ if (!filePath) {
49
+ return '';
50
+ }
51
+
52
+ const resolved = path.resolve(repoRoot, filePath);
53
+ if (!fs.existsSync(resolved)) {
54
+ throw new Error(formatError(`missing input file: ${filePath}`));
55
+ }
56
+
57
+ return fs.readFileSync(resolved, 'utf8');
58
+ }
59
+
60
+ function readTextFileOrEmpty(filePath, repoRoot) {
61
+ if (!filePath) {
62
+ return '';
63
+ }
64
+
65
+ return readTextFile(filePath, repoRoot);
66
+ }
67
+
68
+ function normalizeTimeout(timeoutMs) {
69
+ if (timeoutMs === undefined || timeoutMs === null || timeoutMs === '') {
70
+ return undefined;
71
+ }
72
+
73
+ const parsed = Number(timeoutMs);
74
+ if (!Number.isFinite(parsed) || parsed <= 0) {
75
+ throw new Error(formatError(`invalid timeout value: ${timeoutMs}`));
76
+ }
77
+
78
+ return parsed;
79
+ }
80
+
81
+ function resolveProviderForProfile(repoRoot, role, provider, providerExplicit, fallbackProvider) {
82
+ if (providerExplicit === true || (provider && providerExplicit !== false)) {
83
+ return String(provider || fallbackProvider).trim().toLowerCase();
84
+ }
85
+ return resolveProfileProvider(repoRoot, role, fallbackProvider);
86
+ }
87
+
88
+ function buildPlanContext({ role, context, phase, inputText, inputPath, repoRoot }) {
89
+ const phaseDetails = getPlannerPhaseDetails(phase);
90
+ const pack = buildContextPackMetadata({
91
+ role,
92
+ packName: context || phaseDetails.contextPack,
93
+ repoRoot,
94
+ });
95
+ const relativeInputPath = inputPath ? path.relative(repoRoot, path.resolve(repoRoot, inputPath)).split(path.sep).join('/') : '';
96
+ const sections = [
97
+ pack.prompt,
98
+ `Phase: ${phaseDetails.phase}`,
99
+ phaseDetails.phase === 'acceptance'
100
+ ? 'Task: produce acceptance criteria only. Do not create files or modify product code.'
101
+ : 'Task: produce a technical plan only. Do not create files or modify product code.',
102
+ ];
103
+
104
+ if (relativeInputPath) {
105
+ sections.push(`Input file: ${relativeInputPath}`);
106
+ }
107
+
108
+ if (pack.scanArtifact) {
109
+ sections.push(`Project scan artifact: ${pack.scanArtifact.path} (${pack.scanArtifact.source})`);
110
+ }
111
+
112
+ if (inputText) {
113
+ sections.push('Input:', inputText.trimEnd());
114
+ }
115
+
116
+ return {
117
+ pack,
118
+ prompt: sections.join('\n\n'),
119
+ phaseDetails,
120
+ };
121
+ }
122
+
123
+ function buildOnboardContext({ role, context, inputText, inputPath, repoRoot }) {
124
+ const pack = buildContextPackMetadata({
125
+ role,
126
+ packName: context || DEFAULT_ONBOARD_CONTEXT,
127
+ repoRoot,
128
+ });
129
+ const relativeInputPath = inputPath ? path.relative(repoRoot, path.resolve(repoRoot, inputPath)).split(path.sep).join('/') : '';
130
+ const built = buildPlannerOnboardingPrompt({
131
+ pack,
132
+ inputText,
133
+ inputPath: relativeInputPath,
134
+ repoRoot,
135
+ });
136
+
137
+ return {
138
+ pack,
139
+ plan: built.plan,
140
+ prompt: built.prompt,
141
+ };
142
+ }
143
+
144
+ function formatDryRunReport({ task, provider, role, contextPack, phase, invocation, onboardingPlan }) {
145
+ const lines = [
146
+ `AI ${task} dry-run`,
147
+ `Provider: ${provider}`,
148
+ `Role: ${role}`,
149
+ `Context pack: ${contextPack}`,
150
+ ];
151
+
152
+ if (phase) {
153
+ lines.push(`Phase: ${phase}`);
154
+ }
155
+
156
+ lines.push(`Command: ${invocation.command} ${invocation.args.join(' ')}`);
157
+ lines.push(`Timeout: ${invocation.timeoutMs}ms`);
158
+ lines.push(`Prompt transport: ${invocation.promptTransport.mode}`);
159
+ lines.push(`Prompt length: ${invocation.promptLength} bytes`);
160
+
161
+ if (onboardingPlan) {
162
+ lines.push(`Prompt source: ${onboardingPlan.promptSource}`);
163
+ lines.push(`Selected docs: ${onboardingPlan.selectedDocs.length}`);
164
+ lines.push(`Documentation debt: ${onboardingPlan.missingDocs.length}`);
165
+ }
166
+
167
+ return `${lines.join('\n')}\n`;
168
+ }
169
+
170
+ function formatPathList(items, emptyLabel = 'none') {
171
+ if (!Array.isArray(items) || items.length === 0) {
172
+ return [`- ${emptyLabel}`];
173
+ }
174
+
175
+ return items.map((item) => `- ${item}`);
176
+ }
177
+
178
+ function formatContextPreparationReport({ dryRun, plan, docs, writtenDocs }) {
179
+ const lines = [
180
+ dryRun ? 'AI prepare-context dry-run' : 'AI prepare-context completed',
181
+ `Mode: ${dryRun ? 'dry-run' : 'live'}`,
182
+ `Project: ${plan.projectName}`,
183
+ `Project slug: ${plan.projectSlug}`,
184
+ 'Writes: docs-only',
185
+ 'Product code: untouched',
186
+ `Proposed docs: ${docs.length > 0 ? docs.map((doc) => doc.path).join(', ') : 'none'}`,
187
+ ];
188
+
189
+ if (!dryRun) {
190
+ lines.push(`Written docs: ${writtenDocs.length > 0 ? writtenDocs.join(', ') : 'none'}`);
191
+ }
192
+
193
+ lines.push(
194
+ 'Files considered:',
195
+ ...plan.filesConsidered.map((item) => `- ${item.path}: ${item.present ? 'present' : 'absent'}${item.reason ? ` (${item.reason})` : ''}`),
196
+ 'Assumptions:',
197
+ ...formatPathList(plan.assumptions),
198
+ 'Risks:',
199
+ ...formatPathList(plan.risks),
200
+ 'Omitted paths:',
201
+ ...formatPathList(plan.omittedPaths),
202
+ 'Uncertainty markers: TODO | Assumption | Pending confirmation',
203
+ );
204
+
205
+ return `${lines.join('\n')}\n`;
206
+ }
207
+
208
+ function writeProviderOutput(result) {
209
+ if (result.stdout) {
210
+ process.stdout.write(result.stdout);
211
+ }
212
+ if (result.stderr) {
213
+ process.stderr.write(result.stderr);
214
+ }
215
+ }
216
+
217
+ function writeDraftDocs(repoRoot, drafts) {
218
+ const writtenDocs = [];
219
+ for (const draft of drafts) {
220
+ const destinationPath = path.join(repoRoot, draft.path);
221
+ fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
222
+ fs.writeFileSync(destinationPath, `${draft.content.replace(/\s+$/g, '')}\n`);
223
+ writtenDocs.push(draft.path);
224
+ }
225
+ return writtenDocs;
226
+ }
227
+
228
+ function formatSpecDryRunReport({ manifest, repoRoot }) {
229
+ const preview = describeSpecGeneration(manifest, repoRoot);
230
+ const relativeSpecDir = path.relative(repoRoot, preview.specDir).split(path.sep).join('/');
231
+ const lines = [
232
+ 'AI plan dry-run',
233
+ 'Phase: spec',
234
+ `Spec slug: ${manifest.slug}`,
235
+ `Title: ${manifest.title}`,
236
+ `Input file: ${manifest.sourcePath}`,
237
+ `Target: ${relativeSpecDir}`,
238
+ `Planned files: ${preview.files.length}`,
239
+ ];
240
+
241
+ for (const file of preview.files) {
242
+ lines.push(`- ${file}`);
243
+ }
244
+
245
+ return `${lines.join('\n')}\n`;
246
+ }
247
+
248
+ function formatSpecGenerationResult(result, repoRoot) {
249
+ const relativeSpecDir = path.relative(repoRoot, result.specDir).split(path.sep).join('/');
250
+ const lines = [
251
+ 'AI plan spec generation completed',
252
+ `Spec slug: ${result.manifest.slug}`,
253
+ `Target: ${relativeSpecDir}`,
254
+ `Files written: ${result.files.length}`,
255
+ ];
256
+
257
+ for (const filePath of result.files) {
258
+ lines.push(`- ${path.relative(repoRoot, filePath).split(path.sep).join('/')}`);
259
+ }
260
+
261
+ return `${lines.join('\n')}\n`;
262
+ }
263
+
264
+ function formatApprovalResult(result, repoRoot) {
265
+ const relativePath = path.relative(repoRoot, result.filePath).split(path.sep).join('/');
266
+ const lines = [
267
+ 'AI approval saved',
268
+ `Phase: ${result.phase}`,
269
+ `Status: approved`,
270
+ `Artifact: ${relativePath}`,
271
+ `Source file: ${result.sourceFile}`,
272
+ `Timestamp: ${result.createdAt}`,
273
+ ];
274
+ if (result.version) {
275
+ lines.push(`Version: v${result.version}`);
276
+ }
277
+
278
+ return `${lines.join('\n')}\n`;
279
+ }
280
+
281
+ function formatApprovalDryRunResult({ phase, input, version }) {
282
+ const lines = ['AI approval dry-run', `Phase: ${phase}`];
283
+ if (version) {
284
+ lines.push(`Version: v${version}`);
285
+ }
286
+ if (input) {
287
+ lines.push(`Input file: ${input}`);
288
+ }
289
+ return `${lines.join('\n')}\n`;
290
+ }
291
+
292
+ function formatApprovalStatusReport(repoRoot) {
293
+ const sections = ['AI approvals status'];
294
+ for (const phase of PLANNER_APPROVAL_PHASES) {
295
+ sections.push(summarizePlannerApproval(repoRoot, phase).trimEnd());
296
+ }
297
+ sections.push(summarizePlanReview(repoRoot).trimEnd());
298
+ return `${sections.join('\n\n')}\n`;
299
+ }
300
+
301
+ function annotateProviderError(error, scope, phase) {
302
+ const phaseLabel = phase ? ` phase '${phase}'` : '';
303
+ const message = error && error.message ? error.message : String(error);
304
+ const wrapped = new Error(formatError(`ai ${scope}${phaseLabel} failed: ${message}`));
305
+ wrapped.cause = error;
306
+ wrapped.code = error && error.code ? error.code : 'AI_PROVIDER_ERROR';
307
+ wrapped.details = error && error.details ? error.details : undefined;
308
+ return wrapped;
309
+ }
310
+
311
+ function annotateGitHubError(error, scope) {
312
+ const message = error && error.message ? error.message : String(error);
313
+ const wrapped = new Error(formatError(`ai ${scope} failed: ${message}`));
314
+ wrapped.cause = error;
315
+ wrapped.code = error && error.code ? error.code : 'AI_GITHUB_PR_ERROR';
316
+ wrapped.details = error && error.details ? error.details : undefined;
317
+ return wrapped;
318
+ }
319
+
320
+ async function runOnboard(repoRoot, options = {}) {
321
+ const role = normalizeRole(options.role || DEFAULT_ONBOARD_ROLE);
322
+ const provider = resolveProviderForProfile(repoRoot, role, options.provider, options.providerExplicit, DEFAULT_ONBOARD_PROVIDER);
323
+ const context = options.context || DEFAULT_ONBOARD_CONTEXT;
324
+ const timeoutMs = normalizeTimeout(options.timeout);
325
+ const inputText = readTextFile(options.input, repoRoot);
326
+ const contextInfo = buildOnboardContext({ role, context, inputText, inputPath: options.input, repoRoot });
327
+ const prompt = contextInfo.prompt;
328
+ let invocation;
329
+
330
+ try {
331
+ invocation = buildProviderInvocation(provider, {
332
+ prompt,
333
+ cwd: repoRoot,
334
+ timeoutMs,
335
+ });
336
+ } catch (error) {
337
+ throw annotateProviderError(error, 'onboard');
338
+ }
339
+
340
+ if (options.dryRun) {
341
+ const report = {
342
+ task: 'onboard',
343
+ provider,
344
+ role,
345
+ contextPack: context,
346
+ invocation,
347
+ onboardingPlan: contextInfo.plan,
348
+ };
349
+ process.stdout.write(formatDryRunReport(report));
350
+ return report;
351
+ }
352
+
353
+ let result;
354
+ try {
355
+ result = await (options.runProviderFn || runProvider)(provider, {
356
+ prompt,
357
+ cwd: repoRoot,
358
+ timeoutMs,
359
+ dryRun: false,
360
+ probe: options.probe,
361
+ spawn: options.spawn,
362
+ tempRoot: options.tempRoot,
363
+ tempFileName: options.tempFileName,
364
+ tempFilePrefix: options.tempFilePrefix,
365
+ });
366
+ } catch (error) {
367
+ throw annotateProviderError(error, 'onboard');
368
+ }
369
+
370
+ writeProviderOutput(result);
371
+
372
+ if (!result.ok) {
373
+ throw annotateProviderError(result.error || new Error('provider run failed'), 'onboard');
374
+ }
375
+
376
+ return {
377
+ task: 'onboard',
378
+ provider,
379
+ role,
380
+ contextPack: context,
381
+ invocation,
382
+ onboardingPlan: contextInfo.plan,
383
+ result,
384
+ };
385
+ }
386
+
387
+ async function runPrepareContext(repoRoot, options = {}) {
388
+ const draftPack = buildContextPreparationDrafts(repoRoot);
389
+ const report = {
390
+ task: 'prepare-context',
391
+ dryRun: options.dryRun === true,
392
+ docs: draftPack.docs.map((doc) => doc.path),
393
+ plan: draftPack.plan,
394
+ };
395
+
396
+ if (options.dryRun) {
397
+ process.stdout.write(formatContextPreparationReport({
398
+ dryRun: true,
399
+ docs: draftPack.docs,
400
+ plan: draftPack.plan,
401
+ writtenDocs: [],
402
+ }));
403
+ return report;
404
+ }
405
+
406
+ const writtenDocs = writeDraftDocs(repoRoot, draftPack.docs);
407
+ process.stdout.write(formatContextPreparationReport({
408
+ dryRun: false,
409
+ docs: draftPack.docs,
410
+ plan: draftPack.plan,
411
+ writtenDocs,
412
+ }));
413
+
414
+ return {
415
+ ...report,
416
+ writtenDocs,
417
+ };
418
+ }
419
+
420
+ async function runPlan(repoRoot, options = {}) {
421
+ const phase = normalizePlannerPhase(options.phase || DEFAULT_PLAN_PHASE);
422
+ const role = normalizeRole(options.role || DEFAULT_PLAN_ROLE);
423
+ const provider = resolveProviderForProfile(repoRoot, role, options.provider, options.providerExplicit, DEFAULT_PLAN_PROVIDER);
424
+ const context = options.context || DEFAULT_PLAN_CONTEXT;
425
+ const timeoutMs = normalizeTimeout(options.timeout);
426
+ let inputPath = options.input || '';
427
+
428
+ if (phase === 'spec') {
429
+ const resolved = resolveReviewedTechnicalPlanInput(repoRoot, inputPath || undefined);
430
+ inputPath = resolved.inputPath;
431
+ const inputText = readTextFileOrEmpty(inputPath, repoRoot);
432
+ const manifest = buildSpecGenerationManifest({
433
+ inputPath,
434
+ inputText,
435
+ repoRoot,
436
+ specSlug: options.specSlug,
437
+ });
438
+
439
+ if (options.dryRun) {
440
+ const report = {
441
+ task: 'plan',
442
+ phase,
443
+ manifest,
444
+ };
445
+ process.stdout.write(formatSpecDryRunReport({ manifest, repoRoot }));
446
+ return report;
447
+ }
448
+
449
+ const result = generateSpecArtifacts(repoRoot, {
450
+ input: inputPath,
451
+ specSlug: options.specSlug,
452
+ });
453
+ process.stdout.write(formatSpecGenerationResult(result, repoRoot));
454
+
455
+ return {
456
+ task: 'plan',
457
+ phase,
458
+ specSlug: result.manifest.slug,
459
+ specDir: path.relative(repoRoot, result.specDir).split(path.sep).join('/'),
460
+ files: result.files.map((filePath) => path.relative(repoRoot, filePath).split(path.sep).join('/')),
461
+ manifest: result.manifest,
462
+ };
463
+ }
464
+
465
+ assertPlannerPhaseReady(phase);
466
+
467
+ if (phase === 'technical-plan') {
468
+ const resolved = resolveApprovedPlannerInput(repoRoot, phase, inputPath || undefined);
469
+ inputPath = resolved.inputPath;
470
+ }
471
+
472
+ if (!inputPath) {
473
+ throw new Error(formatError(`missing input file for ai plan phase '${phase}'`));
474
+ }
475
+
476
+ const inputText = readTextFile(inputPath, repoRoot);
477
+ const contextInfo = buildPlanContext({
478
+ role,
479
+ context,
480
+ phase,
481
+ inputText,
482
+ inputPath,
483
+ repoRoot,
484
+ });
485
+ const prompt = contextInfo.prompt;
486
+ let invocation;
487
+
488
+ try {
489
+ invocation = buildProviderInvocation(provider, {
490
+ prompt,
491
+ cwd: repoRoot,
492
+ timeoutMs,
493
+ });
494
+ } catch (error) {
495
+ throw annotateProviderError(error, 'plan', phase);
496
+ }
497
+
498
+ if (options.dryRun) {
499
+ const report = {
500
+ task: 'plan',
501
+ provider,
502
+ role,
503
+ contextPack: contextInfo.pack.packName,
504
+ phase,
505
+ invocation,
506
+ };
507
+ process.stdout.write(formatDryRunReport(report));
508
+ return report;
509
+ }
510
+
511
+ let result;
512
+ try {
513
+ result = await (options.runProviderFn || runProvider)(provider, {
514
+ prompt,
515
+ cwd: repoRoot,
516
+ timeoutMs,
517
+ dryRun: false,
518
+ probe: options.probe,
519
+ spawn: options.spawn,
520
+ tempRoot: options.tempRoot,
521
+ tempFileName: options.tempFileName,
522
+ tempFilePrefix: options.tempFilePrefix,
523
+ });
524
+ } catch (error) {
525
+ throw annotateProviderError(error, 'plan', phase);
526
+ }
527
+
528
+ writeProviderOutput(result);
529
+
530
+ if (!result.ok) {
531
+ throw annotateProviderError(result.error || new Error('provider run failed'), 'plan', phase);
532
+ }
533
+
534
+ savePlannerDraft(repoRoot, phase, inputPath, [result.stdout, result.stderr].filter(Boolean).join(''));
535
+
536
+ return {
537
+ task: 'plan',
538
+ provider,
539
+ role,
540
+ contextPack: contextInfo.pack.packName,
541
+ phase,
542
+ invocation,
543
+ result,
544
+ };
545
+ }
546
+
547
+ async function runReviewPlan(repoRoot, options = {}) {
548
+ const role = 'planner';
549
+ const provider = resolveProviderForProfile(repoRoot, 'reviewer', options.provider, options.providerExplicit, DEFAULT_PLAN_PROVIDER);
550
+ const context = options.context || DEFAULT_PLAN_CONTEXT;
551
+ const timeoutMs = normalizeTimeout(options.timeout);
552
+ const resolved = resolveTechnicalPlanReviewInput(repoRoot, options.input || undefined);
553
+ const inputPath = resolved.inputPath;
554
+ const inputText = readTextFile(inputPath, repoRoot);
555
+ const pack = buildContextPackMetadata({
556
+ role,
557
+ packName: context,
558
+ repoRoot,
559
+ });
560
+ const built = buildPlanReviewPrompt({
561
+ pack,
562
+ inputText,
563
+ inputPath,
564
+ });
565
+ let invocation;
566
+
567
+ try {
568
+ invocation = buildProviderInvocation(provider, {
569
+ prompt: built.prompt,
570
+ cwd: repoRoot,
571
+ timeoutMs,
572
+ });
573
+ } catch (error) {
574
+ throw annotateProviderError(error, 'review-plan');
575
+ }
576
+
577
+ if (options.dryRun) {
578
+ const report = {
579
+ task: 'review-plan',
580
+ provider,
581
+ role: 'reviewer',
582
+ contextPack: pack.packName,
583
+ invocation,
584
+ promptSource: built.promptSource,
585
+ inputPath,
586
+ inputKind: resolved.kind,
587
+ inputVersion: resolved.version,
588
+ };
589
+ process.stdout.write(formatDryRunReport({
590
+ task: 'review-plan',
591
+ provider,
592
+ role: 'reviewer',
593
+ contextPack: pack.packName,
594
+ phase: 'plan-review',
595
+ invocation,
596
+ }));
597
+ process.stdout.write(`Prompt source: ${built.promptSource}\n`);
598
+ process.stdout.write(`Input file: ${inputPath}\n`);
599
+ process.stdout.write(`Input kind: ${resolved.kind}\n`);
600
+ if (resolved.version) {
601
+ process.stdout.write(`Input version: v${resolved.version}\n`);
602
+ }
603
+ return report;
604
+ }
605
+
606
+ let result;
607
+ try {
608
+ result = await (options.runProviderFn || runProvider)(provider, {
609
+ prompt: built.prompt,
610
+ cwd: repoRoot,
611
+ timeoutMs,
612
+ dryRun: false,
613
+ probe: options.probe,
614
+ spawn: options.spawn,
615
+ tempRoot: options.tempRoot,
616
+ tempFileName: options.tempFileName,
617
+ tempFilePrefix: options.tempFilePrefix,
618
+ });
619
+ } catch (error) {
620
+ throw annotateProviderError(error, 'review-plan');
621
+ }
622
+
623
+ writeProviderOutput(result);
624
+
625
+ if (!result.ok) {
626
+ throw annotateProviderError(result.error || new Error('provider run failed'), 'review-plan');
627
+ }
628
+
629
+ const saved = savePlanReview(repoRoot, {
630
+ contents: [result.stdout, result.stderr].filter(Boolean).join(''),
631
+ inputPath,
632
+ inputKind: resolved.kind,
633
+ inputVersion: resolved.version,
634
+ });
635
+ const relativePath = path.relative(repoRoot, saved.filePath).split(path.sep).join('/');
636
+ process.stdout.write(`AI plan review saved\nArtifact: ${relativePath}\nPrompt source: ${PLAN_REVIEW_PROMPT_SOURCE}\n`);
637
+
638
+ return {
639
+ task: 'review-plan',
640
+ provider,
641
+ role: 'reviewer',
642
+ contextPack: pack.packName,
643
+ inputPath,
644
+ inputKind: resolved.kind,
645
+ inputVersion: resolved.version,
646
+ filePath: relativePath,
647
+ invocation,
648
+ result,
649
+ };
650
+ }
651
+
652
+ async function runApprove(repoRoot, options = {}) {
653
+ const phase = normalizePlannerPhase(options.phase || DEFAULT_PLAN_PHASE);
654
+ if (phase === 'spec') {
655
+ throw new Error(formatError(`ai approve does not support phase '${phase}'`));
656
+ }
657
+
658
+ if (!options.input && !options.version) {
659
+ throw new Error(formatError(`missing input file for ai approve phase '${phase}'`));
660
+ }
661
+
662
+ const inputText = options.version ? '' : readTextFile(options.input, repoRoot);
663
+
664
+ if (options.dryRun) {
665
+ process.stdout.write(formatApprovalDryRunResult({ phase, input: options.input, version: options.version }));
666
+ return {
667
+ task: 'approve',
668
+ phase,
669
+ input: options.input,
670
+ version: options.version || null,
671
+ dryRun: true,
672
+ };
673
+ }
674
+
675
+ const result = approvePlannerPhase(repoRoot, phase, options.input || '', inputText, {
676
+ version: options.version || undefined,
677
+ });
678
+ process.stdout.write(formatApprovalResult({
679
+ ...result,
680
+ sourceFile: options.input || `draft version ${options.version}`,
681
+ }, repoRoot));
682
+
683
+ return {
684
+ task: 'approve',
685
+ phase,
686
+ input: options.input,
687
+ filePath: path.relative(repoRoot, result.filePath).split(path.sep).join('/'),
688
+ createdAt: result.createdAt,
689
+ version: result.version || null,
690
+ };
691
+ }
692
+
693
+ async function runApprovalStatus(repoRoot) {
694
+ const report = formatApprovalStatusReport(repoRoot);
695
+ process.stdout.write(report);
696
+ return {
697
+ task: 'approval-status',
698
+ report,
699
+ };
700
+ }
701
+
702
+ function formatAgentProfile(profile) {
703
+ const lines = [
704
+ `Role: ${profile.role}`,
705
+ `Provider: ${profile.provider}`,
706
+ `Model: ${profile.model || '(not set)'}`,
707
+ `Label: ${profile.label || '(not set)'}`,
708
+ `Context: ${profile.context || '(not set)'}`,
709
+ `Updated: ${profile.updated_at}`,
710
+ ];
711
+ return `${lines.join('\n')}\n`;
712
+ }
713
+
714
+ function formatAgentProfileList(profiles) {
715
+ const lines = ['AI agent profiles'];
716
+ for (const item of profiles) {
717
+ if (!item.configured) {
718
+ lines.push(`- ${item.role}: not configured`);
719
+ continue;
720
+ }
721
+ const model = item.profile.model ? ` model=${item.profile.model}` : '';
722
+ const label = item.profile.label ? ` label=${item.profile.label}` : '';
723
+ lines.push(`- ${item.role}: provider=${item.profile.provider}${model}${label}`);
724
+ }
725
+ return `${lines.join('\n')}\n`;
726
+ }
727
+
728
+ function runAgent(repoRoot, options = {}) {
729
+ const command = String(options.command || '').trim().toLowerCase();
730
+
731
+ if (command === 'set') {
732
+ if (!options.role) {
733
+ throw new Error(formatError('missing agent role. Use: npx create-quiver ai agent set <planner|executor|reviewer|researcher> --provider <provider>'));
734
+ }
735
+ if (!options.provider) {
736
+ throw new Error(formatError('ai agent set requires --provider. Supported providers: codex, claude, gemini.'));
737
+ }
738
+ const result = setAgentProfile(repoRoot, options.role, {
739
+ context: options.context,
740
+ label: options.label,
741
+ model: options.model,
742
+ provider: options.provider,
743
+ });
744
+ process.stdout.write('AI agent profile saved\n');
745
+ process.stdout.write(formatAgentProfile(result.profile));
746
+ process.stdout.write(`State: ${path.relative(repoRoot, result.filePath).split(path.sep).join('/')}\n`);
747
+ return {
748
+ task: 'agent',
749
+ command,
750
+ profile: result.profile,
751
+ filePath: path.relative(repoRoot, result.filePath).split(path.sep).join('/'),
752
+ };
753
+ }
754
+
755
+ if (command === 'show') {
756
+ if (!options.role) {
757
+ throw new Error(formatError('missing agent role. Use: npx create-quiver ai agent show <planner|executor|reviewer|researcher>'));
758
+ }
759
+ const profile = getAgentProfile(repoRoot, options.role);
760
+ if (!profile) {
761
+ throw new Error(formatError(`agent profile '${options.role}' is not configured. Run: npx create-quiver ai agent set ${options.role} --provider <provider> --model <label>`));
762
+ }
763
+ process.stdout.write(formatAgentProfile(profile));
764
+ return {
765
+ task: 'agent',
766
+ command,
767
+ profile,
768
+ };
769
+ }
770
+
771
+ if (command === 'list' || command === 'ls' || command === '') {
772
+ const profiles = listAgentProfiles(repoRoot);
773
+ process.stdout.write(formatAgentProfileList(profiles));
774
+ process.stdout.write(`State: ${path.relative(repoRoot, agentProfilesPath(repoRoot)).split(path.sep).join('/')}\n`);
775
+ return {
776
+ task: 'agent',
777
+ command: 'list',
778
+ profiles,
779
+ };
780
+ }
781
+
782
+ throw new Error(formatError(`unsupported ai agent subcommand: ${command}. Supported tasks: set, list, show`));
783
+ }
784
+
785
+ async function runGitHubTask(repoRoot, options = {}, mode = 'pr') {
786
+ const dryRun = options.dryRun === true;
787
+ let report;
788
+
789
+ try {
790
+ report = await (options.preflightFn || preflightGitHubPr)(repoRoot, {
791
+ remote: options.remote,
792
+ sshHostAlias: options.sshHostAlias,
793
+ identityFile: options.identityFile,
794
+ gitFlowGuidePath: options.gitFlowGuidePath,
795
+ ghCommand: options.ghCommand,
796
+ ghProbe: options.ghProbe,
797
+ ghAuthProbe: options.ghAuthProbe,
798
+ ghProbeArgs: options.ghProbeArgs,
799
+ ghAuthArgs: options.ghAuthArgs,
800
+ blockedBranches: options.blockedBranches,
801
+ });
802
+ } catch (error) {
803
+ throw annotateGitHubError(error, mode);
804
+ }
805
+
806
+ process.stdout.write(formatPreflightReport(report, { mode, dryRun }));
807
+
808
+ return {
809
+ task: mode,
810
+ dryRun,
811
+ preflight: report,
812
+ };
813
+ }
814
+
815
+ async function runPr(repoRoot, options = {}) {
816
+ const dryRun = options.dryRun === true;
817
+ const create = options.create === true;
818
+ let preflight;
819
+
820
+ try {
821
+ preflight = await (options.preflightFn || preflightGitHubPr)(repoRoot, {
822
+ remote: options.remote,
823
+ sshHostAlias: options.sshHostAlias,
824
+ identityFile: options.identityFile,
825
+ gitFlowGuidePath: options.gitFlowGuidePath,
826
+ ghCommand: options.ghCommand,
827
+ ghProbe: options.ghProbe,
828
+ ghAuthProbe: options.ghAuthProbe,
829
+ ghProbeArgs: options.ghProbeArgs,
830
+ ghAuthArgs: options.ghAuthArgs,
831
+ blockedBranches: options.blockedBranches,
832
+ });
833
+ } catch (error) {
834
+ throw annotateGitHubError(error, 'pr');
835
+ }
836
+
837
+ let plan;
838
+ try {
839
+ plan = buildPrCreatePlan(repoRoot, preflight, {
840
+ baseBranch: options.baseBranch,
841
+ ghCommand: options.ghCommand,
842
+ input: options.input,
843
+ prBodyPath: options.prBodyPath,
844
+ title: options.title,
845
+ });
846
+ } catch (error) {
847
+ throw annotateGitHubError(error, 'pr');
848
+ }
849
+
850
+ if (dryRun || !create) {
851
+ process.stdout.write(formatPrCreateReport({ preflight, plan }, { dryRun, create }));
852
+ return {
853
+ task: 'pr',
854
+ dryRun,
855
+ create,
856
+ preflight,
857
+ plan,
858
+ };
859
+ }
860
+
861
+ let result;
862
+ try {
863
+ result = runGhPrCreate(plan, {
864
+ ghCreateRunner: options.ghCreateRunner,
865
+ });
866
+ } catch (error) {
867
+ throw annotateGitHubError(error, 'pr');
868
+ }
869
+
870
+ process.stdout.write(formatPrCreateReport({ preflight, plan, result }, { dryRun: false, create: true }));
871
+ return {
872
+ task: 'pr',
873
+ dryRun: false,
874
+ create: true,
875
+ preflight,
876
+ plan,
877
+ result,
878
+ };
879
+ }
880
+
881
+ async function runDoctor(repoRoot, options = {}) {
882
+ return runGitHubTask(repoRoot, options, 'doctor');
883
+ }
884
+
885
+ module.exports = {
886
+ DEFAULT_ONBOARD_CONTEXT,
887
+ DEFAULT_ONBOARD_PROVIDER,
888
+ DEFAULT_ONBOARD_ROLE,
889
+ DEFAULT_PLAN_CONTEXT,
890
+ DEFAULT_PLAN_PHASE,
891
+ DEFAULT_PLAN_PROVIDER,
892
+ DEFAULT_PLAN_ROLE,
893
+ PlannerPhaseError,
894
+ annotateProviderError,
895
+ buildOnboardContext,
896
+ buildPlanContext,
897
+ formatDryRunReport,
898
+ formatSpecGenerationResult,
899
+ formatSpecDryRunReport,
900
+ normalizeTimeout,
901
+ readTextFile,
902
+ runAgent,
903
+ runDoctor,
904
+ runExecutePlan,
905
+ runExecuteSlice,
906
+ runPromptSlice,
907
+ runApprove,
908
+ runApprovalStatus,
909
+ runPrepareContext,
910
+ runReviewPlan,
911
+ runPr,
912
+ runOnboard,
913
+ runPlan,
914
+ writeProviderOutput,
915
+ };