create-quiver 0.10.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/BACKLOG.md +16 -17
  2. package/CHANGELOG.md +78 -0
  3. package/README.md +208 -41
  4. package/README_FOR_AI.md +50 -24
  5. package/ROADMAP.md +34 -11
  6. package/docs/AI_CONTEXT.md.template +2 -0
  7. package/docs/AI_ONBOARDING_PROMPT.md.template +31 -18
  8. package/docs/COMMANDS.md.template +90 -16
  9. package/docs/CONTEXTO.md.template +2 -0
  10. package/docs/DECISIONS.md.template +1 -0
  11. package/docs/INDEX.md.template +20 -18
  12. package/docs/STATUS.md.template +6 -1
  13. package/docs/SUPPORT_MATRIX.md.template +2 -2
  14. package/docs/TROUBLESHOOTING.md.template +50 -0
  15. package/docs/WORKFLOW.md.template +27 -17
  16. package/package.json +27 -4
  17. package/package.template.json +13 -1
  18. package/scripts/init-docs.sh +11 -4
  19. package/scripts/package-quiver.sh +18 -2
  20. package/specs/quiver-v22-guided-ai-workflow/EVIDENCE_REPORT.md +58 -0
  21. package/specs/quiver-v22-guided-ai-workflow/EXECUTION_PLAN.md +88 -0
  22. package/specs/quiver-v22-guided-ai-workflow/SPEC.md +228 -0
  23. package/specs/quiver-v22-guided-ai-workflow/STATUS.md +42 -0
  24. package/specs/quiver-v22-guided-ai-workflow/pr.md +104 -0
  25. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +35 -0
  26. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
  27. package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/slice.json +51 -0
  28. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/CLOSURE_BRIEF.md +31 -0
  29. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/EXECUTION_BRIEF.md +58 -0
  30. package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/slice.json +55 -0
  31. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/CLOSURE_BRIEF.md +30 -0
  32. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/EXECUTION_BRIEF.md +57 -0
  33. package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/slice.json +57 -0
  34. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/CLOSURE_BRIEF.md +32 -0
  35. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/EXECUTION_BRIEF.md +56 -0
  36. package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/slice.json +56 -0
  37. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/CLOSURE_BRIEF.md +33 -0
  38. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/EXECUTION_BRIEF.md +56 -0
  39. package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/slice.json +58 -0
  40. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/CLOSURE_BRIEF.md +32 -0
  41. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/EXECUTION_BRIEF.md +56 -0
  42. package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/slice.json +54 -0
  43. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/CLOSURE_BRIEF.md +32 -0
  44. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/EXECUTION_BRIEF.md +58 -0
  45. package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/slice.json +57 -0
  46. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/CLOSURE_BRIEF.md +32 -0
  47. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/EXECUTION_BRIEF.md +58 -0
  48. package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/slice.json +55 -0
  49. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/CLOSURE_BRIEF.md +32 -0
  50. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/EXECUTION_BRIEF.md +58 -0
  51. package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/slice.json +53 -0
  52. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/CLOSURE_BRIEF.md +33 -0
  53. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/EXECUTION_BRIEF.md +59 -0
  54. package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/slice.json +59 -0
  55. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +34 -0
  56. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +58 -0
  57. package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/slice.json +60 -0
  58. package/specs/quiver-v23-guided-flow-productization/EVIDENCE_REPORT.md +80 -0
  59. package/specs/quiver-v23-guided-flow-productization/EXECUTION_PLAN.md +80 -0
  60. package/specs/quiver-v23-guided-flow-productization/SPEC.md +203 -0
  61. package/specs/quiver-v23-guided-flow-productization/STATUS.md +39 -0
  62. package/specs/quiver-v23-guided-flow-productization/pr.md +119 -0
  63. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +30 -0
  64. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
  65. package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/slice.json +51 -0
  66. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/CLOSURE_BRIEF.md +33 -0
  67. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/EXECUTION_BRIEF.md +35 -0
  68. package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/slice.json +56 -0
  69. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/CLOSURE_BRIEF.md +31 -0
  70. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/EXECUTION_BRIEF.md +29 -0
  71. package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/slice.json +55 -0
  72. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/CLOSURE_BRIEF.md +33 -0
  73. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/EXECUTION_BRIEF.md +29 -0
  74. package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/slice.json +54 -0
  75. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/CLOSURE_BRIEF.md +32 -0
  76. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/EXECUTION_BRIEF.md +30 -0
  77. package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/slice.json +59 -0
  78. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/CLOSURE_BRIEF.md +31 -0
  79. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/EXECUTION_BRIEF.md +29 -0
  80. package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/slice.json +53 -0
  81. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/CLOSURE_BRIEF.md +33 -0
  82. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/EXECUTION_BRIEF.md +30 -0
  83. package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/slice.json +54 -0
  84. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/CLOSURE_BRIEF.md +33 -0
  85. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/EXECUTION_BRIEF.md +30 -0
  86. package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/slice.json +55 -0
  87. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/CLOSURE_BRIEF.md +32 -0
  88. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/EXECUTION_BRIEF.md +30 -0
  89. package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/slice.json +55 -0
  90. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/CLOSURE_BRIEF.md +33 -0
  91. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/EXECUTION_BRIEF.md +34 -0
  92. package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/slice.json +57 -0
  93. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +33 -0
  94. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +32 -0
  95. package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/slice.json +63 -0
  96. package/specs/quiver-v24-dx-onboarding-hardening/EVIDENCE_REPORT.md +55 -0
  97. package/specs/quiver-v24-dx-onboarding-hardening/EXECUTION_PLAN.md +43 -0
  98. package/specs/quiver-v24-dx-onboarding-hardening/SPEC.md +149 -0
  99. package/specs/quiver-v24-dx-onboarding-hardening/STATUS.md +31 -0
  100. package/specs/quiver-v24-dx-onboarding-hardening/pr.md +76 -0
  101. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +31 -0
  102. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +52 -0
  103. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/slice.json +51 -0
  104. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/CLOSURE_BRIEF.md +38 -0
  105. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/EXECUTION_BRIEF.md +53 -0
  106. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/slice.json +55 -0
  107. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/CLOSURE_BRIEF.md +33 -0
  108. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/EXECUTION_BRIEF.md +50 -0
  109. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/slice.json +52 -0
  110. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/CLOSURE_BRIEF.md +33 -0
  111. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/EXECUTION_BRIEF.md +50 -0
  112. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/slice.json +53 -0
  113. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/CLOSURE_BRIEF.md +33 -0
  114. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/EXECUTION_BRIEF.md +50 -0
  115. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/slice.json +70 -0
  116. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/CLOSURE_BRIEF.md +36 -0
  117. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/EXECUTION_BRIEF.md +49 -0
  118. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/slice.json +52 -0
  119. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/CLOSURE_BRIEF.md +43 -0
  120. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/EXECUTION_BRIEF.md +53 -0
  121. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/slice.json +60 -0
  122. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/CLOSURE_BRIEF.md +32 -0
  123. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/EXECUTION_BRIEF.md +50 -0
  124. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/slice.json +51 -0
  125. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/CLOSURE_BRIEF.md +34 -0
  126. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/EXECUTION_BRIEF.md +52 -0
  127. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/slice.json +54 -0
  128. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/CLOSURE_BRIEF.md +34 -0
  129. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/EXECUTION_BRIEF.md +51 -0
  130. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/slice.json +59 -0
  131. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +33 -0
  132. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +54 -0
  133. package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/slice.json +76 -0
  134. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/EVIDENCE_REPORT.md +293 -0
  135. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/EXECUTION_PLAN.md +58 -0
  136. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/SPEC.md +242 -0
  137. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/STATUS.md +35 -0
  138. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/pr.md +77 -0
  139. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +34 -0
  140. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +52 -0
  141. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-00-spec-foundation/slice.json +52 -0
  142. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/CLOSURE_BRIEF.md +36 -0
  143. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/EXECUTION_BRIEF.md +52 -0
  144. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-01-cli-contract-compatibility/slice.json +56 -0
  145. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/CLOSURE_BRIEF.md +43 -0
  146. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/EXECUTION_BRIEF.md +54 -0
  147. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-02-run-state-phase-locks/slice.json +52 -0
  148. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/CLOSURE_BRIEF.md +35 -0
  149. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/EXECUTION_BRIEF.md +53 -0
  150. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-03-safe-ai-onboarding-docs/slice.json +54 -0
  151. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/CLOSURE_BRIEF.md +34 -0
  152. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/EXECUTION_BRIEF.md +54 -0
  153. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-04-agent-profiles-adapters/slice.json +52 -0
  154. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/CLOSURE_BRIEF.md +34 -0
  155. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/EXECUTION_BRIEF.md +54 -0
  156. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-05-approval-gates/slice.json +53 -0
  157. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/CLOSURE_BRIEF.md +33 -0
  158. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/EXECUTION_BRIEF.md +56 -0
  159. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-06-spec-slice-generator/slice.json +55 -0
  160. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/CLOSURE_BRIEF.md +33 -0
  161. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/EXECUTION_BRIEF.md +54 -0
  162. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-07-slice-execution-planner/slice.json +52 -0
  163. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/CLOSURE_BRIEF.md +39 -0
  164. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/EXECUTION_BRIEF.md +56 -0
  165. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-08-controlled-slice-execution/slice.json +53 -0
  166. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/CLOSURE_BRIEF.md +38 -0
  167. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/EXECUTION_BRIEF.md +57 -0
  168. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-09-git-worktree-pr-lifecycle/slice.json +52 -0
  169. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/CLOSURE_BRIEF.md +39 -0
  170. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/EXECUTION_BRIEF.md +55 -0
  171. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-10-validation-errors-fixtures/slice.json +56 -0
  172. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/CLOSURE_BRIEF.md +36 -0
  173. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/EXECUTION_BRIEF.md +54 -0
  174. package/specs/quiver-v25-ai-first-lifecycle-orchestrator/slices/slice-11-export-dashboard-migration/slice.json +53 -0
  175. package/specs/quiver-v26-0121-smoke-hardening/EVIDENCE_REPORT.md +208 -0
  176. package/specs/quiver-v26-0121-smoke-hardening/EXECUTION_PLAN.md +57 -0
  177. package/specs/quiver-v26-0121-smoke-hardening/SPEC.md +137 -0
  178. package/specs/quiver-v26-0121-smoke-hardening/STATUS.md +32 -0
  179. package/specs/quiver-v26-0121-smoke-hardening/pr.md +96 -0
  180. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/CLOSURE_BRIEF.md +35 -0
  181. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/EXECUTION_BRIEF.md +55 -0
  182. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-00-docs-foundation/slice.json +73 -0
  183. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/CLOSURE_BRIEF.md +38 -0
  184. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/EXECUTION_BRIEF.md +51 -0
  185. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-01-cli-help-version-contract/slice.json +76 -0
  186. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/CLOSURE_BRIEF.md +37 -0
  187. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/EXECUTION_BRIEF.md +52 -0
  188. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-02-init-doc-links-and-flow-guidance/slice.json +75 -0
  189. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/CLOSURE_BRIEF.md +37 -0
  190. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/EXECUTION_BRIEF.md +53 -0
  191. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-03-ai-approval-review-consistency/slice.json +77 -0
  192. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/CLOSURE_BRIEF.md +35 -0
  193. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/EXECUTION_BRIEF.md +52 -0
  194. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-04-local-validation-brief-contracts/slice.json +77 -0
  195. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/CLOSURE_BRIEF.md +34 -0
  196. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/EXECUTION_BRIEF.md +54 -0
  197. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-05-demo-scaffold-readiness/slice.json +84 -0
  198. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/CLOSURE_BRIEF.md +35 -0
  199. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/EXECUTION_BRIEF.md +53 -0
  200. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-06-plan-graph-scope-performance/slice.json +82 -0
  201. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/CLOSURE_BRIEF.md +35 -0
  202. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/EXECUTION_BRIEF.md +55 -0
  203. package/specs/quiver-v26-0121-smoke-hardening/slices/slice-07-smoke-release-readiness/slice.json +92 -0
  204. package/src/create-quiver/commands/ai.js +1060 -37
  205. package/src/create-quiver/commands/demo.js +22 -0
  206. package/src/create-quiver/commands/evidence.js +37 -0
  207. package/src/create-quiver/commands/flow.js +562 -0
  208. package/src/create-quiver/commands/graph.js +19 -4
  209. package/src/create-quiver/commands/next.js +28 -0
  210. package/src/create-quiver/commands/plan.js +9 -6
  211. package/src/create-quiver/commands/prepare.js +236 -0
  212. package/src/create-quiver/commands/spec.js +133 -0
  213. package/src/create-quiver/index.js +1010 -31
  214. package/src/create-quiver/lib/actionable-error.js +27 -0
  215. package/src/create-quiver/lib/agent-profiles.js +148 -0
  216. package/src/create-quiver/lib/ai/context-packs.js +16 -0
  217. package/src/create-quiver/lib/ai/execution-plan.js +377 -11
  218. package/src/create-quiver/lib/ai/executor.js +633 -24
  219. package/src/create-quiver/lib/ai/export-state.js +534 -0
  220. package/src/create-quiver/lib/ai/github.js +279 -0
  221. package/src/create-quiver/lib/ai/onboarding-template.js +578 -0
  222. package/src/create-quiver/lib/ai/plan-review.js +286 -0
  223. package/src/create-quiver/lib/ai/providers.js +5 -3
  224. package/src/create-quiver/lib/ai/run-state.js +414 -0
  225. package/src/create-quiver/lib/ai/safety.js +5 -0
  226. package/src/create-quiver/lib/ai/spec-generator.js +12 -0
  227. package/src/create-quiver/lib/ai/spec-templates.js +80 -11
  228. package/src/create-quiver/lib/approvals.js +369 -0
  229. package/src/create-quiver/lib/demo.js +832 -0
  230. package/src/create-quiver/lib/doctor.js +309 -0
  231. package/src/create-quiver/lib/evidence.js +115 -0
  232. package/src/create-quiver/lib/handoff.js +81 -12
  233. package/src/create-quiver/lib/init-docs.js +302 -17
  234. package/src/create-quiver/lib/init-layout.js +34 -1
  235. package/src/create-quiver/lib/json.js +53 -3
  236. package/src/create-quiver/lib/lifecycle.js +6 -0
  237. package/src/create-quiver/lib/package-safety.js +117 -0
  238. package/src/create-quiver/lib/readiness.js +103 -21
  239. package/src/create-quiver/lib/scope.js +50 -7
  240. package/src/create-quiver/lib/slice-graph.js +138 -37
  241. package/src/create-quiver/lib/slice.js +14 -9
  242. package/src/create-quiver/lib/spec-worktrees.js +363 -0
