create-quiver 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BACKLOG.md +16 -17
- package/CHANGELOG.md +34 -0
- package/README.md +174 -39
- package/README_FOR_AI.md +48 -24
- package/ROADMAP.md +22 -11
- package/docs/AI_CONTEXT.md.template +2 -0
- package/docs/AI_ONBOARDING_PROMPT.md.template +25 -18
- package/docs/COMMANDS.md.template +59 -11
- package/docs/CONTEXTO.md.template +2 -0
- package/docs/DECISIONS.md.template +1 -0
- package/docs/INDEX.md.template +20 -18
- package/docs/STATUS.md.template +1 -0
- package/docs/SUPPORT_MATRIX.md.template +2 -2
- package/docs/TROUBLESHOOTING.md.template +50 -0
- package/docs/WORKFLOW.md.template +25 -17
- package/package.json +19 -2
- package/package.template.json +13 -1
- package/scripts/init-docs.sh +11 -4
- package/scripts/package-quiver.sh +18 -2
- package/specs/quiver-v22-guided-ai-workflow/EVIDENCE_REPORT.md +58 -0
- package/specs/quiver-v22-guided-ai-workflow/EXECUTION_PLAN.md +88 -0
- package/specs/quiver-v22-guided-ai-workflow/SPEC.md +228 -0
- package/specs/quiver-v22-guided-ai-workflow/STATUS.md +42 -0
- package/specs/quiver-v22-guided-ai-workflow/pr.md +104 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +35 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-00-spec-foundation/slice.json +51 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/CLOSURE_BRIEF.md +31 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-01-docs-source-of-truth-sync/slice.json +55 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/CLOSURE_BRIEF.md +30 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/EXECUTION_BRIEF.md +57 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-02-prepare-command-diagnostics/slice.json +57 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/EXECUTION_BRIEF.md +56 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-03-context-doc-refresh/slice.json +56 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/EXECUTION_BRIEF.md +56 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-04-planner-approval-state/slice.json +58 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/EXECUTION_BRIEF.md +56 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-05-spec-worktree-lifecycle/slice.json +54 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-06-executor-commit-recovery/slice.json +57 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-07-execution-waves-delegation/slice.json +55 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-08-pr-create-gh-ssh/slice.json +53 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/EXECUTION_BRIEF.md +59 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-09-post-merge-cleanup-release-safety/slice.json +59 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v22-guided-ai-workflow/slices/slice-10-docs-smokes-release-readiness/slice.json +60 -0
- package/specs/quiver-v23-guided-flow-productization/EVIDENCE_REPORT.md +80 -0
- package/specs/quiver-v23-guided-flow-productization/EXECUTION_PLAN.md +80 -0
- package/specs/quiver-v23-guided-flow-productization/SPEC.md +203 -0
- package/specs/quiver-v23-guided-flow-productization/STATUS.md +39 -0
- package/specs/quiver-v23-guided-flow-productization/pr.md +119 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +30 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +61 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-00-spec-foundation/slice.json +51 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/EXECUTION_BRIEF.md +35 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-01-short-command-and-flow-entrypoint/slice.json +56 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/CLOSURE_BRIEF.md +31 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/EXECUTION_BRIEF.md +29 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-02-flow-status-wizard/slice.json +55 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/EXECUTION_BRIEF.md +29 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-03-agent-profiles/slice.json +54 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/EXECUTION_BRIEF.md +30 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-04-context-preparation-onboarding/slice.json +59 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/CLOSURE_BRIEF.md +31 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/EXECUTION_BRIEF.md +29 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-05-planner-iteration-history/slice.json +53 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/EXECUTION_BRIEF.md +30 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-06-production-plan-review/slice.json +54 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/EXECUTION_BRIEF.md +30 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-07-spec-create-experience/slice.json +55 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/EXECUTION_BRIEF.md +30 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-08-executor-prompt-generation/slice.json +55 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/EXECUTION_BRIEF.md +34 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-09-delegated-slice-execution/slice.json +57 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +32 -0
- package/specs/quiver-v23-guided-flow-productization/slices/slice-10-docs-smokes-release-readiness/slice.json +63 -0
- package/specs/quiver-v24-dx-onboarding-hardening/EVIDENCE_REPORT.md +55 -0
- package/specs/quiver-v24-dx-onboarding-hardening/EXECUTION_PLAN.md +43 -0
- package/specs/quiver-v24-dx-onboarding-hardening/SPEC.md +149 -0
- package/specs/quiver-v24-dx-onboarding-hardening/STATUS.md +31 -0
- package/specs/quiver-v24-dx-onboarding-hardening/pr.md +76 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +31 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +52 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-00-spec-foundation/slice.json +51 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/CLOSURE_BRIEF.md +38 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/EXECUTION_BRIEF.md +53 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-01-init-template-hygiene/slice.json +55 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/EXECUTION_BRIEF.md +50 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-02-cli-command-routing-version-errors/slice.json +52 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/EXECUTION_BRIEF.md +50 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-03-doctor-fix-doc-link-checks/slice.json +53 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/EXECUTION_BRIEF.md +50 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-04-prepare-output-ai-context-drafts/slice.json +70 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/CLOSURE_BRIEF.md +36 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/EXECUTION_BRIEF.md +49 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-05-local-slice-validation-base-guidance/slice.json +52 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/CLOSURE_BRIEF.md +43 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/EXECUTION_BRIEF.md +53 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-06-plan-graph-next-history-views/slice.json +60 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/EXECUTION_BRIEF.md +50 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-07-analyzer-command-map-hardening/slice.json +51 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/EXECUTION_BRIEF.md +52 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-08-evidence-run-command/slice.json +54 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/EXECUTION_BRIEF.md +51 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-09-spec-viewer-demo-scaffolding/slice.json +59 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/EXECUTION_BRIEF.md +54 -0
- package/specs/quiver-v24-dx-onboarding-hardening/slices/slice-10-docs-smokes-release-readiness/slice.json +76 -0
- package/src/create-quiver/commands/ai.js +508 -35
- package/src/create-quiver/commands/demo.js +22 -0
- package/src/create-quiver/commands/evidence.js +37 -0
- package/src/create-quiver/commands/flow.js +561 -0
- package/src/create-quiver/commands/graph.js +14 -1
- package/src/create-quiver/commands/next.js +28 -0
- package/src/create-quiver/commands/plan.js +6 -3
- package/src/create-quiver/commands/prepare.js +236 -0
- package/src/create-quiver/commands/spec.js +133 -0
- package/src/create-quiver/index.js +688 -25
- package/src/create-quiver/lib/agent-profiles.js +148 -0
- package/src/create-quiver/lib/ai/context-packs.js +12 -0
- package/src/create-quiver/lib/ai/execution-plan.js +370 -10
- package/src/create-quiver/lib/ai/executor.js +376 -17
- package/src/create-quiver/lib/ai/github.js +196 -0
- package/src/create-quiver/lib/ai/onboarding-template.js +365 -0
- package/src/create-quiver/lib/ai/plan-review.js +283 -0
- package/src/create-quiver/lib/ai/providers.js +1 -0
- package/src/create-quiver/lib/ai/safety.js +5 -0
- package/src/create-quiver/lib/ai/spec-templates.js +2 -2
- package/src/create-quiver/lib/approvals.js +350 -0
- package/src/create-quiver/lib/demo.js +657 -0
- package/src/create-quiver/lib/doctor.js +234 -0
- package/src/create-quiver/lib/evidence.js +115 -0
- package/src/create-quiver/lib/init-docs.js +284 -17
- package/src/create-quiver/lib/init-layout.js +26 -1
- package/src/create-quiver/lib/lifecycle.js +6 -0
- package/src/create-quiver/lib/package-safety.js +117 -0
- package/src/create-quiver/lib/readiness.js +85 -18
- package/src/create-quiver/lib/slice-graph.js +1 -0
- package/src/create-quiver/lib/slice.js +8 -8
- package/src/create-quiver/lib/spec-worktrees.js +349 -0
|
@@ -3,15 +3,27 @@ const os = require('os');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { execFileSync } = require('child_process');
|
|
5
5
|
const { checkHandoff, scaffoldHandoff } = require('./lib/handoff');
|
|
6
|
-
const {
|
|
7
|
-
|
|
6
|
+
const {
|
|
7
|
+
applyDoctorFixPlan,
|
|
8
|
+
buildDoctorFixPlan,
|
|
9
|
+
collectDoctorReport,
|
|
10
|
+
formatDoctorFixPlan,
|
|
11
|
+
} = require('./lib/doctor');
|
|
12
|
+
const { runAgent: runAiAgent, runApprovalStatus: runAiApprovalStatus, runApprove: runAiApprove, runDoctor: runAiDoctor, runExecutePlan: runAiExecutePlan, runExecuteSlice: runAiExecuteSlice, runOnboard, runPlan: runAiPlan, runPrepareContext: runAiPrepareContext, runPr: runAiPr, runPromptSlice: runAiPromptSlice, runReviewPlan: runAiReviewPlan } = require('./commands/ai');
|
|
13
|
+
const { runDemo } = require('./commands/demo');
|
|
14
|
+
const { runPrepare } = require('./commands/prepare');
|
|
15
|
+
const { runEvidence } = require('./commands/evidence');
|
|
16
|
+
const { runFlow } = require('./commands/flow');
|
|
8
17
|
const { runGraph } = require('./commands/graph');
|
|
9
18
|
const { runNext } = require('./commands/next');
|
|
10
19
|
const { runPlan } = require('./commands/plan');
|
|
20
|
+
const { runCreateSpec } = require('./commands/spec');
|
|
11
21
|
const { buildInitLayout, formatInitLayoutPlan } = require('./lib/init-layout');
|
|
12
|
-
const { initializeProjectDocs, installSelfAsDevDep } = require('./lib/init-docs');
|
|
22
|
+
const { initializeProjectDocs, installSelfAsDevDep, refreshAiContextDoc } = require('./lib/init-docs');
|
|
13
23
|
const { checkPrReadiness, checkScope, checkSliceReadiness } = require('./lib/readiness');
|
|
14
24
|
const { cleanupSlice, refreshActiveSlicesBoard, startSlice } = require('./lib/lifecycle');
|
|
25
|
+
const { buildSpecStatus, closeSpecWorktree, formatSpecCloseResult, formatSpecStartResult, formatSpecStatus, startSpecWorktree } = require('./lib/spec-worktrees');
|
|
26
|
+
const { getContextPathExclusionReason } = require('./lib/ai/safety');
|
|
15
27
|
const { relativePosixPath, resolveTargetRoot } = require('./lib/paths');
|
|
16
28
|
const {
|
|
17
29
|
CURRENT_SCAN_RELATIVE_PATH,
|
|
@@ -35,17 +47,74 @@ function formatError(message) {
|
|
|
35
47
|
return `create-quiver: ${message}`;
|
|
36
48
|
}
|
|
37
49
|
|
|
50
|
+
const SUPPORTED_COMMAND_MODES = new Set([
|
|
51
|
+
'init',
|
|
52
|
+
'flow',
|
|
53
|
+
'plan',
|
|
54
|
+
'graph',
|
|
55
|
+
'next',
|
|
56
|
+
'doctor',
|
|
57
|
+
'prepare',
|
|
58
|
+
'analyze',
|
|
59
|
+
'migrate',
|
|
60
|
+
'start-slice',
|
|
61
|
+
'check-slice',
|
|
62
|
+
'check-pr',
|
|
63
|
+
'check-handoff',
|
|
64
|
+
'new-handoff',
|
|
65
|
+
'cleanup-slice',
|
|
66
|
+
'check-scope',
|
|
67
|
+
'refresh-active-slices',
|
|
68
|
+
'spec',
|
|
69
|
+
'evidence',
|
|
70
|
+
'demo',
|
|
71
|
+
'ai',
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
const SUPPORTED_AI_COMMANDS = new Set([
|
|
75
|
+
'agent',
|
|
76
|
+
'approve',
|
|
77
|
+
'approval-status',
|
|
78
|
+
'approvals',
|
|
79
|
+
'doctor',
|
|
80
|
+
'execute-plan',
|
|
81
|
+
'execute-slice',
|
|
82
|
+
'executor-prompt',
|
|
83
|
+
'onboard',
|
|
84
|
+
'plan',
|
|
85
|
+
'prepare-context',
|
|
86
|
+
'pr',
|
|
87
|
+
'prompt-slice',
|
|
88
|
+
'review-plan',
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
const SUPPORTED_SPEC_COMMANDS = new Set(['close', 'create', 'start', 'status']);
|
|
92
|
+
const SUPPORTED_DEMO_COMMANDS = new Set(['create']);
|
|
93
|
+
|
|
94
|
+
function unsupportedCommandMessage(commandName) {
|
|
95
|
+
return [
|
|
96
|
+
`unsupported command: ${commandName}`,
|
|
97
|
+
'Run: npx create-quiver --help',
|
|
98
|
+
`If you meant to initialize a project, use: npx create-quiver init --name "${commandName}"`,
|
|
99
|
+
'If this command exists in newer docs, update create-quiver and rerun the command.',
|
|
100
|
+
].join('\n');
|
|
101
|
+
}
|
|
102
|
+
|
|
38
103
|
function printUsage() {
|
|
39
104
|
console.log(`Usage:
|
|
40
105
|
npx create-quiver [options]
|
|
41
106
|
npx create-quiver init [options]
|
|
42
107
|
npx create-quiver analyze [options]
|
|
108
|
+
npx create-quiver flow [options]
|
|
43
109
|
npx create-quiver plan [options]
|
|
44
110
|
npx create-quiver ai <task> [options]
|
|
111
|
+
npx create-quiver ai agent <set|list|show> [role] [options]
|
|
112
|
+
npx create-quiver ai prepare-context [options]
|
|
45
113
|
npx create-quiver graph [options]
|
|
46
114
|
npx create-quiver next [options]
|
|
47
115
|
npx create-quiver migrate [options]
|
|
48
116
|
npx create-quiver doctor [options]
|
|
117
|
+
npx create-quiver prepare [options]
|
|
49
118
|
npx create-quiver start-slice [options] <slice.json>
|
|
50
119
|
npx create-quiver check-slice [options] <slice.json>
|
|
51
120
|
npx create-quiver check-pr <slice.json>
|
|
@@ -54,6 +123,12 @@ function printUsage() {
|
|
|
54
123
|
npx create-quiver cleanup-slice [options] <slice.json>
|
|
55
124
|
npx create-quiver check-scope [options] <slice.json>
|
|
56
125
|
npx create-quiver refresh-active-slices
|
|
126
|
+
npx create-quiver spec create [options]
|
|
127
|
+
npx create-quiver spec start <spec-dir>
|
|
128
|
+
npx create-quiver spec status <spec-dir>
|
|
129
|
+
npx create-quiver spec close <spec-dir>
|
|
130
|
+
npx create-quiver evidence run [options] -- <command>
|
|
131
|
+
npx create-quiver demo create spec-viewer [options]
|
|
57
132
|
|
|
58
133
|
Options:
|
|
59
134
|
-n, --name <project-name> Project name to generate
|
|
@@ -63,15 +138,33 @@ Options:
|
|
|
63
138
|
--show-conflicts Show shared file paths in graph output
|
|
64
139
|
--level <n> Restrict graph output to one level
|
|
65
140
|
--json Emit machine-readable JSON
|
|
141
|
+
--include-completed Include completed slices in plan, graph, or next history output
|
|
66
142
|
--only-ready Show only slices with no pending dependencies
|
|
67
143
|
--all-ready List every ready slice returned by next
|
|
68
144
|
--auto-start Prompt for confirmation and run start-slice on next
|
|
145
|
+
--local For check-slice, run structural validation without remote/base checks
|
|
69
146
|
--unicode Prefer Unicode output when supported
|
|
70
147
|
--minimal Plan or run the minimal init profile
|
|
71
148
|
--full Plan or run the full compatibility init profile
|
|
72
149
|
--legacy-scripts Include legacy Bash wrappers in init profile
|
|
73
150
|
--include-templates Export packaged templates in init profile
|
|
74
|
-
--dry-run Preview init or AI work without executing writes/providers
|
|
151
|
+
--dry-run Preview init, prepare, spec create, demo, or AI work without executing writes/providers
|
|
152
|
+
--fix For doctor, apply safe non-destructive repairs
|
|
153
|
+
--execute For ai execute-plan, run the planned slices instead of printing commands
|
|
154
|
+
--create For ai pr, create the PR after preflight instead of printing the plan only
|
|
155
|
+
--commit For ai execute-slice, commit validated slice changes after provider, scope, and tests pass
|
|
156
|
+
--allow-dirty For ai execute-slice, allow pre-existing dirty files and ignore them for scope diff
|
|
157
|
+
--mode <name> Execution mode for ai execute-plan (auto, manual, delegated)
|
|
158
|
+
--provider <name> Provider CLI to preflight for prepare or AI commands
|
|
159
|
+
--model <label> Free-form model label for AI agent profiles
|
|
160
|
+
--version <n> Draft version to approve for AI planner phases
|
|
161
|
+
--ssh-host-alias <name> SSH host alias to validate for prepare or AI commands
|
|
162
|
+
--identity-file <path> SSH identity file to validate for prepare or AI commands
|
|
163
|
+
--remote <name> Git remote name for check-slice or AI PR checks
|
|
164
|
+
--base <branch> Base branch for check-slice, ai pr, or spec close (default: main)
|
|
165
|
+
--output <file> Output file for evidence run
|
|
166
|
+
--max-output <n> Maximum stdout/stderr chars per evidence section
|
|
167
|
+
--title <text> Override PR title for ai pr create
|
|
75
168
|
-y, --yes Skip prompts and use the provided inputs
|
|
76
169
|
-h, --help Show this help message
|
|
77
170
|
|
|
@@ -80,13 +173,28 @@ Examples:
|
|
|
80
173
|
npx create-quiver init --name "My Project" --dry-run
|
|
81
174
|
npx create-quiver --name "My Project"
|
|
82
175
|
npx create-quiver --name "My Project" --dir ./my-project
|
|
176
|
+
cd ./my-project && npx create-quiver flow
|
|
83
177
|
cd ./my-project && npx create-quiver analyze
|
|
84
178
|
cd ./my-project && npx create-quiver plan --json
|
|
85
179
|
cd ./my-project && npx create-quiver ai onboard --dry-run
|
|
180
|
+
cd ./my-project && npx create-quiver ai prepare-context --dry-run
|
|
181
|
+
cd ./my-project && npx create-quiver ai agent set planner --provider codex --model gpt-5.5
|
|
182
|
+
cd ./my-project && npx create-quiver ai agent list
|
|
86
183
|
cd ./my-project && npx create-quiver ai plan --phase acceptance --input requirements.md --dry-run
|
|
184
|
+
cd ./my-project && npx create-quiver ai approve --phase acceptance --input acceptance.md
|
|
185
|
+
cd ./my-project && npx create-quiver ai plan --phase technical-plan --dry-run
|
|
186
|
+
cd ./my-project && npx create-quiver ai review-plan --dry-run
|
|
187
|
+
cd ./my-project && npx create-quiver ai approve --phase technical-plan --version 1
|
|
188
|
+
cd ./my-project && npx create-quiver spec create --dry-run
|
|
189
|
+
cd ./my-project && npx create-quiver ai approvals
|
|
190
|
+
cd ./my-project && npx create-quiver ai prompt-slice --slice specs/my-project/slices/slice-01/slice.json --dry-run
|
|
87
191
|
cd ./my-project && npx create-quiver ai execute-slice --slice specs/my-project/slices/slice-01/slice.json --dry-run
|
|
192
|
+
cd ./my-project && npx create-quiver ai execute-slice --slice specs/my-project/slices/slice-01/slice.json --commit
|
|
193
|
+
cd ./my-project && npx create-quiver ai execute-plan --dry-run --commit
|
|
88
194
|
cd ./my-project && npx create-quiver ai doctor --dry-run --ssh-host-alias github-work --identity-file ~/.ssh/github-work
|
|
89
195
|
cd ./my-project && npx create-quiver ai pr --dry-run --ssh-host-alias github-work --identity-file ~/.ssh/github-work
|
|
196
|
+
cd ./my-project && npx create-quiver ai pr --create --input specs/my-project/pr.md --ssh-host-alias github-work --identity-file ~/.ssh/github-work
|
|
197
|
+
cd ./my-project && npx create-quiver prepare --dry-run --provider codex --ssh-host-alias github-work --identity-file ~/.ssh/github-work
|
|
90
198
|
cd ./my-project && npx create-quiver graph --show-conflicts
|
|
91
199
|
cd ./my-project && npx create-quiver graph --format mermaid
|
|
92
200
|
cd ./my-project && npx create-quiver graph --format dot
|
|
@@ -103,6 +211,11 @@ Examples:
|
|
|
103
211
|
cd ./my-project && npx create-quiver cleanup-slice specs/my-project/slices/slice-01/slice.json
|
|
104
212
|
cd ./my-project && npx create-quiver check-scope specs/my-project/slices/slice-01/slice.json
|
|
105
213
|
cd ./my-project && npx create-quiver refresh-active-slices
|
|
214
|
+
cd ./my-project && npx create-quiver spec start specs/my-project
|
|
215
|
+
cd ./my-project && npx create-quiver spec status specs/my-project
|
|
216
|
+
cd ./my-project && npx create-quiver spec close specs/my-project --dry-run
|
|
217
|
+
cd ./my-project && npx create-quiver evidence run -- npm test
|
|
218
|
+
cd ./my-project && npx create-quiver demo create spec-viewer --dry-run
|
|
106
219
|
node bin/create-quiver.js doctor --dir ./my-project
|
|
107
220
|
`);
|
|
108
221
|
}
|
|
@@ -114,15 +227,19 @@ function parseArgs(argv) {
|
|
|
114
227
|
explicitInit: false,
|
|
115
228
|
mode: 'init',
|
|
116
229
|
allowDraft: false,
|
|
230
|
+
checkSliceLocal: false,
|
|
117
231
|
closeBaseline: false,
|
|
118
232
|
discard: false,
|
|
233
|
+
doctorFix: false,
|
|
119
234
|
dryRun: false,
|
|
120
235
|
gate: 'execution',
|
|
121
236
|
projectName: '',
|
|
122
237
|
targetDir: '.',
|
|
238
|
+
targetDirExplicit: false,
|
|
123
239
|
strict: false,
|
|
124
240
|
strictOverlap: false,
|
|
125
241
|
json: false,
|
|
242
|
+
includeCompleted: false,
|
|
126
243
|
onlyReady: false,
|
|
127
244
|
allReady: false,
|
|
128
245
|
autoStart: false,
|
|
@@ -132,13 +249,28 @@ function parseArgs(argv) {
|
|
|
132
249
|
level: null,
|
|
133
250
|
unicode: false,
|
|
134
251
|
aiCommand: '',
|
|
252
|
+
aiAgentCommand: '',
|
|
253
|
+
aiAgentRole: '',
|
|
135
254
|
aiPhase: 'acceptance',
|
|
136
255
|
aiProvider: 'codex',
|
|
256
|
+
aiProviderExplicit: false,
|
|
257
|
+
aiModel: '',
|
|
258
|
+
aiLabel: '',
|
|
259
|
+
aiVersion: '',
|
|
260
|
+
prepareProvider: '',
|
|
137
261
|
aiRole: '',
|
|
138
262
|
aiContext: '',
|
|
139
263
|
aiInput: '',
|
|
140
264
|
aiSlice: '',
|
|
141
265
|
aiTimeout: null,
|
|
266
|
+
aiCommit: false,
|
|
267
|
+
aiAllowDirty: false,
|
|
268
|
+
aiExecute: false,
|
|
269
|
+
aiExecutionMode: 'auto',
|
|
270
|
+
aiCreate: false,
|
|
271
|
+
aiBaseBranch: 'main',
|
|
272
|
+
baseBranchExplicit: false,
|
|
273
|
+
aiTitle: '',
|
|
142
274
|
aiSshHostAlias: '',
|
|
143
275
|
aiIdentityFile: '',
|
|
144
276
|
aiRemote: 'origin',
|
|
@@ -146,14 +278,30 @@ function parseArgs(argv) {
|
|
|
146
278
|
initIncludeTemplates: false,
|
|
147
279
|
initLegacyScripts: false,
|
|
148
280
|
initMinimal: false,
|
|
281
|
+
specCommand: '',
|
|
282
|
+
demoCommand: '',
|
|
283
|
+
demoName: '',
|
|
284
|
+
evidenceCommand: '',
|
|
285
|
+
evidenceArgs: [],
|
|
286
|
+
evidenceOutput: '',
|
|
287
|
+
evidenceMaxOutput: null,
|
|
149
288
|
};
|
|
150
289
|
|
|
151
290
|
const args = [...argv];
|
|
152
|
-
|
|
153
|
-
if (commandModes.has(args[0])) {
|
|
291
|
+
if (SUPPORTED_COMMAND_MODES.has(args[0])) {
|
|
154
292
|
result.mode = args[0];
|
|
155
293
|
result.explicitInit = args[0] === 'init';
|
|
156
294
|
args.shift();
|
|
295
|
+
if (result.mode === 'spec') {
|
|
296
|
+
result.specCommand = args.shift() || '';
|
|
297
|
+
}
|
|
298
|
+
if (result.mode === 'evidence') {
|
|
299
|
+
result.evidenceCommand = args.shift() || '';
|
|
300
|
+
}
|
|
301
|
+
if (result.mode === 'demo') {
|
|
302
|
+
result.demoCommand = args.shift() || '';
|
|
303
|
+
result.demoName = args.shift() || '';
|
|
304
|
+
}
|
|
157
305
|
} else if (args[0] === '--analyze') {
|
|
158
306
|
result.mode = 'analyze';
|
|
159
307
|
args.shift();
|
|
@@ -169,6 +317,8 @@ function parseArgs(argv) {
|
|
|
169
317
|
} else if (args[0] === '--new-handoff') {
|
|
170
318
|
result.mode = 'new-handoff';
|
|
171
319
|
args.shift();
|
|
320
|
+
} else if (args[0] && !args[0].startsWith('-')) {
|
|
321
|
+
throw new Error(formatError(unsupportedCommandMessage(args[0])));
|
|
172
322
|
}
|
|
173
323
|
|
|
174
324
|
const positional = [];
|
|
@@ -176,6 +326,11 @@ function parseArgs(argv) {
|
|
|
176
326
|
for (let index = 0; index < args.length; index += 1) {
|
|
177
327
|
const arg = args[index];
|
|
178
328
|
|
|
329
|
+
if (arg === '--') {
|
|
330
|
+
result.evidenceArgs = args.slice(index + 1);
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
|
|
179
334
|
if (arg === '-h' || arg === '--help') {
|
|
180
335
|
result.help = true;
|
|
181
336
|
continue;
|
|
@@ -216,6 +371,11 @@ function parseArgs(argv) {
|
|
|
216
371
|
continue;
|
|
217
372
|
}
|
|
218
373
|
|
|
374
|
+
if (arg === '--local') {
|
|
375
|
+
result.checkSliceLocal = true;
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
|
|
219
379
|
if (arg === '--close-baseline') {
|
|
220
380
|
result.closeBaseline = true;
|
|
221
381
|
continue;
|
|
@@ -226,11 +386,45 @@ function parseArgs(argv) {
|
|
|
226
386
|
continue;
|
|
227
387
|
}
|
|
228
388
|
|
|
389
|
+
if (arg === '--fix') {
|
|
390
|
+
result.doctorFix = true;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
|
|
229
394
|
if (arg === '--dry-run') {
|
|
230
395
|
result.dryRun = true;
|
|
231
396
|
continue;
|
|
232
397
|
}
|
|
233
398
|
|
|
399
|
+
if (arg === '--commit') {
|
|
400
|
+
result.aiCommit = true;
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (arg === '--execute') {
|
|
405
|
+
result.aiExecute = true;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (arg === '--create') {
|
|
410
|
+
result.aiCreate = true;
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (arg === '--mode') {
|
|
415
|
+
const value = args[++index];
|
|
416
|
+
if (!value) {
|
|
417
|
+
throw new Error(formatError('missing value for --mode'));
|
|
418
|
+
}
|
|
419
|
+
result.aiExecutionMode = value;
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (arg === '--allow-dirty') {
|
|
424
|
+
result.aiAllowDirty = true;
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
|
|
234
428
|
if (arg === '--minimal') {
|
|
235
429
|
result.initMinimal = true;
|
|
236
430
|
continue;
|
|
@@ -266,6 +460,11 @@ function parseArgs(argv) {
|
|
|
266
460
|
continue;
|
|
267
461
|
}
|
|
268
462
|
|
|
463
|
+
if (arg === '--include-completed') {
|
|
464
|
+
result.includeCompleted = true;
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
|
|
269
468
|
if (arg === '--show-conflicts') {
|
|
270
469
|
result.showConflicts = true;
|
|
271
470
|
continue;
|
|
@@ -319,6 +518,35 @@ function parseArgs(argv) {
|
|
|
319
518
|
throw new Error(formatError('missing value for --provider'));
|
|
320
519
|
}
|
|
321
520
|
result.aiProvider = value;
|
|
521
|
+
result.prepareProvider = value;
|
|
522
|
+
result.aiProviderExplicit = true;
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (arg === '--model') {
|
|
527
|
+
const value = args[++index];
|
|
528
|
+
if (!value) {
|
|
529
|
+
throw new Error(formatError('missing value for --model'));
|
|
530
|
+
}
|
|
531
|
+
result.aiModel = value;
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (arg === '--label') {
|
|
536
|
+
const value = args[++index];
|
|
537
|
+
if (!value) {
|
|
538
|
+
throw new Error(formatError('missing value for --label'));
|
|
539
|
+
}
|
|
540
|
+
result.aiLabel = value;
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (arg === '--version') {
|
|
545
|
+
const value = args[++index];
|
|
546
|
+
if (!value) {
|
|
547
|
+
throw new Error(formatError('missing value for --version'));
|
|
548
|
+
}
|
|
549
|
+
result.aiVersion = value;
|
|
322
550
|
continue;
|
|
323
551
|
}
|
|
324
552
|
|
|
@@ -398,6 +626,47 @@ function parseArgs(argv) {
|
|
|
398
626
|
continue;
|
|
399
627
|
}
|
|
400
628
|
|
|
629
|
+
if (arg === '--base') {
|
|
630
|
+
const value = args[++index];
|
|
631
|
+
if (!value) {
|
|
632
|
+
throw new Error(formatError('missing value for --base'));
|
|
633
|
+
}
|
|
634
|
+
result.aiBaseBranch = value;
|
|
635
|
+
result.baseBranchExplicit = true;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
if (arg === '--output') {
|
|
640
|
+
const value = args[++index];
|
|
641
|
+
if (!value) {
|
|
642
|
+
throw new Error(formatError('missing value for --output'));
|
|
643
|
+
}
|
|
644
|
+
result.evidenceOutput = value;
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
if (arg === '--max-output') {
|
|
649
|
+
const value = args[++index];
|
|
650
|
+
if (typeof value === 'undefined') {
|
|
651
|
+
throw new Error(formatError('missing value for --max-output'));
|
|
652
|
+
}
|
|
653
|
+
const parsed = Number.parseInt(value, 10);
|
|
654
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
655
|
+
throw new Error(formatError('invalid value for --max-output'));
|
|
656
|
+
}
|
|
657
|
+
result.evidenceMaxOutput = parsed;
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (arg === '--title') {
|
|
662
|
+
const value = args[++index];
|
|
663
|
+
if (!value) {
|
|
664
|
+
throw new Error(formatError('missing value for --title'));
|
|
665
|
+
}
|
|
666
|
+
result.aiTitle = value;
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
|
|
401
670
|
if (arg === '--phase') {
|
|
402
671
|
const value = args[++index];
|
|
403
672
|
if (!value) {
|
|
@@ -440,6 +709,7 @@ function parseArgs(argv) {
|
|
|
440
709
|
throw new Error(formatError('missing value for --dir'));
|
|
441
710
|
}
|
|
442
711
|
result.targetDir = value;
|
|
712
|
+
result.targetDirExplicit = true;
|
|
443
713
|
continue;
|
|
444
714
|
}
|
|
445
715
|
|
|
@@ -462,17 +732,78 @@ function parseArgs(argv) {
|
|
|
462
732
|
if (positional.length > 0) {
|
|
463
733
|
throw new Error(formatError('plan does not accept positional arguments; use --spec <slug>'));
|
|
464
734
|
}
|
|
735
|
+
} else if (result.mode === 'flow') {
|
|
736
|
+
if (positional.length > 0) {
|
|
737
|
+
throw new Error(formatError('flow does not accept positional arguments'));
|
|
738
|
+
}
|
|
465
739
|
} else if (result.mode === 'ai') {
|
|
466
740
|
if (!result.aiCommand && positional.length > 0) {
|
|
467
741
|
result.aiCommand = positional.shift();
|
|
468
742
|
}
|
|
743
|
+
if (result.aiCommand === 'agent') {
|
|
744
|
+
if (!result.aiAgentCommand && positional.length > 0) {
|
|
745
|
+
result.aiAgentCommand = positional.shift();
|
|
746
|
+
}
|
|
747
|
+
if (!result.aiAgentRole && positional.length > 0) {
|
|
748
|
+
result.aiAgentRole = positional.shift();
|
|
749
|
+
}
|
|
750
|
+
}
|
|
469
751
|
if (positional.length > 0) {
|
|
470
752
|
throw new Error(formatError('ai does not accept extra positional arguments'));
|
|
471
753
|
}
|
|
754
|
+
} else if (result.mode === 'prepare') {
|
|
755
|
+
if (positional.length > 0) {
|
|
756
|
+
throw new Error(formatError('prepare does not accept positional arguments'));
|
|
757
|
+
}
|
|
472
758
|
} else if (result.mode === 'refresh-active-slices') {
|
|
473
759
|
if (positional.length > 0) {
|
|
474
760
|
throw new Error(formatError('refresh-active-slices does not accept positional arguments'));
|
|
475
761
|
}
|
|
762
|
+
} else if (result.mode === 'spec') {
|
|
763
|
+
if (!result.specCommand && positional.length > 0) {
|
|
764
|
+
result.specCommand = positional.shift();
|
|
765
|
+
}
|
|
766
|
+
if (!result.specCommand) {
|
|
767
|
+
throw new Error(formatError('missing spec subcommand. Use: npx create-quiver spec <create|start|status|close>'));
|
|
768
|
+
}
|
|
769
|
+
if (result.specCommand !== 'create' && positional.length > 0) {
|
|
770
|
+
result.targetDir = positional.shift();
|
|
771
|
+
}
|
|
772
|
+
if (result.specCommand === 'create' && positional.length > 0) {
|
|
773
|
+
throw new Error(formatError('spec create does not accept positional arguments; use --input <file> or --spec <slug>'));
|
|
774
|
+
}
|
|
775
|
+
} else if (result.mode === 'evidence') {
|
|
776
|
+
if (!result.evidenceCommand && positional.length > 0) {
|
|
777
|
+
result.evidenceCommand = positional.shift();
|
|
778
|
+
}
|
|
779
|
+
if (!result.evidenceCommand) {
|
|
780
|
+
throw new Error(formatError('missing evidence subcommand. Use: npx create-quiver evidence run -- <command>'));
|
|
781
|
+
}
|
|
782
|
+
if (result.evidenceCommand !== 'run') {
|
|
783
|
+
throw new Error(formatError(`unsupported evidence subcommand: ${result.evidenceCommand}. Supported tasks: run`));
|
|
784
|
+
}
|
|
785
|
+
if (positional.length > 0) {
|
|
786
|
+
throw new Error(formatError('evidence run does not accept positional arguments before --'));
|
|
787
|
+
}
|
|
788
|
+
} else if (result.mode === 'demo') {
|
|
789
|
+
if (!result.demoCommand && positional.length > 0) {
|
|
790
|
+
result.demoCommand = positional.shift();
|
|
791
|
+
}
|
|
792
|
+
if (!result.demoName && positional.length > 0) {
|
|
793
|
+
result.demoName = positional.shift();
|
|
794
|
+
}
|
|
795
|
+
if (!result.demoCommand) {
|
|
796
|
+
throw new Error(formatError('missing demo subcommand. Use: npx create-quiver demo create spec-viewer'));
|
|
797
|
+
}
|
|
798
|
+
if (!SUPPORTED_DEMO_COMMANDS.has(result.demoCommand)) {
|
|
799
|
+
throw new Error(formatError(`unsupported demo subcommand: ${result.demoCommand}. Supported tasks: create`));
|
|
800
|
+
}
|
|
801
|
+
if (result.demoName !== 'spec-viewer') {
|
|
802
|
+
throw new Error(formatError(`unsupported demo: ${result.demoName || '(missing)'}. Supported demos: spec-viewer`));
|
|
803
|
+
}
|
|
804
|
+
if (positional.length > 0) {
|
|
805
|
+
throw new Error(formatError('demo create spec-viewer does not accept positional target paths; use --dir <target-dir>'));
|
|
806
|
+
}
|
|
476
807
|
} else {
|
|
477
808
|
if (positional.length > 0) {
|
|
478
809
|
result.targetDir = positional.shift();
|
|
@@ -698,6 +1029,43 @@ function escapeMarkdownCell(value) {
|
|
|
698
1029
|
return String(value).replace(/\|/g, '\\|');
|
|
699
1030
|
}
|
|
700
1031
|
|
|
1032
|
+
function summarizeSkippedPaths(scan) {
|
|
1033
|
+
const details = Array.isArray(scan.skipped_path_details) && scan.skipped_path_details.length > 0
|
|
1034
|
+
? scan.skipped_path_details
|
|
1035
|
+
: (Array.isArray(scan.skipped_paths) ? scan.skipped_paths.map((item) => ({ reason: 'excluded path', path: item })) : []);
|
|
1036
|
+
const counts = new Map();
|
|
1037
|
+
const dependencySegments = new Set(['node_modules', '.pnpm-store', '.npm', '.yarn']);
|
|
1038
|
+
const outputSegments = new Set(['dist', 'build', 'coverage', 'out', 'tmp', 'temp', 'cache', '.cache', '.turbo', '.next', '.nuxt', '.parcel-cache', 'generated', 'gen', 'artifacts', 'reports', 'vendor', 'target']);
|
|
1039
|
+
|
|
1040
|
+
for (const item of details) {
|
|
1041
|
+
const reason = item.reason || 'excluded path';
|
|
1042
|
+
let label = reason;
|
|
1043
|
+
if (reason === 'env-file') {
|
|
1044
|
+
label = 'env files';
|
|
1045
|
+
} else if (reason === 'git-metadata') {
|
|
1046
|
+
label = 'git metadata';
|
|
1047
|
+
} else if (reason === 'hidden-directory') {
|
|
1048
|
+
label = 'hidden directories';
|
|
1049
|
+
} else if (reason.startsWith('secret-file:')) {
|
|
1050
|
+
label = 'secret files';
|
|
1051
|
+
} else if (reason.startsWith('unsafe-segment:')) {
|
|
1052
|
+
const segment = reason.slice('unsafe-segment:'.length);
|
|
1053
|
+
if (segment === '.quiver') {
|
|
1054
|
+
label = 'local AI state';
|
|
1055
|
+
} else if (dependencySegments.has(segment)) {
|
|
1056
|
+
label = 'dependency folders';
|
|
1057
|
+
} else if (outputSegments.has(segment)) {
|
|
1058
|
+
label = 'generated/output/cache folders';
|
|
1059
|
+
} else {
|
|
1060
|
+
label = segment;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
counts.set(label, (counts.get(label) || 0) + 1);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
return Array.from(counts.entries()).map(([reason, count]) => ({ reason, count }));
|
|
1067
|
+
}
|
|
1068
|
+
|
|
701
1069
|
function collectPackageManagers(projectRoot) {
|
|
702
1070
|
const packageManagerField = readJsonIfExists(path.join(projectRoot, 'package.json'))?.packageManager;
|
|
703
1071
|
|
|
@@ -725,6 +1093,7 @@ function collectPackageManagers(projectRoot) {
|
|
|
725
1093
|
function collectProjectFiles(projectRoot, maxDepth = 2) {
|
|
726
1094
|
const files = [];
|
|
727
1095
|
const skippedPaths = [];
|
|
1096
|
+
const skippedPathDetails = [];
|
|
728
1097
|
const ignoredDirs = new Set([
|
|
729
1098
|
'.git',
|
|
730
1099
|
'node_modules',
|
|
@@ -741,6 +1110,12 @@ function collectProjectFiles(projectRoot, maxDepth = 2) {
|
|
|
741
1110
|
]);
|
|
742
1111
|
const allowedHiddenDirs = new Set(['.github', '.vscode', '.devcontainer']);
|
|
743
1112
|
|
|
1113
|
+
function skipPath(relativePath, reason) {
|
|
1114
|
+
const normalized = relativePath.split(path.sep).join('/');
|
|
1115
|
+
skippedPaths.push(normalized);
|
|
1116
|
+
skippedPathDetails.push({ path: normalized, reason });
|
|
1117
|
+
}
|
|
1118
|
+
|
|
744
1119
|
function walk(currentDir, depth, relativeDir = '') {
|
|
745
1120
|
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
746
1121
|
|
|
@@ -750,12 +1125,18 @@ function collectProjectFiles(projectRoot, maxDepth = 2) {
|
|
|
750
1125
|
|
|
751
1126
|
if (entry.isDirectory()) {
|
|
752
1127
|
if (ignoredDirs.has(entry.name)) {
|
|
753
|
-
|
|
1128
|
+
skipPath(entryRelativePath, `unsafe-segment:${entry.name}`);
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
const directoryReason = getContextPathExclusionReason(entryRelativePath);
|
|
1133
|
+
if (directoryReason) {
|
|
1134
|
+
skipPath(entryRelativePath, directoryReason);
|
|
754
1135
|
continue;
|
|
755
1136
|
}
|
|
756
1137
|
|
|
757
1138
|
if (entry.name.startsWith('.') && !allowedHiddenDirs.has(entry.name)) {
|
|
758
|
-
|
|
1139
|
+
skipPath(entryRelativePath, 'hidden-directory');
|
|
759
1140
|
continue;
|
|
760
1141
|
}
|
|
761
1142
|
|
|
@@ -766,13 +1147,19 @@ function collectProjectFiles(projectRoot, maxDepth = 2) {
|
|
|
766
1147
|
continue;
|
|
767
1148
|
}
|
|
768
1149
|
|
|
1150
|
+
const fileReason = getContextPathExclusionReason(entryRelativePath);
|
|
1151
|
+
if (fileReason) {
|
|
1152
|
+
skipPath(entryRelativePath, fileReason);
|
|
1153
|
+
continue;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
769
1156
|
files.push(entryRelativePath);
|
|
770
1157
|
}
|
|
771
1158
|
}
|
|
772
1159
|
|
|
773
1160
|
walk(projectRoot, 0);
|
|
774
1161
|
|
|
775
|
-
return { files, skippedPaths };
|
|
1162
|
+
return { files, skipped_path_details: skippedPathDetails, skippedPaths };
|
|
776
1163
|
}
|
|
777
1164
|
|
|
778
1165
|
function collectRootEntries(projectRoot) {
|
|
@@ -820,6 +1207,7 @@ function collectLanguageSignals(files) {
|
|
|
820
1207
|
}
|
|
821
1208
|
|
|
822
1209
|
const languages = [];
|
|
1210
|
+
const seenLanguages = new Set();
|
|
823
1211
|
const extToLanguage = new Map([
|
|
824
1212
|
['.ts', 'typescript'],
|
|
825
1213
|
['.tsx', 'typescript'],
|
|
@@ -845,14 +1233,90 @@ function collectLanguageSignals(files) {
|
|
|
845
1233
|
]);
|
|
846
1234
|
|
|
847
1235
|
for (const [ext, language] of extToLanguage.entries()) {
|
|
848
|
-
if (extensions.has(ext)) {
|
|
1236
|
+
if (extensions.has(ext) && !seenLanguages.has(language)) {
|
|
849
1237
|
languages.push(language);
|
|
1238
|
+
seenLanguages.add(language);
|
|
850
1239
|
}
|
|
851
1240
|
}
|
|
852
1241
|
|
|
853
1242
|
return languages;
|
|
854
1243
|
}
|
|
855
1244
|
|
|
1245
|
+
function parseCreateQuiverScriptCommand(command) {
|
|
1246
|
+
const normalized = String(command || '').trim();
|
|
1247
|
+
const match = normalized.match(/^npx\s+create-quiver(?:@[^\s]+)?\s+(.+)$/);
|
|
1248
|
+
if (!match) {
|
|
1249
|
+
return null;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
const tokens = match[1].split(/\s+/).filter(Boolean);
|
|
1253
|
+
if (tokens.length === 0) {
|
|
1254
|
+
return null;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
return {
|
|
1258
|
+
commandName: tokens[0],
|
|
1259
|
+
subcommand: tokens[1] || '',
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
function findUnsupportedCreateQuiverScripts(scripts = {}) {
|
|
1264
|
+
const unsupported = [];
|
|
1265
|
+
|
|
1266
|
+
for (const [scriptName, command] of Object.entries(scripts)) {
|
|
1267
|
+
const parsed = parseCreateQuiverScriptCommand(command);
|
|
1268
|
+
if (!parsed) {
|
|
1269
|
+
continue;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
if (!SUPPORTED_COMMAND_MODES.has(parsed.commandName)) {
|
|
1273
|
+
unsupported.push({
|
|
1274
|
+
command,
|
|
1275
|
+
reason: `unsupported command "${parsed.commandName}"`,
|
|
1276
|
+
scriptName,
|
|
1277
|
+
});
|
|
1278
|
+
continue;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
if (parsed.commandName === 'ai' && !SUPPORTED_AI_COMMANDS.has(parsed.subcommand)) {
|
|
1282
|
+
unsupported.push({
|
|
1283
|
+
command,
|
|
1284
|
+
reason: `unsupported ai subcommand "${parsed.subcommand || '(missing)'}"`,
|
|
1285
|
+
scriptName,
|
|
1286
|
+
});
|
|
1287
|
+
continue;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
if (parsed.commandName === 'spec' && !SUPPORTED_SPEC_COMMANDS.has(parsed.subcommand)) {
|
|
1291
|
+
unsupported.push({
|
|
1292
|
+
command,
|
|
1293
|
+
reason: `unsupported spec subcommand "${parsed.subcommand || '(missing)'}"`,
|
|
1294
|
+
scriptName,
|
|
1295
|
+
});
|
|
1296
|
+
continue;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
if (parsed.commandName === 'demo' && !SUPPORTED_DEMO_COMMANDS.has(parsed.subcommand)) {
|
|
1300
|
+
unsupported.push({
|
|
1301
|
+
command,
|
|
1302
|
+
reason: `unsupported demo subcommand "${parsed.subcommand || '(missing)'}"`,
|
|
1303
|
+
scriptName,
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
return unsupported;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
function detectNodeProject(files, rootEntries, packageJson, languages) {
|
|
1312
|
+
const hasPackageJson = Boolean(packageJson);
|
|
1313
|
+
const hasJavaScriptSignals = languages.some((language) => language === 'javascript' || language === 'typescript');
|
|
1314
|
+
const hasSourceDirectories = detectSourceDirectories(rootEntries).length > 0;
|
|
1315
|
+
const hasSourceFiles = files.some((file) => /\.(?:c|m)?jsx?$/i.test(file) || /\.(?:c|m)?tsx?$/i.test(file));
|
|
1316
|
+
|
|
1317
|
+
return hasJavaScriptSignals && (hasPackageJson || hasSourceDirectories || hasSourceFiles);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
856
1320
|
function collectWorkspaces(packageJson) {
|
|
857
1321
|
if (!packageJson) {
|
|
858
1322
|
return [];
|
|
@@ -982,6 +1446,11 @@ function detectFrameworks(projectRoot, files, rootEntries, packageJson) {
|
|
|
982
1446
|
evidence.push({ framework: 'react', signals: ['react', 'typescript files'] });
|
|
983
1447
|
}
|
|
984
1448
|
|
|
1449
|
+
if (frameworks.length === 0 && detectNodeProject(files, rootEntries, packageJson, languages)) {
|
|
1450
|
+
frameworks.push('node');
|
|
1451
|
+
evidence.push({ framework: 'node', signals: ['package.json', 'javascript or typescript source files'] });
|
|
1452
|
+
}
|
|
1453
|
+
|
|
985
1454
|
const primary = frameworks[0] || 'unknown';
|
|
986
1455
|
|
|
987
1456
|
return {
|
|
@@ -1076,7 +1545,7 @@ function detectRisks(projectRoot, scan) {
|
|
|
1076
1545
|
function buildProjectScan(projectRoot) {
|
|
1077
1546
|
const packageJson = readJsonIfExists(path.join(projectRoot, 'package.json'));
|
|
1078
1547
|
const rootEntries = collectRootEntries(projectRoot);
|
|
1079
|
-
const { files, skippedPaths } = collectProjectFiles(projectRoot);
|
|
1548
|
+
const { files, skippedPaths, skipped_path_details } = collectProjectFiles(projectRoot);
|
|
1080
1549
|
const topLevelDirectories = rootEntries.filter((entry) => entry.type === 'directory' && !entry.name.startsWith('.')).map((entry) => entry.name);
|
|
1081
1550
|
const sourceDirectories = detectSourceDirectories(rootEntries);
|
|
1082
1551
|
const configFiles = detectConfigFiles(rootEntries);
|
|
@@ -1134,6 +1603,7 @@ function buildProjectScan(projectRoot) {
|
|
|
1134
1603
|
},
|
|
1135
1604
|
risks: [],
|
|
1136
1605
|
skipped_paths: skippedPaths,
|
|
1606
|
+
skipped_path_details,
|
|
1137
1607
|
};
|
|
1138
1608
|
|
|
1139
1609
|
scan.risks = detectRisks(projectRoot, scan);
|
|
@@ -1250,7 +1720,7 @@ function renderProjectMap(scan) {
|
|
|
1250
1720
|
}
|
|
1251
1721
|
|
|
1252
1722
|
const relevantScripts = Object.entries(scan.commands.scripts)
|
|
1253
|
-
.filter(([name]) => /(^|:)(analyze|doctor|migrate|test|build|lint|dev|start|check)(:|$)|analyze|doctor|migrate|test|build|lint|dev|start|check/i.test(name))
|
|
1723
|
+
.filter(([name]) => /(^|:)(analyze|doctor|migrate|validate|test|build|lint|dev|start|check)(:|$)|analyze|doctor|migrate|validate|test|build|lint|dev|start|check/i.test(name))
|
|
1254
1724
|
.slice(0, 12);
|
|
1255
1725
|
|
|
1256
1726
|
if (relevantScripts.length > 0) {
|
|
@@ -1310,9 +1780,10 @@ function renderProjectMap(scan) {
|
|
|
1310
1780
|
|
|
1311
1781
|
lines.push('');
|
|
1312
1782
|
lines.push('## Skipped Paths');
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1783
|
+
const skippedSummaries = summarizeSkippedPaths(scan);
|
|
1784
|
+
if (skippedSummaries.length > 0) {
|
|
1785
|
+
for (const skippedPath of skippedSummaries) {
|
|
1786
|
+
lines.push(`- ${skippedPath.reason}: ${skippedPath.count}`);
|
|
1316
1787
|
}
|
|
1317
1788
|
} else {
|
|
1318
1789
|
lines.push('- None');
|
|
@@ -1320,10 +1791,8 @@ function renderProjectMap(scan) {
|
|
|
1320
1791
|
|
|
1321
1792
|
lines.push('');
|
|
1322
1793
|
lines.push('## Do Not Read First');
|
|
1323
|
-
if (
|
|
1324
|
-
|
|
1325
|
-
lines.push(`- ${skippedPath}`);
|
|
1326
|
-
}
|
|
1794
|
+
if (skippedSummaries.length > 0) {
|
|
1795
|
+
lines.push('- Hidden, generated, secret, and cache paths are excluded from the analysis scan.');
|
|
1327
1796
|
} else {
|
|
1328
1797
|
lines.push('- None detected, but still prioritize docs and config files before source trees.');
|
|
1329
1798
|
}
|
|
@@ -1351,11 +1820,13 @@ function runAnalyze(targetDir) {
|
|
|
1351
1820
|
|
|
1352
1821
|
const scan = buildProjectScan(projectRoot);
|
|
1353
1822
|
const artifacts = writeProjectScanArtifacts(projectRoot, scan);
|
|
1823
|
+
const aiContextPath = refreshAiContextDoc(projectRoot, scan);
|
|
1354
1824
|
updateStateForAnalyze(projectRoot, CLI_VERSION);
|
|
1355
1825
|
|
|
1356
1826
|
console.log(`Project analysis completed for ${projectRoot}`);
|
|
1357
1827
|
console.log(`Wrote ${relativePosixPath(projectRoot, artifacts.jsonPath)}`);
|
|
1358
1828
|
console.log(`Wrote ${relativePosixPath(projectRoot, artifacts.mdPath)}`);
|
|
1829
|
+
console.log(`Wrote ${relativePosixPath(projectRoot, aiContextPath)}`);
|
|
1359
1830
|
console.log(`Detected primary stack: ${scan.stack.primary}`);
|
|
1360
1831
|
console.log(`Detected package manager: ${scan.project.package_manager}`);
|
|
1361
1832
|
}
|
|
@@ -1410,7 +1881,7 @@ function runMigrate(targetDir, options = {}) {
|
|
|
1410
1881
|
}
|
|
1411
1882
|
}
|
|
1412
1883
|
|
|
1413
|
-
function runDoctor(targetDir) {
|
|
1884
|
+
function runDoctor(targetDir, options = {}) {
|
|
1414
1885
|
const projectRoot = resolveTargetRoot(process.cwd(), targetDir);
|
|
1415
1886
|
|
|
1416
1887
|
if (!fs.existsSync(projectRoot)) {
|
|
@@ -1421,6 +1892,17 @@ function runDoctor(targetDir) {
|
|
|
1421
1892
|
throw new Error(formatError('doctor requires a project previously initialized by Quiver.\nRun init first: npx create-quiver --name "Project Name"'));
|
|
1422
1893
|
}
|
|
1423
1894
|
|
|
1895
|
+
const fixPlan = buildDoctorFixPlan(projectRoot);
|
|
1896
|
+
if (options.fix) {
|
|
1897
|
+
if (options.dryRun) {
|
|
1898
|
+
console.log(formatDoctorFixPlan(fixPlan, { dryRun: true }));
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
applyDoctorFixPlan(projectRoot, fixPlan);
|
|
1903
|
+
console.log(formatDoctorFixPlan(fixPlan));
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1424
1906
|
const doctorReport = collectDoctorReport(projectRoot);
|
|
1425
1907
|
const specSlugs = doctorReport.specSlugs;
|
|
1426
1908
|
const specRequiredFiles = specSlugs.flatMap((projectSlug) => [
|
|
@@ -1475,12 +1957,18 @@ function runDoctor(targetDir) {
|
|
|
1475
1957
|
const missingNodeNativeScripts = ['quiver:migrate', 'quiver:analyze', 'quiver:doctor']
|
|
1476
1958
|
.filter((name) => typeof pkg.scripts?.[name] !== 'string');
|
|
1477
1959
|
const missingAiScripts = [
|
|
1960
|
+
'quiver:ai:agent',
|
|
1478
1961
|
'quiver:ai:onboard',
|
|
1479
1962
|
'quiver:ai:plan',
|
|
1963
|
+
'quiver:ai:review-plan',
|
|
1964
|
+
'quiver:ai:approve',
|
|
1965
|
+
'quiver:ai:prompt-slice',
|
|
1480
1966
|
'quiver:ai:execute-slice',
|
|
1967
|
+
'quiver:ai:execute-plan',
|
|
1481
1968
|
'quiver:ai:pr',
|
|
1482
1969
|
'quiver:ai:doctor',
|
|
1483
1970
|
].filter((name) => typeof pkg.scripts?.[name] !== 'string');
|
|
1971
|
+
const unsupportedCreateQuiverScripts = findUnsupportedCreateQuiverScripts(pkg.scripts || {});
|
|
1484
1972
|
const hasScanArtifacts = hasProjectScanArtifact(projectRoot)
|
|
1485
1973
|
&& fs.existsSync(path.join(projectRoot, PROJECT_MAP_RELATIVE_PATH));
|
|
1486
1974
|
const quiverState = readState(projectRoot);
|
|
@@ -1523,6 +2011,9 @@ function runDoctor(targetDir) {
|
|
|
1523
2011
|
if (legacyOnlyScripts.length > 0) {
|
|
1524
2012
|
console.log(`- Warning: legacy Bash workflow scripts detected for ${legacyOnlyScripts.join(', ')}. Run npx create-quiver migrate to add quiver:* npm scripts.`);
|
|
1525
2013
|
}
|
|
2014
|
+
for (const script of unsupportedCreateQuiverScripts) {
|
|
2015
|
+
console.log(`- Warning: package.json script ${script.scriptName} targets ${script.reason}: \`${script.command}\`. Update create-quiver or regenerate scripts with npx create-quiver migrate.`);
|
|
2016
|
+
}
|
|
1526
2017
|
for (const warning of softWarnings) {
|
|
1527
2018
|
console.log(`- Warning: ${warning}`);
|
|
1528
2019
|
}
|
|
@@ -1540,7 +2031,7 @@ function runDoctor(targetDir) {
|
|
|
1540
2031
|
console.log(`- Validate a slice: npx create-quiver check-slice specs/${projectSlug}/slices/<slice-id>/slice.json`);
|
|
1541
2032
|
console.log(`- Validate the PR gate: npx create-quiver check-pr specs/${projectSlug}/slices/<slice-id>/slice.json`);
|
|
1542
2033
|
} else {
|
|
1543
|
-
console.log('- Create real specs and slices only after acceptance criteria and the technical plan
|
|
2034
|
+
console.log('- Create real specs and slices only after acceptance criteria are approved and the technical plan is reviewed and approved.');
|
|
1544
2035
|
}
|
|
1545
2036
|
}
|
|
1546
2037
|
|
|
@@ -1550,7 +2041,7 @@ function printInitNextSteps(targetDir, projectName) {
|
|
|
1550
2041
|
console.log(`- Review AGENTS.md, then ${path.join(targetDir, 'docs', 'AI_ONBOARDING_PROMPT.md')}`);
|
|
1551
2042
|
console.log(`- Review ${path.join(targetDir, 'docs', 'WORKFLOW.md')}`);
|
|
1552
2043
|
console.log('- Analyze the project with npx create-quiver analyze');
|
|
1553
|
-
console.log('- Create real specs and slices after acceptance criteria and the technical plan
|
|
2044
|
+
console.log('- Create real specs and slices after acceptance criteria are approved and the technical plan is reviewed and approved.');
|
|
1554
2045
|
}
|
|
1555
2046
|
|
|
1556
2047
|
async function run(argv) {
|
|
@@ -1566,8 +2057,16 @@ async function run(argv) {
|
|
|
1566
2057
|
return;
|
|
1567
2058
|
}
|
|
1568
2059
|
|
|
2060
|
+
if (args.mode === 'flow') {
|
|
2061
|
+
await runFlow(process.cwd(), {
|
|
2062
|
+
json: args.json,
|
|
2063
|
+
});
|
|
2064
|
+
return;
|
|
2065
|
+
}
|
|
2066
|
+
|
|
1569
2067
|
if (args.mode === 'plan') {
|
|
1570
2068
|
runPlan(process.cwd(), {
|
|
2069
|
+
includeCompleted: args.includeCompleted,
|
|
1571
2070
|
json: args.json,
|
|
1572
2071
|
onlyReady: args.onlyReady,
|
|
1573
2072
|
specSlug: args.specSlug,
|
|
@@ -1576,9 +2075,31 @@ async function run(argv) {
|
|
|
1576
2075
|
return;
|
|
1577
2076
|
}
|
|
1578
2077
|
|
|
2078
|
+
if (args.mode === 'prepare') {
|
|
2079
|
+
await runPrepare(process.cwd(), {
|
|
2080
|
+
dryRun: args.dryRun,
|
|
2081
|
+
identityFile: args.aiIdentityFile || undefined,
|
|
2082
|
+
provider: args.prepareProvider || undefined,
|
|
2083
|
+
sshHostAlias: args.aiSshHostAlias || undefined,
|
|
2084
|
+
});
|
|
2085
|
+
return;
|
|
2086
|
+
}
|
|
2087
|
+
|
|
1579
2088
|
if (args.mode === 'ai') {
|
|
1580
2089
|
if (!args.aiCommand) {
|
|
1581
|
-
throw new Error(formatError('missing ai subcommand. Use: npx create-quiver ai onboard | plan | execute-slice | doctor | pr'));
|
|
2090
|
+
throw new Error(formatError('missing ai subcommand. Use: npx create-quiver ai onboard | prepare-context | plan | review-plan | approve | approvals | agent | prompt-slice | execute-slice | execute-plan | doctor | pr'));
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
if (args.aiCommand === 'agent') {
|
|
2094
|
+
runAiAgent(process.cwd(), {
|
|
2095
|
+
command: args.aiAgentCommand,
|
|
2096
|
+
context: args.aiContext || undefined,
|
|
2097
|
+
label: args.aiLabel || undefined,
|
|
2098
|
+
model: args.aiModel || undefined,
|
|
2099
|
+
provider: args.aiProviderExplicit ? args.aiProvider : undefined,
|
|
2100
|
+
role: args.aiAgentRole || undefined,
|
|
2101
|
+
});
|
|
2102
|
+
return;
|
|
1582
2103
|
}
|
|
1583
2104
|
|
|
1584
2105
|
if (args.aiCommand === 'onboard') {
|
|
@@ -1587,12 +2108,20 @@ async function run(argv) {
|
|
|
1587
2108
|
dryRun: args.dryRun,
|
|
1588
2109
|
input: args.aiInput || undefined,
|
|
1589
2110
|
provider: args.aiProvider,
|
|
2111
|
+
providerExplicit: args.aiProviderExplicit,
|
|
1590
2112
|
role: args.aiRole,
|
|
1591
2113
|
timeout: args.aiTimeout,
|
|
1592
2114
|
});
|
|
1593
2115
|
return;
|
|
1594
2116
|
}
|
|
1595
2117
|
|
|
2118
|
+
if (args.aiCommand === 'prepare-context') {
|
|
2119
|
+
await runAiPrepareContext(process.cwd(), {
|
|
2120
|
+
dryRun: args.dryRun,
|
|
2121
|
+
});
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
|
|
1596
2125
|
if (args.aiCommand === 'plan') {
|
|
1597
2126
|
await runAiPlan(process.cwd(), {
|
|
1598
2127
|
context: args.aiContext || undefined,
|
|
@@ -1600,6 +2129,7 @@ async function run(argv) {
|
|
|
1600
2129
|
input: args.aiInput || undefined,
|
|
1601
2130
|
phase: args.aiPhase,
|
|
1602
2131
|
provider: args.aiProvider,
|
|
2132
|
+
providerExplicit: args.aiProviderExplicit,
|
|
1603
2133
|
role: args.aiRole,
|
|
1604
2134
|
specSlug: args.specSlug || undefined,
|
|
1605
2135
|
timeout: args.aiTimeout,
|
|
@@ -1607,11 +2137,41 @@ async function run(argv) {
|
|
|
1607
2137
|
return;
|
|
1608
2138
|
}
|
|
1609
2139
|
|
|
2140
|
+
if (args.aiCommand === 'review-plan') {
|
|
2141
|
+
await runAiReviewPlan(process.cwd(), {
|
|
2142
|
+
context: args.aiContext || undefined,
|
|
2143
|
+
dryRun: args.dryRun,
|
|
2144
|
+
input: args.aiInput || undefined,
|
|
2145
|
+
provider: args.aiProvider,
|
|
2146
|
+
providerExplicit: args.aiProviderExplicit,
|
|
2147
|
+
timeout: args.aiTimeout,
|
|
2148
|
+
});
|
|
2149
|
+
return;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
if (args.aiCommand === 'approve') {
|
|
2153
|
+
await runAiApprove(process.cwd(), {
|
|
2154
|
+
dryRun: args.dryRun,
|
|
2155
|
+
input: args.aiInput || undefined,
|
|
2156
|
+
phase: args.aiPhase,
|
|
2157
|
+
version: args.aiVersion || undefined,
|
|
2158
|
+
});
|
|
2159
|
+
return;
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
if (args.aiCommand === 'approvals' || args.aiCommand === 'approval-status') {
|
|
2163
|
+
await runAiApprovalStatus(process.cwd());
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
1610
2167
|
if (args.aiCommand === 'execute-slice') {
|
|
1611
2168
|
await runAiExecuteSlice(process.cwd(), {
|
|
2169
|
+
allowDirty: args.aiAllowDirty,
|
|
2170
|
+
commit: args.aiCommit,
|
|
1612
2171
|
context: args.aiContext || undefined,
|
|
1613
2172
|
dryRun: args.dryRun,
|
|
1614
2173
|
provider: args.aiProvider,
|
|
2174
|
+
providerExplicit: args.aiProviderExplicit,
|
|
1615
2175
|
role: args.aiRole,
|
|
1616
2176
|
slice: args.aiSlice || undefined,
|
|
1617
2177
|
timeout: args.aiTimeout,
|
|
@@ -1619,6 +2179,31 @@ async function run(argv) {
|
|
|
1619
2179
|
return;
|
|
1620
2180
|
}
|
|
1621
2181
|
|
|
2182
|
+
if (args.aiCommand === 'prompt-slice' || args.aiCommand === 'executor-prompt') {
|
|
2183
|
+
runAiPromptSlice(process.cwd(), {
|
|
2184
|
+
slice: args.aiSlice || undefined,
|
|
2185
|
+
});
|
|
2186
|
+
return;
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
if (args.aiCommand === 'execute-plan') {
|
|
2190
|
+
await runAiExecutePlan(process.cwd(), {
|
|
2191
|
+
allowDirty: args.aiAllowDirty,
|
|
2192
|
+
commit: args.aiCommit,
|
|
2193
|
+
context: args.aiContext || undefined,
|
|
2194
|
+
dryRun: args.dryRun,
|
|
2195
|
+
execute: args.aiExecute,
|
|
2196
|
+
json: args.json,
|
|
2197
|
+
mode: args.aiExecutionMode,
|
|
2198
|
+
provider: args.aiProvider,
|
|
2199
|
+
providerExplicit: args.aiProviderExplicit,
|
|
2200
|
+
role: args.aiRole,
|
|
2201
|
+
specSlug: args.specSlug || undefined,
|
|
2202
|
+
timeout: args.aiTimeout,
|
|
2203
|
+
});
|
|
2204
|
+
return;
|
|
2205
|
+
}
|
|
2206
|
+
|
|
1622
2207
|
if (args.aiCommand === 'doctor') {
|
|
1623
2208
|
await runAiDoctor(process.cwd(), {
|
|
1624
2209
|
dryRun: args.dryRun,
|
|
@@ -1631,23 +2216,29 @@ async function run(argv) {
|
|
|
1631
2216
|
|
|
1632
2217
|
if (args.aiCommand === 'pr') {
|
|
1633
2218
|
await runAiPr(process.cwd(), {
|
|
2219
|
+
baseBranch: args.aiBaseBranch,
|
|
2220
|
+
create: args.aiCreate,
|
|
1634
2221
|
dryRun: args.dryRun,
|
|
2222
|
+
input: args.aiInput || undefined,
|
|
1635
2223
|
remote: args.aiRemote || undefined,
|
|
1636
2224
|
sshHostAlias: args.aiSshHostAlias || undefined,
|
|
1637
2225
|
identityFile: args.aiIdentityFile || undefined,
|
|
2226
|
+
title: args.aiTitle || undefined,
|
|
1638
2227
|
});
|
|
1639
2228
|
return;
|
|
1640
2229
|
}
|
|
1641
2230
|
|
|
1642
|
-
throw new Error(formatError(`unsupported ai subcommand: ${args.aiCommand}. Supported tasks: onboard, plan, execute-slice, doctor, pr`));
|
|
2231
|
+
throw new Error(formatError(`unsupported ai subcommand: ${args.aiCommand}. Supported tasks: onboard, plan, review-plan, approve, approvals, agent, prompt-slice, execute-slice, execute-plan, doctor, pr`));
|
|
1643
2232
|
}
|
|
1644
2233
|
|
|
1645
2234
|
if (args.mode === 'graph') {
|
|
1646
2235
|
runGraph(process.cwd(), {
|
|
1647
2236
|
format: args.format,
|
|
2237
|
+
includeCompleted: args.includeCompleted,
|
|
1648
2238
|
json: args.json,
|
|
1649
2239
|
level: args.level,
|
|
1650
2240
|
showConflicts: args.showConflicts,
|
|
2241
|
+
specSlug: args.specSlug,
|
|
1651
2242
|
unicode: args.unicode,
|
|
1652
2243
|
});
|
|
1653
2244
|
return;
|
|
@@ -1657,19 +2248,45 @@ async function run(argv) {
|
|
|
1657
2248
|
await runNext(process.cwd(), {
|
|
1658
2249
|
allReady: args.allReady,
|
|
1659
2250
|
autoStart: args.autoStart,
|
|
2251
|
+
includeCompleted: args.includeCompleted,
|
|
1660
2252
|
json: args.json,
|
|
1661
2253
|
specSlug: args.specSlug,
|
|
1662
2254
|
});
|
|
1663
2255
|
return;
|
|
1664
2256
|
}
|
|
1665
2257
|
|
|
2258
|
+
if (args.mode === 'evidence') {
|
|
2259
|
+
const result = runEvidence(process.cwd(), {
|
|
2260
|
+
command: args.evidenceArgs,
|
|
2261
|
+
maxOutput: args.evidenceMaxOutput || undefined,
|
|
2262
|
+
output: args.evidenceOutput || undefined,
|
|
2263
|
+
subcommand: args.evidenceCommand,
|
|
2264
|
+
});
|
|
2265
|
+
process.exitCode = result.exitCode;
|
|
2266
|
+
return;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
if (args.mode === 'demo') {
|
|
2270
|
+
const demoTarget = resolveTargetRoot(process.cwd(), args.targetDirExplicit ? args.targetDir : 'quiver-spec-viewer');
|
|
2271
|
+
runDemo({
|
|
2272
|
+
command: args.demoCommand,
|
|
2273
|
+
demo: args.demoName,
|
|
2274
|
+
dryRun: args.dryRun,
|
|
2275
|
+
targetRoot: demoTarget,
|
|
2276
|
+
});
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2279
|
+
|
|
1666
2280
|
if (args.mode === 'migrate') {
|
|
1667
2281
|
runMigrate(args.targetDir, { skipInstall: args.skipInstall });
|
|
1668
2282
|
return;
|
|
1669
2283
|
}
|
|
1670
2284
|
|
|
1671
2285
|
if (args.mode === 'doctor') {
|
|
1672
|
-
runDoctor(args.targetDir
|
|
2286
|
+
runDoctor(args.targetDir, {
|
|
2287
|
+
dryRun: args.dryRun,
|
|
2288
|
+
fix: args.doctorFix,
|
|
2289
|
+
});
|
|
1673
2290
|
return;
|
|
1674
2291
|
}
|
|
1675
2292
|
|
|
@@ -1680,7 +2297,10 @@ async function run(argv) {
|
|
|
1680
2297
|
|
|
1681
2298
|
if (args.mode === 'check-slice') {
|
|
1682
2299
|
checkSliceReadiness(args.targetDir, {
|
|
2300
|
+
baseBranch: args.baseBranchExplicit ? args.aiBaseBranch : '',
|
|
1683
2301
|
gate: args.gate,
|
|
2302
|
+
local: args.checkSliceLocal,
|
|
2303
|
+
remote: args.aiRemote,
|
|
1684
2304
|
strictOverlap: args.strictOverlap,
|
|
1685
2305
|
});
|
|
1686
2306
|
return;
|
|
@@ -1731,6 +2351,47 @@ async function run(argv) {
|
|
|
1731
2351
|
return;
|
|
1732
2352
|
}
|
|
1733
2353
|
|
|
2354
|
+
if (args.mode === 'spec') {
|
|
2355
|
+
if (args.specCommand === 'create') {
|
|
2356
|
+
runCreateSpec(process.cwd(), {
|
|
2357
|
+
dryRun: args.dryRun,
|
|
2358
|
+
input: args.aiInput || undefined,
|
|
2359
|
+
specSlug: args.specSlug || undefined,
|
|
2360
|
+
});
|
|
2361
|
+
return;
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
if (!args.targetDir || args.targetDir === '.') {
|
|
2365
|
+
throw new Error(formatError('missing spec directory. Use: npx create-quiver spec <start|status|close> <spec-dir>'));
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
if (args.specCommand === 'start') {
|
|
2369
|
+
const report = startSpecWorktree(process.cwd(), args.targetDir);
|
|
2370
|
+
process.stdout.write(formatSpecStartResult(report));
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
if (args.specCommand === 'status') {
|
|
2375
|
+
const report = buildSpecStatus(process.cwd(), args.targetDir);
|
|
2376
|
+
process.stdout.write(formatSpecStatus(report));
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
if (args.specCommand === 'close') {
|
|
2381
|
+
const report = closeSpecWorktree(process.cwd(), args.targetDir, {
|
|
2382
|
+
baseBranch: args.aiBaseBranch,
|
|
2383
|
+
discard: args.discard,
|
|
2384
|
+
dryRun: args.dryRun,
|
|
2385
|
+
force: args.force,
|
|
2386
|
+
remote: args.aiRemote,
|
|
2387
|
+
});
|
|
2388
|
+
process.stdout.write(formatSpecCloseResult(report));
|
|
2389
|
+
return;
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
throw new Error(formatError(`unsupported spec subcommand: ${args.specCommand}. Supported tasks: create, start, status, close`));
|
|
2393
|
+
}
|
|
2394
|
+
|
|
1734
2395
|
const packageRoot = path.resolve(__dirname, '../..');
|
|
1735
2396
|
const targetDir = resolveTargetRoot(process.cwd(), args.targetDir);
|
|
1736
2397
|
const projectName = args.projectName || path.basename(targetDir) || 'Quiver Project';
|
|
@@ -1785,6 +2446,8 @@ async function run(argv) {
|
|
|
1785
2446
|
module.exports = {
|
|
1786
2447
|
runAnalyze,
|
|
1787
2448
|
runDoctor,
|
|
2449
|
+
runFlow,
|
|
1788
2450
|
runMigrate,
|
|
2451
|
+
runPrepare,
|
|
1789
2452
|
run,
|
|
1790
2453
|
};
|