@@ -1,8 +1,12 @@
1
1
  const fs = require('node:fs');
2
2
  const path = require('node:path');
3
+ const cp = require('node:child_process');
3
4
 
4
5
  const { buildContextPackMetadata, normalizeRole } = require('./context-packs');
5
6
  const { buildProviderInvocation, runProvider } = require('./providers');
7
+ const { resolveProfileProvider } = require('../agent-profiles');
8
+ const { currentBranch, runGit } = require('../git');
9
+ const { redactSecrets, truncateText } = require('../evidence');
6
10
  const { captureWorktreeSnapshot, validateScopeSnapshot } = require('../scope');
7
11
  const { resolveSliceContext } = require('../slice');
8
12
 
@@ -74,6 +78,213 @@ function formatList(items) {
74
78
  return items.map((item) => `- ${item}`);
75
79
  }
76
80
 
81
+ function uniqueList(items) {
82
+ return Array.from(new Set((Array.isArray(items) ? items : []).map((item) => String(item)).filter(Boolean)));
83
+ }
84
+
85
+ function escapeRegex(value) {
86
+ return String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
87
+ }
88
+
89
+ function extractMarkdownHeading(text) {
90
+ const match = String(text || '').match(/^#\s+(.+)$/m);
91
+ return match ? match[1].trim() : '';
92
+ }
93
+
94
+ function extractMarkdownSection(text, headings) {
95
+ const lines = String(text || '').split(/\r?\n/);
96
+ const normalized = new Set(headings.map((heading) => String(heading).trim().toLowerCase()));
97
+ const section = [];
98
+ let capture = false;
99
+
100
+ for (const line of lines) {
101
+ const heading = line.match(/^##\s+(.+)$/);
102
+ if (heading) {
103
+ const key = heading[1].trim().toLowerCase();
104
+ if (normalized.has(key)) {
105
+ capture = true;
106
+ continue;
107
+ }
108
+ if (capture) {
109
+ break;
110
+ }
111
+ }
112
+
113
+ if (capture) {
114
+ section.push(line);
115
+ }
116
+ }
117
+
118
+ return section.join('\n').trim();
119
+ }
120
+
121
+ function buildSpecExcerpt(repoRoot, slice) {
122
+ const specPath = path.join(slice.specDirAbs, 'SPEC.md');
123
+ if (!fs.existsSync(specPath)) {
124
+ return {
125
+ path: toRelativePath(repoRoot, specPath),
126
+ lines: ['- n/a'],
127
+ };
128
+ }
129
+
130
+ const text = fs.readFileSync(specPath, 'utf8');
131
+ const title = extractMarkdownHeading(text);
132
+ const objective = extractMarkdownSection(text, ['Objective', 'Objetivo']);
133
+ const lines = [];
134
+
135
+ if (title) {
136
+ lines.push(`- Title: ${title}`);
137
+ }
138
+ if (objective) {
139
+ lines.push(`- Objective: ${objective.replace(/\s+/g, ' ').slice(0, 500)}`);
140
+ }
141
+ if (lines.length === 0) {
142
+ lines.push('- SPEC.md exists, but no short title/objective excerpt was found.');
143
+ }
144
+
145
+ return {
146
+ path: toRelativePath(repoRoot, specPath),
147
+ lines,
148
+ };
149
+ }
150
+
151
+ function buildManualExecutorPrompt({ repoRoot, slicePath, role, context, tokenLimit } = {}) {
152
+ const executorContext = buildExecuteSliceContext({
153
+ repoRoot,
154
+ slicePath,
155
+ role: role || DEFAULT_EXECUTE_ROLE,
156
+ context: context || DEFAULT_EXECUTE_CONTEXT,
157
+ });
158
+ const canonicalRepoRoot = canonicalizeRepoRoot(repoRoot);
159
+ const closurePath = path.join(path.dirname(executorContext.slice.sliceAbs), 'CLOSURE_BRIEF.md');
160
+ const closureText = readTextFile(closurePath, canonicalRepoRoot);
161
+ const relativeClosurePath = toRelativePath(canonicalRepoRoot, closurePath);
162
+ const specExcerpt = buildSpecExcerpt(canonicalRepoRoot, executorContext.slice);
163
+ const slice = executorContext.slice;
164
+ const objective = String(slice.json.objective || slice.json.description || slice.sliceId).trim();
165
+ const restrictions = [
166
+ 'Do not read the whole repo.',
167
+ 'Do not modify files outside the allowed files.',
168
+ 'Before editing, list the files you will read and the files you expect to modify.',
169
+ 'Do not add unrequested features.',
170
+ 'Do not refactor architecture unless the slice explicitly requires it.',
171
+ 'If another file is needed, justify why before reading it.',
172
+ 'If blocked, stop and report the blocker before improvising.',
173
+ ];
174
+ const outputFormat = [
175
+ '## Cambios realizados',
176
+ '## Archivos modificados',
177
+ '## Comandos ejecutados',
178
+ '## Validaciones',
179
+ '## Riesgos pendientes',
180
+ '## Proximo paso recomendado',
181
+ ];
182
+ const promptLines = [
183
+ 'Act as a WDD + SDD executor agent.',
184
+ '',
185
+ 'MODE: controlled SLICE execution.',
186
+ '',
187
+ 'Slice objective:',
188
+ objective || 'n/a',
189
+ '',
190
+ 'Minimal context:',
191
+ `- Spec: ${slice.specSlug}`,
192
+ `- Slice: ${slice.sliceId}`,
193
+ `- Slice file: ${slice.sliceRel}`,
194
+ `- Execution brief: ${executorContext.briefPath}`,
195
+ `- Closure brief: ${relativeClosurePath}`,
196
+ '',
197
+ 'Relevant SPEC excerpts:',
198
+ `- Source: ${specExcerpt.path}`,
199
+ ...specExcerpt.lines,
200
+ '',
201
+ 'Expected read paths:',
202
+ ...formatList(executorContext.expectedReadPaths),
203
+ '',
204
+ 'Allowed files:',
205
+ ...formatList(executorContext.allowedFiles),
206
+ '',
207
+ 'Restrictions:',
208
+ ...formatList(restrictions),
209
+ '',
210
+ 'Acceptance criteria:',
211
+ ...formatList(slice.acceptance),
212
+ '',
213
+ 'Validation commands:',
214
+ ...formatList(executorContext.validationCommands),
215
+ '',
216
+ 'Validation hints:',
217
+ ...formatList(executorContext.validationHints),
218
+ '',
219
+ 'Exact deliverable expected:',
220
+ '- Implement only this slice.',
221
+ '- Keep the change inside the allowed files.',
222
+ '- Leave evidence in the final report.',
223
+ '',
224
+ 'Required final report format:',
225
+ ...outputFormat.map((line) => `- ${line}`),
226
+ '',
227
+ `Suggested token limit: ${Number(tokenLimit) > 0 ? Number(tokenLimit) : 3000}`,
228
+ '',
229
+ 'Execution brief content:',
230
+ executorContext.briefText.trimEnd(),
231
+ '',
232
+ 'Closure brief content:',
233
+ closureText.trimEnd(),
234
+ ];
235
+
236
+ return {
237
+ allowedFiles: executorContext.allowedFiles,
238
+ closurePath: relativeClosurePath,
239
+ prompt: `${promptLines.join('\n')}\n`,
240
+ slice,
241
+ specExcerpt,
242
+ validationCommands: executorContext.validationCommands,
243
+ };
244
+ }
245
+
246
+ function runPromptSlice(repoRoot, options = {}) {
247
+ if (!options.slice) {
248
+ throw new Error(formatError('missing required --slice path for ai prompt-slice'));
249
+ }
250
+
251
+ const built = buildManualExecutorPrompt({
252
+ repoRoot,
253
+ slicePath: options.slice,
254
+ tokenLimit: options.tokenLimit,
255
+ });
256
+ process.stdout.write(built.prompt);
257
+
258
+ return {
259
+ task: 'prompt-slice',
260
+ slice: built.slice.sliceId,
261
+ specSlug: built.slice.specSlug,
262
+ prompt: built.prompt,
263
+ };
264
+ }
265
+
266
+ function buildRecoveryGuidance(slice) {
267
+ const sliceRef = slice && slice.sliceRel ? slice.sliceRel : '<slice.json>';
268
+ return [
269
+ 'Recovery:',
270
+ `- Retry: npx create-quiver ai execute-slice --slice ${sliceRef}`,
271
+ '- Abort: inspect the local changes, then manually revert or stash anything you do not want to keep.',
272
+ '- Commit: rerun with --commit only after provider, scope, and validation pass.',
273
+ ].join('\n');
274
+ }
275
+
276
+ function appendRecovery(error, slice) {
277
+ if (!error || !error.message || error.message.includes('Recovery:')) {
278
+ return error;
279
+ }
280
+
281
+ const wrapped = new Error(`${error.message}\n\n${buildRecoveryGuidance(slice)}`);
282
+ wrapped.cause = error;
283
+ wrapped.code = error.code;
284
+ wrapped.details = error.details;
285
+ return wrapped;
286
+ }
287
+
77
288
  function buildExecuteSliceContext({ repoRoot, slicePath, role, context }) {
78
289
  const canonicalRepoRoot = canonicalizeRepoRoot(repoRoot);
79
290
  const resolvedRole = normalizeRole(role || DEFAULT_EXECUTE_ROLE);
@@ -93,8 +304,10 @@ function buildExecuteSliceContext({ repoRoot, slicePath, role, context }) {
93
304
  const relativeSlicePath = toRelativePath(canonicalRepoRoot, slice.sliceAbs);
94
305
  const relativeBriefPath = toRelativePath(canonicalRepoRoot, briefPath);
95
306
  const allowedFiles = Array.isArray(slice.files) ? slice.files.map((file) => String(file)) : [];
307
+ const expectedReadPaths = Array.isArray(slice.expectedReadPaths) ? slice.expectedReadPaths.map((file) => String(file)) : [];
96
308
  const acceptance = Array.isArray(slice.acceptance) ? slice.acceptance.map((item) => String(item)) : [];
97
309
  const validationCommands = Array.isArray(slice.tests) ? slice.tests.map((item) => String(item)) : [];
310
+ const validationHints = Array.isArray(slice.validationHints) ? slice.validationHints.map((item) => String(item)) : [];
98
311
  const mustItems = Array.isArray(slice.json.must) ? slice.json.must.map((item) => String(item)) : [];
99
312
  const excludedItems = Array.isArray(slice.json.not_included) ? slice.json.not_included.map((item) => String(item)) : [];
100
313
 
@@ -105,6 +318,8 @@ function buildExecuteSliceContext({ repoRoot, slicePath, role, context }) {
105
318
  `Spec: ${slice.specSlug}`,
106
319
  `Slice file: ${relativeSlicePath}`,
107
320
  `Execution brief: ${relativeBriefPath}`,
321
+ 'Expected read paths:',
322
+ ...formatList(expectedReadPaths),
108
323
  'Allowed files:',
109
324
  ...formatList(allowedFiles),
110
325
  'Acceptance criteria:',
@@ -121,9 +336,13 @@ function buildExecuteSliceContext({ repoRoot, slicePath, role, context }) {
121
336
  sections.push('Not included:', ...formatList(excludedItems));
122
337
  }
123
338
 
339
+ if (validationHints.length > 0) {
340
+ sections.push('Validation hints:', ...formatList(validationHints));
341
+ }
342
+
124
343
  sections.push(
125
344
  'Constraints:',
126
- '- Do not commit automatically.',
345
+ '- Do not commit manually. Quiver can create the slice commit after scope and validation pass when the user enables --commit.',
127
346
  '- Do not fix scope violations automatically.',
128
347
  '- Do not run multiple executors concurrently.',
129
348
  '- Stay inside the allowed files declared by slice.json.',
@@ -136,13 +355,15 @@ function buildExecuteSliceContext({ repoRoot, slicePath, role, context }) {
136
355
  briefPath: relativeBriefPath,
137
356
  briefText,
138
357
  context: pack,
358
+ expectedReadPaths,
139
359
  prompt: sections.join('\n\n'),
140
360
  slice,
361
+ validationHints,
141
362
  validationCommands,
142
363
  };
143
364
  }
144
365
 
145
- function formatExecuteSliceDryRunReport({ provider, role, contextPack, slice, briefPath, invocation, validationCommands, allowedFiles }) {
366
+ function formatExecuteSliceDryRunReport({ provider, role, contextPack, slice, briefPath, invocation, validationCommands, allowedFiles, commitEnabled }) {
146
367
  const lines = [
147
368
  'AI execute-slice dry-run',
148
369
  `Provider: ${provider}`,
@@ -155,6 +376,7 @@ function formatExecuteSliceDryRunReport({ provider, role, contextPack, slice, br
155
376
  `Timeout: ${invocation.timeoutMs}ms`,
156
377
  `Prompt transport: ${invocation.promptTransport.mode}`,
157
378
  `Prompt length: ${invocation.promptLength} bytes`,
379
+ `Commit after validation: ${commitEnabled ? 'enabled' : 'disabled'}`,
158
380
  'Allowed files:',
159
381
  ...formatList(allowedFiles),
160
382
  'Validation commands:',
@@ -164,7 +386,7 @@ function formatExecuteSliceDryRunReport({ provider, role, contextPack, slice, br
164
386
  return `${lines.join('\n')}\n`;
165
387
  }
166
388
 
167
- function formatExecuteSliceResult({ slice, changedFiles, scopeResult }) {
389
+ function formatExecuteSliceResult({ slice, changedFiles, scopeResult, validationResults, commitResult, commitEnabled }) {
168
390
  const lines = [
169
391
  'AI execute-slice completed',
170
392
  `Slice: ${slice.sliceId}`,
@@ -177,6 +399,17 @@ function formatExecuteSliceResult({ slice, changedFiles, scopeResult }) {
177
399
  }
178
400
 
179
401
  lines.push(`Scope validation: ${scopeResult.ok ? 'passed' : 'failed'}`);
402
+ if (!Array.isArray(validationResults) || validationResults.length === 0) {
403
+ lines.push('Validation commands: skipped (none declared)');
404
+ } else {
405
+ lines.push(`Validation commands: passed (${validationResults.length})`);
406
+ }
407
+ if (commitResult) {
408
+ lines.push(`Commit: created ${commitResult.hash}`);
409
+ lines.push(`Commit message: ${commitResult.message}`);
410
+ } else {
411
+ lines.push(`Commit: ${commitEnabled ? 'not created' : 'skipped'}`);
412
+ }
180
413
 
181
414
  return `${lines.join('\n')}\n`;
182
415
  }
@@ -190,9 +423,296 @@ function annotateProviderError(error, scope) {
190
423
  return wrapped;
191
424
  }
192
425
 
426
+ function runValidationCommand(command, repoRoot) {
427
+ try {
428
+ const stdout = cp.execSync(command, {
429
+ cwd: repoRoot,
430
+ encoding: 'utf8',
431
+ shell: true,
432
+ stdio: ['ignore', 'pipe', 'pipe'],
433
+ });
434
+ return {
435
+ command: redactSecrets(command),
436
+ ok: true,
437
+ stdout: redactSecrets(stdout),
438
+ stderr: '',
439
+ exitCode: 0,
440
+ };
441
+ } catch (error) {
442
+ return {
443
+ command: redactSecrets(command),
444
+ ok: false,
445
+ stdout: redactSecrets(error.stdout ? String(error.stdout) : ''),
446
+ stderr: redactSecrets(error.stderr ? String(error.stderr) : ''),
447
+ exitCode: Number.isInteger(error.status) ? error.status : 1,
448
+ error,
449
+ };
450
+ }
451
+ }
452
+
453
+ function runValidationCommands(repoRoot, commands, runner = runValidationCommand) {
454
+ const results = [];
455
+ for (const command of commands) {
456
+ const rawResult = runner(command, repoRoot);
457
+ const result = {
458
+ ...rawResult,
459
+ command: redactSecrets(rawResult.command || command),
460
+ stderr: redactSecrets(rawResult.stderr || ''),
461
+ stdout: redactSecrets(rawResult.stdout || ''),
462
+ };
463
+ results.push(result);
464
+ if (!result.ok) {
465
+ const details = [
466
+ formatError(`validation command failed: ${command}`),
467
+ `Exit code: ${result.exitCode}`,
468
+ ];
469
+ if (result.stderr) {
470
+ details.push(`stderr:\n${result.stderr.trimEnd()}`);
471
+ }
472
+ if (result.stdout) {
473
+ details.push(`stdout:\n${result.stdout.trimEnd()}`);
474
+ }
475
+ const error = new Error(details.join('\n'));
476
+ error.code = 'VALIDATION_FAILED';
477
+ error.details = { command, result, results };
478
+ throw error;
479
+ }
480
+ }
481
+ return results;
482
+ }
483
+
484
+ function commitTypeForSlice(slice) {
485
+ const type = String(slice.json.type || slice.json.git?.branch_type || '').trim().toLowerCase();
486
+ if (type === 'bugfix' || type === 'hotfix' || type === 'fix') {
487
+ return 'fix';
488
+ }
489
+ if (type === 'docs' || type === 'documentation') {
490
+ return 'docs';
491
+ }
492
+ if (type === 'test' || type === 'tests') {
493
+ return 'test';
494
+ }
495
+ if (type === 'chore') {
496
+ return 'chore';
497
+ }
498
+ return 'feat';
499
+ }
500
+
501
+ function buildSliceCommitMessage(slice) {
502
+ const title = String(slice.json.title || slice.sliceId || 'slice').trim();
503
+ const ticket = String(slice.ticket || '').trim();
504
+ const subject = ticket ? `${ticket} ${title}` : title;
505
+ return `${commitTypeForSlice(slice)}: ${subject}`;
506
+ }
507
+
508
+ function commitSliceChanges(repoRoot, slice, changedFiles, options = {}) {
509
+ if (!Array.isArray(changedFiles) || changedFiles.length === 0) {
510
+ const error = new Error(formatError('commit requested but provider produced no changed files.'));
511
+ error.code = 'NO_CHANGES_TO_COMMIT';
512
+ throw error;
513
+ }
514
+
515
+ const message = options.message || buildSliceCommitMessage(slice);
516
+ runGit(['add', '--', ...changedFiles], repoRoot);
517
+ runGit(['commit', '-m', message], repoRoot);
518
+
519
+ return {
520
+ files: changedFiles,
521
+ hash: runGit(['rev-parse', '--short', 'HEAD'], repoRoot),
522
+ message,
523
+ };
524
+ }
525
+
526
+ function assertCorrectSliceWorktree(repoRoot, slice, options = {}) {
527
+ if (options.skipWorktreeBranchCheck === true) {
528
+ return null;
529
+ }
530
+
531
+ const expectedBranch = String(slice.branchName || slice.json.git?.branch_name || '').trim();
532
+ if (!expectedBranch) {
533
+ return null;
534
+ }
535
+
536
+ const actualBranch = currentBranch(repoRoot);
537
+ if (actualBranch !== expectedBranch) {
538
+ const error = new Error(formatError(`ai execute-slice must run from the slice worktree branch. Current branch: ${actualBranch || '(detached or unavailable)'}. Expected: ${expectedBranch}.`));
539
+ error.code = 'WRONG_WORKTREE';
540
+ error.details = {
541
+ actualBranch,
542
+ expectedBranch,
543
+ slice: slice.sliceRel,
544
+ };
545
+ throw error;
546
+ }
547
+
548
+ return {
549
+ actualBranch,
550
+ expectedBranch,
551
+ };
552
+ }
553
+
554
+ function sliceLifecycleArtifactPaths(repoRoot, slice) {
555
+ const closureAbs = path.join(path.dirname(slice.sliceAbs), 'CLOSURE_BRIEF.md');
556
+ return {
557
+ closure: toRelativePath(repoRoot, closureAbs),
558
+ commandLog: toRelativePath(repoRoot, path.join(slice.specDirAbs, 'COMMAND_LOG.md')),
559
+ evidence: toRelativePath(repoRoot, path.join(slice.specDirAbs, 'EVIDENCE_REPORT.md')),
560
+ sliceJson: toRelativePath(repoRoot, slice.sliceAbs),
561
+ status: toRelativePath(repoRoot, path.join(slice.specDirAbs, 'STATUS.md')),
562
+ };
563
+ }
564
+
565
+ function renderClosureBrief({ slice, changedFiles, validationResults, completedAt }) {
566
+ const criteria = Array.isArray(slice.acceptance) ? slice.acceptance : [];
567
+ const validationLines = Array.isArray(validationResults) && validationResults.length > 0
568
+ ? validationResults.map((result) => `- [x] \`${result.command}\` exited ${result.exitCode}`)
569
+ : ['- [x] No validation commands declared.'];
570
+
571
+ return `${[
572
+ `# CLOSURE BRIEF - ${slice.sliceId}: ${slice.json.title || slice.sliceId}`,
573
+ '',
574
+ '## Summary of Work',
575
+ '',
576
+ `Executed controlled slice closure at ${completedAt}. Quiver validated scope, validation commands, and lifecycle evidence for this slice.`,
577
+ '',
578
+ '## Validation Against Acceptance Criteria',
579
+ '',
580
+ ...(criteria.length > 0 ? criteria.map((item) => `- [x] ${item}`) : ['- [x] Slice execution completed with scope validation.']),
581
+ '',
582
+ '## Relevant Changes',
583
+ '',
584
+ ...formatList(changedFiles),
585
+ '',
586
+ '## Validation Commands',
587
+ '',
588
+ ...validationLines,
589
+ '',
590
+ '## Pending',
591
+ '',
592
+ 'None recorded by Quiver.',
593
+ '',
594
+ '## Remaining Risks',
595
+ '',
596
+ 'None recorded by Quiver.',
597
+ '',
598
+ '## Future Recommendations',
599
+ '',
600
+ 'Review the evidence report and commit diff before opening the PR.',
601
+ '',
602
+ ].join('\n')}\n`;
603
+ }
604
+
605
+ function appendSection(filePath, fallbackTitle, section) {
606
+ const current = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8').trimEnd() : fallbackTitle;
607
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
608
+ fs.writeFileSync(filePath, `${current}\n\n${section.trimEnd()}\n`);
609
+ }
610
+
611
+ function updateStatusMarkdown(filePath, slice, completedAt) {
612
+ const fallback = `# Status - ${slice.specSlug}\n`;
613
+ let text = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : fallback;
614
+ const rowRegex = new RegExp(`(\\|\\s*${escapeRegex(slice.sliceId)}\\s*\\|\\s*)[^|\\n]+(\\|[^\\n]*\\|)`);
615
+ if (rowRegex.test(text)) {
616
+ text = text.replace(rowRegex, '$1Completed $2');
617
+ }
618
+ text = text.replace(/\*\*Current slice:\*\*\s*[^\n]*/i, `**Current slice:** ${slice.sliceId} completed`);
619
+ if (!text.endsWith('\n')) {
620
+ text += '\n';
621
+ }
622
+ const section = [
623
+ '',
624
+ `## Execution Update - ${slice.sliceId}`,
625
+ '',
626
+ `- Status: Completed`,
627
+ `- Completed at: ${completedAt}`,
628
+ `- Source: \`npx create-quiver ai execute-slice --slice ${slice.sliceRel}\``,
629
+ ].join('\n');
630
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
631
+ fs.writeFileSync(filePath, `${text}${section}\n`);
632
+ }
633
+
634
+ function updateSliceJson(filePath, completedAt) {
635
+ const json = JSON.parse(fs.readFileSync(filePath, 'utf8'));
636
+ json.status = 'completed';
637
+ json.completed_at = completedAt;
638
+ fs.writeFileSync(filePath, `${JSON.stringify(json, null, 2)}\n`);
639
+ }
640
+
641
+ function writeExecutionArtifacts(repoRoot, executorContext, details) {
642
+ const { slice } = executorContext;
643
+ const completedAt = details.completedAt || new Date().toISOString();
644
+ const artifacts = sliceLifecycleArtifactPaths(repoRoot, slice);
645
+ const changedFiles = uniqueList(details.changedFiles);
646
+ const closurePath = path.join(repoRoot, artifacts.closure);
647
+ const evidencePath = path.join(repoRoot, artifacts.evidence);
648
+ const commandLogPath = path.join(repoRoot, artifacts.commandLog);
649
+ const statusPath = path.join(repoRoot, artifacts.status);
650
+ const validationResults = Array.isArray(details.validationResults) ? details.validationResults : [];
651
+ const providerStdout = truncateText(redactSecrets(details.providerOutput?.stdout || ''), 1200).text;
652
+ const providerStderr = truncateText(redactSecrets(details.providerOutput?.stderr || ''), 1200).text;
653
+
654
+ fs.mkdirSync(path.dirname(closurePath), { recursive: true });
655
+ fs.writeFileSync(closurePath, renderClosureBrief({
656
+ slice,
657
+ changedFiles,
658
+ validationResults,
659
+ completedAt,
660
+ }));
661
+
662
+ const validationLines = validationResults.length > 0
663
+ ? validationResults.map((result) => `- \`${result.command}\` -> exit ${result.exitCode}`)
664
+ : ['- No validation commands declared.'];
665
+ appendSection(evidencePath, `# Evidence Report - ${slice.specSlug}`, [
666
+ `## ${slice.sliceId} - Execution Evidence`,
667
+ '',
668
+ `- Completed at: ${completedAt}`,
669
+ `- Changed files: ${changedFiles.length}`,
670
+ ...changedFiles.map((file) => ` - \`${file}\``),
671
+ `- Scope validation: passed`,
672
+ `- Provider stdout redacted: ${providerStdout ? 'yes' : 'n/a'}`,
673
+ `- Provider stderr redacted: ${providerStderr ? 'yes' : 'n/a'}`,
674
+ '',
675
+ '### Validation',
676
+ '',
677
+ ...validationLines,
678
+ '',
679
+ '### Provider Output',
680
+ '',
681
+ '```text',
682
+ providerStdout || 'n/a',
683
+ providerStderr ? `\n${providerStderr}` : '',
684
+ '```',
685
+ ].join('\n'));
686
+
687
+ const commandLogRows = [
688
+ `| ${completedAt} | ${slice.sliceId} | \`npx create-quiver ai execute-slice --slice ${slice.sliceRel}\` | passed |`,
689
+ ...validationResults.map((result) => `| ${completedAt} | ${slice.sliceId} | \`${result.command}\` | exit ${result.exitCode} |`),
690
+ ];
691
+ const commandLogHeader = [
692
+ '# Command Log',
693
+ '',
694
+ '| Timestamp | Slice | Command | Result |',
695
+ '|---|---|---|---|',
696
+ ].join('\n');
697
+ const currentCommandLog = fs.existsSync(commandLogPath) ? fs.readFileSync(commandLogPath, 'utf8').trimEnd() : commandLogHeader;
698
+ fs.mkdirSync(path.dirname(commandLogPath), { recursive: true });
699
+ fs.writeFileSync(commandLogPath, `${currentCommandLog}\n${commandLogRows.join('\n')}\n`);
700
+
701
+ updateStatusMarkdown(statusPath, slice, completedAt);
702
+ updateSliceJson(path.join(repoRoot, artifacts.sliceJson), completedAt);
703
+
704
+ return {
705
+ completedAt,
706
+ files: Object.values(artifacts),
707
+ };
708
+ }
709
+
193
710
  async function runExecuteSlice(repoRoot, options = {}) {
194
- const provider = String(options.provider || DEFAULT_EXECUTE_PROVIDER).trim().toLowerCase();
711
+ const canonicalRepoRoot = canonicalizeRepoRoot(repoRoot);
195
712
  const role = normalizeRole(options.role || DEFAULT_EXECUTE_ROLE);
713
+ const provider = options.providerExplicit === true || (options.provider && options.providerExplicit !== false)
714
+ ? String(options.provider || DEFAULT_EXECUTE_PROVIDER).trim().toLowerCase()
715
+ : resolveProfileProvider(canonicalRepoRoot, role, DEFAULT_EXECUTE_PROVIDER);
196
716
  const context = options.context || DEFAULT_EXECUTE_CONTEXT;
197
717
  const timeoutMs = normalizeTimeout(options.timeout);
198
718
 
@@ -201,7 +721,7 @@ async function runExecuteSlice(repoRoot, options = {}) {
201
721
  }
202
722
 
203
723
  const executorContext = buildExecuteSliceContext({
204
- repoRoot,
724
+ repoRoot: canonicalRepoRoot,
205
725
  slicePath: options.slice,
206
726
  role,
207
727
  context,
@@ -213,7 +733,7 @@ async function runExecuteSlice(repoRoot, options = {}) {
213
733
  try {
214
734
  invocation = buildProviderInvocation(provider, {
215
735
  prompt,
216
- cwd: repoRoot,
736
+ cwd: canonicalRepoRoot,
217
737
  timeoutMs,
218
738
  });
219
739
  } catch (error) {
@@ -231,6 +751,7 @@ async function runExecuteSlice(repoRoot, options = {}) {
231
751
  briefPath: executorContext.briefPath,
232
752
  allowedFiles: executorContext.allowedFiles,
233
753
  validationCommands: executorContext.validationCommands,
754
+ commitEnabled: options.commit === true,
234
755
  };
235
756
  process.stdout.write(formatExecuteSliceDryRunReport({
236
757
  provider,
@@ -241,20 +762,30 @@ async function runExecuteSlice(repoRoot, options = {}) {
241
762
  invocation,
242
763
  validationCommands: executorContext.validationCommands,
243
764
  allowedFiles: executorContext.allowedFiles,
765
+ commitEnabled: options.commit === true,
244
766
  }));
245
767
  return report;
246
768
  }
247
769
 
248
- const beforeSnapshot = captureWorktreeSnapshot(repoRoot);
770
+ try {
771
+ assertCorrectSliceWorktree(canonicalRepoRoot, executorContext.slice, options);
772
+ } catch (error) {
773
+ throw appendRecovery(error, executorContext.slice);
774
+ }
775
+
776
+ const beforeSnapshot = captureWorktreeSnapshot(canonicalRepoRoot);
777
+ if (beforeSnapshot.files.length > 0 && options.commit === true) {
778
+ throw appendRecovery(new Error(formatError(`ai execute-slice --commit requires a clean worktree before running. Commit or stash first: ${beforeSnapshot.files.join(', ')}`)), executorContext.slice);
779
+ }
249
780
  if (beforeSnapshot.files.length > 0 && options.allowDirty !== true) {
250
- throw new Error(formatError(`ai execute-slice requires a clean worktree before running. Commit or stash first: ${beforeSnapshot.files.join(', ')}`));
781
+ throw appendRecovery(new Error(formatError(`ai execute-slice requires a clean worktree before running. Commit or stash first: ${beforeSnapshot.files.join(', ')}`)), executorContext.slice);
251
782
  }
252
783
 
253
784
  let result;
254
785
  try {
255
786
  result = await (options.runProviderFn || runProvider)(provider, {
256
787
  prompt,
257
- cwd: repoRoot,
788
+ cwd: canonicalRepoRoot,
258
789
  timeoutMs,
259
790
  dryRun: false,
260
791
  probe: options.probe,
@@ -264,32 +795,97 @@ async function runExecuteSlice(repoRoot, options = {}) {
264
795
  tempFilePrefix: options.tempFilePrefix,
265
796
  });
266
797
  } catch (error) {
267
- throw annotateProviderError(error, 'execute-slice');
798
+ throw appendRecovery(annotateProviderError(error, 'execute-slice'), executorContext.slice);
268
799
  }
269
800
 
270
801
  if (result.stdout) {
271
- process.stdout.write(result.stdout);
802
+ process.stdout.write(redactSecrets(result.stdout));
272
803
  }
273
804
  if (result.stderr) {
274
- process.stderr.write(result.stderr);
805
+ process.stderr.write(redactSecrets(result.stderr));
275
806
  }
276
807
 
277
808
  if (!result.ok) {
278
- throw annotateProviderError(result.error || new Error('provider run failed'), 'execute-slice');
809
+ throw appendRecovery(annotateProviderError(result.error || new Error('provider run failed'), 'execute-slice'), executorContext.slice);
279
810
  }
280
811
 
281
- const afterSnapshot = captureWorktreeSnapshot(repoRoot);
282
- const scopeResult = validateScopeSnapshot({
283
- allowedFiles: executorContext.allowedFiles,
284
- beforeSnapshot,
285
- afterSnapshot,
286
- strict: true,
812
+ const providerOutput = {
813
+ stdout: redactSecrets(result.stdout || ''),
814
+ stderr: redactSecrets(result.stderr || ''),
815
+ };
816
+ const sanitizedResult = {
817
+ ...result,
818
+ stdout: providerOutput.stdout,
819
+ stderr: providerOutput.stderr,
820
+ };
821
+
822
+ const afterSnapshot = captureWorktreeSnapshot(canonicalRepoRoot);
823
+ let scopeResult;
824
+ try {
825
+ scopeResult = validateScopeSnapshot({
826
+ allowedFiles: executorContext.allowedFiles,
827
+ beforeSnapshot,
828
+ afterSnapshot,
829
+ strict: true,
830
+ });
831
+ } catch (error) {
832
+ throw appendRecovery(error, executorContext.slice);
833
+ }
834
+ if (scopeResult.changedFiles.length === 0) {
835
+ const error = new Error(formatError('provider produced no changed files; slice closure was not updated.'));
836
+ error.code = 'NO_CHANGES_TO_CLOSE';
837
+ throw appendRecovery(error, executorContext.slice);
838
+ }
839
+
840
+ let validationResults = [];
841
+ try {
842
+ validationResults = runValidationCommands(
843
+ canonicalRepoRoot,
844
+ executorContext.validationCommands,
845
+ options.runValidationCommandFn,
846
+ );
847
+ } catch (error) {
848
+ throw appendRecovery(error, executorContext.slice);
849
+ }
850
+
851
+ const artifacts = writeExecutionArtifacts(canonicalRepoRoot, executorContext, {
852
+ changedFiles: scopeResult.changedFiles,
853
+ completedAt: new Date().toISOString(),
854
+ providerOutput,
855
+ validationResults,
287
856
  });
288
857
 
858
+ const finalSnapshot = captureWorktreeSnapshot(canonicalRepoRoot);
859
+ let finalScopeResult;
860
+ try {
861
+ finalScopeResult = validateScopeSnapshot({
862
+ allowedFiles: uniqueList([...executorContext.allowedFiles, ...artifacts.files]),
863
+ beforeSnapshot,
864
+ afterSnapshot: finalSnapshot,
865
+ strict: true,
866
+ });
867
+ } catch (error) {
868
+ throw appendRecovery(error, executorContext.slice);
869
+ }
870
+
871
+ let commitResult = null;
872
+ if (options.commit === true) {
873
+ try {
874
+ commitResult = commitSliceChanges(canonicalRepoRoot, executorContext.slice, finalScopeResult.changedFiles, {
875
+ message: options.commitMessage,
876
+ });
877
+ } catch (error) {
878
+ throw appendRecovery(error, executorContext.slice);
879
+ }
880
+ }
881
+
289
882
  process.stdout.write(formatExecuteSliceResult({
290
883
  slice: executorContext.slice,
291
- changedFiles: scopeResult.changedFiles,
292
- scopeResult,
884
+ changedFiles: finalScopeResult.changedFiles,
885
+ scopeResult: finalScopeResult,
886
+ validationResults,
887
+ commitResult,
888
+ commitEnabled: options.commit === true,
293
889
  }));
294
890
 
295
891
  return {
@@ -300,10 +896,13 @@ async function runExecuteSlice(repoRoot, options = {}) {
300
896
  slice: executorContext.slice.sliceId,
301
897
  specSlug: executorContext.slice.specSlug,
302
898
  invocation,
303
- result,
899
+ result: sanitizedResult,
304
900
  beforeSnapshot,
305
- afterSnapshot,
306
- scopeResult,
901
+ afterSnapshot: finalSnapshot,
902
+ scopeResult: finalScopeResult,
903
+ validationResults,
904
+ commitResult,
905
+ artifacts,
307
906
  };
308
907
  }
309
908
 
@@ -312,12 +911,22 @@ module.exports = {
312
911
  DEFAULT_EXECUTE_PROVIDER,
313
912
  DEFAULT_EXECUTE_ROLE,
314
913
  annotateProviderError,
914
+ appendRecovery,
315
915
  buildExecuteSliceContext,
916
+ buildManualExecutorPrompt,
917
+ buildRecoveryGuidance,
918
+ buildSliceCommitMessage,
316
919
  canonicalizeRepoRoot,
920
+ commitSliceChanges,
317
921
  formatExecuteSliceDryRunReport,
318
922
  formatExecuteSliceResult,
923
+ assertCorrectSliceWorktree,
924
+ writeExecutionArtifacts,
925
+ runValidationCommand,
926
+ runValidationCommands,
319
927
  normalizeTimeout,
320
928
  readTextFile,
321
929
  resolveSliceJsonPath,
322
930
  runExecuteSlice,
931
+ runPromptSlice,
323
932
  };