create-quiver 0.15.4 → 0.17.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/.github/pull_request_template.md +17 -0
- package/.github/workflows/ci.yml +76 -0
- package/.markdown-link-check.json +15 -0
- package/.markdownlint.json +11 -0
- package/ARCHITECTURE.md +133 -0
- package/CHANGELOG.md +16 -0
- package/CONTRIBUTING.md +174 -9
- package/README.md +17 -2
- package/README_FOR_AI.md +4 -1
- package/ROADMAP.md +4 -0
- package/SECURITY.md +9 -2
- package/docs/AI_CONTEXT.md.es.template +3 -1
- package/docs/AI_CONTEXT.md.template +3 -1
- package/docs/CLI_UX_GUIDE.md +20 -1
- package/docs/COMMANDS.md.template +20 -6
- package/docs/GITFLOW_PR_GUIDE.md +73 -11
- package/docs/GITFLOW_PR_GUIDE.md.es.template +61 -2
- package/docs/GITFLOW_PR_GUIDE.md.template +72 -10
- package/docs/INDEX.md +6 -1
- package/docs/QUICK.md.template +2 -1
- package/docs/STANDARD.md.template +2 -1
- package/docs/WORKFLOW.md.es.template +3 -1
- package/docs/WORKFLOW.md.template +6 -4
- package/docs/getting-started/installation.md +7 -0
- package/docs/reference/commands.md +138 -6
- package/docs/reference/slice-schema.md +37 -0
- package/docs/schema/slice.schema.json +221 -0
- package/docs/specs/01-spec/01-slice/01-slice.json +36 -0
- package/docs/specs/01-spec/01-slice/01-slice.md +106 -0
- package/docs/specs/01-spec/01-slice/CLOSURE_BRIEF.md +80 -0
- package/docs/specs/01-spec/01-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/02-slice/02-slice.json +36 -0
- package/docs/specs/01-spec/02-slice/02-slice.md +108 -0
- package/docs/specs/01-spec/02-slice/CLOSURE_BRIEF.md +88 -0
- package/docs/specs/01-spec/02-slice/EXECUTION_BRIEF.md +40 -0
- package/docs/specs/01-spec/03-slice/03-slice.json +36 -0
- package/docs/specs/01-spec/03-slice/03-slice.md +103 -0
- package/docs/specs/01-spec/03-slice/CLOSURE_BRIEF.md +54 -0
- package/docs/specs/01-spec/03-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/04-slice/04-slice.json +36 -0
- package/docs/specs/01-spec/04-slice/04-slice.md +107 -0
- package/docs/specs/01-spec/04-slice/CLOSURE_BRIEF.md +46 -0
- package/docs/specs/01-spec/04-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/05-slice/05-slice.json +36 -0
- package/docs/specs/01-spec/05-slice/05-slice.md +106 -0
- package/docs/specs/01-spec/05-slice/CLOSURE_BRIEF.md +84 -0
- package/docs/specs/01-spec/05-slice/EXECUTION_BRIEF.md +109 -0
- package/docs/specs/01-spec/06-slice/06-slice.json +36 -0
- package/docs/specs/01-spec/06-slice/06-slice.md +107 -0
- package/docs/specs/01-spec/06-slice/CLOSURE_BRIEF.md +67 -0
- package/docs/specs/01-spec/06-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/07-slice/07-slice.json +36 -0
- package/docs/specs/01-spec/07-slice/07-slice.md +105 -0
- package/docs/specs/01-spec/07-slice/CLOSURE_BRIEF.md +71 -0
- package/docs/specs/01-spec/07-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/08-slice/08-slice.json +36 -0
- package/docs/specs/01-spec/08-slice/08-slice.md +105 -0
- package/docs/specs/01-spec/08-slice/CLOSURE_BRIEF.md +114 -0
- package/docs/specs/01-spec/08-slice/EXECUTION_BRIEF.md +39 -0
- package/docs/specs/01-spec/CLOSURE_BRIEF.md +87 -0
- package/docs/specs/01-spec/spec.md +197 -0
- package/docs/workflows/full-ai-spec-to-pr.md +46 -3
- package/i18n/es/docs/GITFLOW_PR_GUIDE.md.template +38 -1
- package/package.json +27 -1
- package/scripts/package-quiver.sh +82 -2
- package/scripts/release-quiver.sh +14 -3
- package/specs/[project-name]/slices/pr.md.template +19 -0
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/command-language-mode-matrix.json +122 -1
- package/specs/quiver-v46-deep-project-analysis/EVIDENCE_REPORT.md +94 -0
- package/specs/quiver-v46-deep-project-analysis/EXECUTION_PLAN.md +26 -0
- package/specs/quiver-v46-deep-project-analysis/SPEC.md +157 -0
- package/specs/quiver-v46-deep-project-analysis/STATUS.md +26 -0
- package/specs/quiver-v46-deep-project-analysis/pr.md +131 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-00-analysis-contract-foundation/CLOSURE_BRIEF.md +14 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-00-analysis-contract-foundation/EXECUTION_BRIEF.md +41 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-00-analysis-contract-foundation/slice.json +61 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-01-stack-agnostic-discovery-sampling/CLOSURE_BRIEF.md +22 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-01-stack-agnostic-discovery-sampling/EXECUTION_BRIEF.md +33 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-01-stack-agnostic-discovery-sampling/slice.json +80 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-02-provider-analysis-json-contract/CLOSURE_BRIEF.md +21 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-02-provider-analysis-json-contract/EXECUTION_BRIEF.md +34 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-02-provider-analysis-json-contract/slice.json +79 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-03-doc-proposal-review-safe-writes/CLOSURE_BRIEF.md +19 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-03-doc-proposal-review-safe-writes/EXECUTION_BRIEF.md +33 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-03-doc-proposal-review-safe-writes/slice.json +79 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-04-validation-docs-release-readiness/CLOSURE_BRIEF.md +20 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-04-validation-docs-release-readiness/EXECUTION_BRIEF.md +32 -0
- package/specs/quiver-v46-deep-project-analysis/slices/slice-04-validation-docs-release-readiness/slice.json +85 -0
- package/specs/quiver-v50-audit-trust-foundation/EVIDENCE_REPORT.md +151 -0
- package/specs/quiver-v50-audit-trust-foundation/EXECUTION_PLAN.md +34 -0
- package/specs/quiver-v50-audit-trust-foundation/SPEC.md +113 -0
- package/specs/quiver-v50-audit-trust-foundation/STATUS.md +26 -0
- package/specs/quiver-v50-audit-trust-foundation/pr.md +120 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/CLOSURE_BRIEF.md +20 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-00-audit-baseline-and-resolved-findings/slice.json +57 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/CLOSURE_BRIEF.md +24 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/EXECUTION_BRIEF.md +67 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-01-runtime-minimum-and-package-metadata/slice.json +71 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/CLOSURE_BRIEF.md +24 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/EXECUTION_BRIEF.md +71 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-02-migrate-write-safety-contract/slice.json +81 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/CLOSURE_BRIEF.md +22 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/EXECUTION_BRIEF.md +57 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-03-security-reporting-channel/slice.json +56 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/CLOSURE_BRIEF.md +23 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/EXECUTION_BRIEF.md +68 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-04-user-facing-i18n-error-coverage/slice.json +84 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/CLOSURE_BRIEF.md +25 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/EXECUTION_BRIEF.md +73 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-05-init-analyze-progress-and-summaries/slice.json +72 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/CLOSURE_BRIEF.md +22 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/EXECUTION_BRIEF.md +66 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-06-contributor-and-architecture-docs/slice.json +74 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/CLOSURE_BRIEF.md +29 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/EXECUTION_BRIEF.md +74 -0
- package/specs/quiver-v50-audit-trust-foundation/slices/slice-07-ci-and-documentation-lint-baseline/slice.json +81 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/EVIDENCE_REPORT.md +145 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/EXECUTION_PLAN.md +32 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/SPEC.md +109 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/STATUS.md +25 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/pr.md +69 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/CLOSURE_BRIEF.md +20 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/EXECUTION_BRIEF.md +58 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-00-cli-contract-baseline/slice.json +56 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/CLOSURE_BRIEF.md +21 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/EXECUTION_BRIEF.md +61 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-01-flow-json-compatibility/slice.json +68 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/CLOSURE_BRIEF.md +25 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/EXECUTION_BRIEF.md +65 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/pr.md +134 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-02-dashboard-section-validation-i18n/slice.json +80 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/CLOSURE_BRIEF.md +31 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/EXECUTION_BRIEF.md +80 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/pr.md +159 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-03-base-branch-resolution-policy/slice.json +102 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/CLOSURE_BRIEF.md +25 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/EXECUTION_BRIEF.md +74 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/pr.md +147 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-04-next-plan-graph-ux-edge-cases/slice.json +91 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/CLOSURE_BRIEF.md +28 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/EXECUTION_BRIEF.md +73 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/pr.md +146 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-05-evidence-robustness-path-safety/slice.json +100 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/CLOSURE_BRIEF.md +36 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/EXECUTION_BRIEF.md +76 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/pr.md +155 -0
- package/specs/quiver-v51-cli-ergonomics-automation-contracts/slices/slice-06-namespace-compatibility-windows-scripts/slice.json +111 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/EVIDENCE_REPORT.md +95 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/EXECUTION_PLAN.md +31 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/SPEC.md +107 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/STATUS.md +22 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/pr.md +69 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/CLOSURE_BRIEF.md +21 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/EXECUTION_BRIEF.md +60 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-00-schema-docs-release-baseline/slice.json +62 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/EXECUTION_BRIEF.md +71 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/pr.md +146 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-01-json-schema-for-slice-json/slice.json +106 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/EXECUTION_BRIEF.md +67 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/pr.md +144 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-02-generated-cli-reference/slice.json +86 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/CLOSURE_BRIEF.md +38 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/EXECUTION_BRIEF.md +75 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/pr.md +159 -0
- package/specs/quiver-v52-schema-docs-release-hygiene/slices/slice-03-changelog-package-release-smoke-hygiene/slice.json +105 -0
- package/src/create-quiver/commands/ai.js +521 -0
- package/src/create-quiver/commands/changelog.js +93 -0
- package/src/create-quiver/commands/config.js +16 -5
- package/src/create-quiver/commands/evidence.js +33 -2
- package/src/create-quiver/commands/flow.js +1 -0
- package/src/create-quiver/commands/graph.js +8 -2
- package/src/create-quiver/commands/plan.js +6 -0
- package/src/create-quiver/commands/spec.js +28 -13
- package/src/create-quiver/index.js +408 -98
- package/src/create-quiver/lib/ai/analyze-project-discovery.js +387 -0
- package/src/create-quiver/lib/ai/analyze-project-docs.js +364 -0
- package/src/create-quiver/lib/ai/analyze-project-parser.js +277 -0
- package/src/create-quiver/lib/ai/analyze-project-prompts.js +214 -0
- package/src/create-quiver/lib/ai/analyze-project-review.js +99 -0
- package/src/create-quiver/lib/ai/analyze-project-sampling.js +402 -0
- package/src/create-quiver/lib/ai/analyze-project-schema.js +92 -0
- package/src/create-quiver/lib/ai/analyze-project-validation.js +309 -0
- package/src/create-quiver/lib/ai/artifacts.js +4 -1
- package/src/create-quiver/lib/ai/github.js +5 -2
- package/src/create-quiver/lib/ai/spec-templates.js +19 -0
- package/src/create-quiver/lib/cli/command-registry.js +72 -0
- package/src/create-quiver/lib/cli/parser.js +14 -0
- package/src/create-quiver/lib/evidence.js +161 -6
- package/src/create-quiver/lib/git.js +99 -0
- package/src/create-quiver/lib/i18n/messages/en.js +52 -7
- package/src/create-quiver/lib/i18n/messages/es.js +54 -9
- package/src/create-quiver/lib/init-docs.js +1 -1
- package/src/create-quiver/lib/init-layout.js +9 -8
- package/src/create-quiver/lib/lifecycle.js +24 -26
- package/src/create-quiver/lib/readiness.js +67 -56
- package/src/create-quiver/lib/spec-worktrees.js +16 -34
|
@@ -6,12 +6,34 @@ const { redactSecrets } = require('../lib/evidence');
|
|
|
6
6
|
const { formatActionableError } = require('../lib/actionable-error');
|
|
7
7
|
const {
|
|
8
8
|
assertProviderPromptWithinLimit,
|
|
9
|
+
byteLength,
|
|
9
10
|
compactRevisionInput,
|
|
10
11
|
extractCleanProviderOutput,
|
|
12
|
+
redactSensitiveLocalValues,
|
|
11
13
|
writeRawProviderArtifact,
|
|
12
14
|
} = require('../lib/ai/artifacts');
|
|
13
15
|
const { buildContextPackMetadata, normalizeRole } = require('../lib/ai/context-packs');
|
|
14
16
|
const { parseContextProposalOutput } = require('../lib/ai/context-proposal');
|
|
17
|
+
const { discoverProjectFiles } = require('../lib/ai/analyze-project-discovery');
|
|
18
|
+
const {
|
|
19
|
+
buildAnalyzeProjectDocProposal,
|
|
20
|
+
buildAnalyzeProjectWritePlan,
|
|
21
|
+
createAnalyzeProjectSnapshot,
|
|
22
|
+
formatAnalyzeProjectDiffPreview,
|
|
23
|
+
writeAnalyzeProjectDocs,
|
|
24
|
+
} = require('../lib/ai/analyze-project-docs');
|
|
25
|
+
const { parseAnalyzeProjectOutput } = require('../lib/ai/analyze-project-parser');
|
|
26
|
+
const { buildAnalyzeProjectPrompt } = require('../lib/ai/analyze-project-prompts');
|
|
27
|
+
const {
|
|
28
|
+
confirmAnalyzeProjectWrites,
|
|
29
|
+
reviewAnalyzeProjectDocProposal,
|
|
30
|
+
} = require('../lib/ai/analyze-project-review');
|
|
31
|
+
const {
|
|
32
|
+
DEFAULT_MAX_BYTES: DEFAULT_ANALYZE_MAX_BYTES,
|
|
33
|
+
DEFAULT_MAX_FILES: DEFAULT_ANALYZE_MAX_FILES,
|
|
34
|
+
sampleProjectFiles,
|
|
35
|
+
} = require('../lib/ai/analyze-project-sampling');
|
|
36
|
+
const { validateAnalyzeProjectPostWrite } = require('../lib/ai/analyze-project-validation');
|
|
15
37
|
const { openEditor } = require('../lib/cli/editor');
|
|
16
38
|
const { selectOption, promptText } = require('../lib/cli/selectors');
|
|
17
39
|
const { createUx } = require('../lib/cli/ux');
|
|
@@ -103,11 +125,316 @@ const DEFAULT_PLAN_CONTEXT = 'planning';
|
|
|
103
125
|
const DEFAULT_PLAN_PHASE = 'acceptance';
|
|
104
126
|
const CONTEXT_PREP_START = '<!-- quiver:context-prep:start -->';
|
|
105
127
|
const CONTEXT_PREP_END = '<!-- quiver:context-prep:end -->';
|
|
128
|
+
const ANALYZE_PROJECT_KIND = 'quiver-project-analysis-plan';
|
|
106
129
|
|
|
107
130
|
function formatError(message) {
|
|
108
131
|
return `create-quiver: ${message}`;
|
|
109
132
|
}
|
|
110
133
|
|
|
134
|
+
function normalizeAnalyzeBudget(value, fallback, flagName) {
|
|
135
|
+
if (typeof value === 'undefined' || value === null || value === '') {
|
|
136
|
+
return fallback;
|
|
137
|
+
}
|
|
138
|
+
const parsed = Number.parseInt(value, 10);
|
|
139
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
140
|
+
throw new Error(formatError(`invalid value for ${flagName}`));
|
|
141
|
+
}
|
|
142
|
+
return parsed;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function mergeReasonSummaries(...summaries) {
|
|
146
|
+
const merged = {};
|
|
147
|
+
for (const summary of summaries) {
|
|
148
|
+
for (const [reason, count] of Object.entries(summary || {})) {
|
|
149
|
+
merged[reason] = (merged[reason] || 0) + count;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return Object.keys(merged)
|
|
153
|
+
.sort()
|
|
154
|
+
.reduce((acc, reason) => {
|
|
155
|
+
acc[reason] = merged[reason];
|
|
156
|
+
return acc;
|
|
157
|
+
}, {});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function limitList(items, maxItems = 30) {
|
|
161
|
+
const list = Array.isArray(items) ? items : [];
|
|
162
|
+
return {
|
|
163
|
+
items: list.slice(0, maxItems),
|
|
164
|
+
hidden: Math.max(0, list.length - maxItems),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function formatAnalyzeProjectFileLine(file) {
|
|
169
|
+
const details = [];
|
|
170
|
+
if (Array.isArray(file.signals) && file.signals.length > 0) {
|
|
171
|
+
details.push(file.signals.join(', '));
|
|
172
|
+
}
|
|
173
|
+
if (typeof file.bytes === 'number') {
|
|
174
|
+
details.push(`${file.bytes} bytes`);
|
|
175
|
+
}
|
|
176
|
+
if (file.reason) {
|
|
177
|
+
details.push(file.reason);
|
|
178
|
+
}
|
|
179
|
+
return `- ${file.path}${details.length > 0 ? ` (${details.join('; ')})` : ''}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function formatAnalyzeProjectReport(report) {
|
|
183
|
+
const selected = limitList(report.selected_files, 80);
|
|
184
|
+
const omitted = limitList(report.omitted_files, 30);
|
|
185
|
+
const safety = limitList(report.safety_exclusions, 30);
|
|
186
|
+
const workspaces = limitList(report.roots.workspaces, 20);
|
|
187
|
+
const lines = [
|
|
188
|
+
'AI analyze-project read-only analysis',
|
|
189
|
+
`Mode: ${report.mode}`,
|
|
190
|
+
`Dry-run: ${report.dry_run ? 'yes' : 'no'} (dry-run never writes)`,
|
|
191
|
+
`Provider execution: ${report.provider_execution}`,
|
|
192
|
+
`Writes: ${report.writes.length === 0 ? 'none' : report.writes.join(', ')}`,
|
|
193
|
+
`Project: ${report.project.name}`,
|
|
194
|
+
`Scope: ${report.options.scope}`,
|
|
195
|
+
`Budgets: ${report.budgets.selected_files}/${report.budgets.max_files} files, ${report.budgets.selected_bytes}/${report.budgets.max_bytes} bytes`,
|
|
196
|
+
`Selected files: ${report.selected_files.length}`,
|
|
197
|
+
`Omitted files: ${report.omitted_files.length}`,
|
|
198
|
+
`Safety exclusions: ${report.safety_exclusions.length}`,
|
|
199
|
+
'',
|
|
200
|
+
'Workspace roots:',
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
for (const workspace of workspaces.items) {
|
|
204
|
+
lines.push(`- ${workspace.path} (${workspace.name}; ${workspace.source})`);
|
|
205
|
+
}
|
|
206
|
+
if (workspaces.hidden > 0) {
|
|
207
|
+
lines.push(`- ... ${workspaces.hidden} more`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
lines.push('', `Detected stack: ${report.detected.stack.length > 0 ? report.detected.stack.join(', ') : 'unknown'}`);
|
|
211
|
+
lines.push(`Source roots: ${report.detected.source_roots.length > 0 ? report.detected.source_roots.join(', ') : 'none'}`);
|
|
212
|
+
lines.push(`Entrypoints: ${report.detected.entrypoints.length > 0 ? report.detected.entrypoints.join(', ') : 'none'}`);
|
|
213
|
+
lines.push(`Configs: ${report.detected.configs.length > 0 ? report.detected.configs.join(', ') : 'none'}`);
|
|
214
|
+
|
|
215
|
+
lines.push('', 'Selected files:');
|
|
216
|
+
for (const file of selected.items) {
|
|
217
|
+
lines.push(formatAnalyzeProjectFileLine(file));
|
|
218
|
+
}
|
|
219
|
+
if (selected.hidden > 0) {
|
|
220
|
+
lines.push(`- ... ${selected.hidden} more`);
|
|
221
|
+
}
|
|
222
|
+
if (selected.items.length === 0) {
|
|
223
|
+
lines.push('- none');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
lines.push('', 'Omitted files:');
|
|
227
|
+
for (const file of omitted.items) {
|
|
228
|
+
lines.push(formatAnalyzeProjectFileLine(file));
|
|
229
|
+
}
|
|
230
|
+
if (omitted.hidden > 0) {
|
|
231
|
+
lines.push(`- ... ${omitted.hidden} more`);
|
|
232
|
+
}
|
|
233
|
+
if (omitted.items.length === 0) {
|
|
234
|
+
lines.push('- none');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
lines.push('', 'Safety exclusions:');
|
|
238
|
+
for (const file of safety.items) {
|
|
239
|
+
lines.push(`- ${file.path} (${file.reason})`);
|
|
240
|
+
}
|
|
241
|
+
if (safety.hidden > 0) {
|
|
242
|
+
lines.push(`- ... ${safety.hidden} more`);
|
|
243
|
+
}
|
|
244
|
+
if (safety.items.length === 0) {
|
|
245
|
+
lines.push('- none');
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
lines.push('', 'Next commands:');
|
|
249
|
+
for (const command of report.next_commands) {
|
|
250
|
+
lines.push(`- ${command}`);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return `${lines.join('\n')}\n`;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function buildAnalyzeProjectReport(repoRoot, options = {}) {
|
|
257
|
+
const deep = options.deep === true;
|
|
258
|
+
const includeSource = options.includeSource === true || deep;
|
|
259
|
+
const includeDb = options.includeDb === true || deep;
|
|
260
|
+
const includeTests = options.includeTests === true;
|
|
261
|
+
const maxFiles = normalizeAnalyzeBudget(options.maxFiles, DEFAULT_ANALYZE_MAX_FILES, '--max-files');
|
|
262
|
+
const maxBytes = normalizeAnalyzeBudget(options.maxBytes, DEFAULT_ANALYZE_MAX_BYTES, '--max-bytes');
|
|
263
|
+
const discovery = discoverProjectFiles(repoRoot, { scope: options.scope || '' });
|
|
264
|
+
const sample = sampleProjectFiles(discovery.files, {
|
|
265
|
+
includeDb,
|
|
266
|
+
includeSource,
|
|
267
|
+
includeTests,
|
|
268
|
+
maxBytes,
|
|
269
|
+
maxFiles,
|
|
270
|
+
});
|
|
271
|
+
const omittedFiles = [
|
|
272
|
+
...sample.omittedFiles,
|
|
273
|
+
...discovery.skippedFiles.map((file) => ({
|
|
274
|
+
path: file.path,
|
|
275
|
+
reason: file.reason,
|
|
276
|
+
})),
|
|
277
|
+
].sort((a, b) => a.path.localeCompare(b.path));
|
|
278
|
+
const omittedSummary = mergeReasonSummaries(
|
|
279
|
+
sample.omittedSummary,
|
|
280
|
+
discovery.skippedSummary,
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
schema_version: 1,
|
|
285
|
+
kind: ANALYZE_PROJECT_KIND,
|
|
286
|
+
command: 'ai analyze-project',
|
|
287
|
+
mode: 'read-only',
|
|
288
|
+
dry_run: options.dryRun === true,
|
|
289
|
+
read_only: true,
|
|
290
|
+
provider_execution: 'skipped',
|
|
291
|
+
writes: [],
|
|
292
|
+
project: discovery.project,
|
|
293
|
+
options: {
|
|
294
|
+
deep,
|
|
295
|
+
scope: discovery.roots.analysis_root,
|
|
296
|
+
max_files: maxFiles,
|
|
297
|
+
max_bytes: maxBytes,
|
|
298
|
+
include_source: includeSource,
|
|
299
|
+
include_tests: includeTests,
|
|
300
|
+
include_db: includeDb,
|
|
301
|
+
},
|
|
302
|
+
roots: discovery.roots,
|
|
303
|
+
detected: discovery.detected,
|
|
304
|
+
budgets: sample.budgets,
|
|
305
|
+
selected_files: sample.selectedFiles,
|
|
306
|
+
omitted_files: omittedFiles,
|
|
307
|
+
omitted_summary: omittedSummary,
|
|
308
|
+
safety_exclusions: discovery.safetyExclusions,
|
|
309
|
+
safety_summary: discovery.safetySummary,
|
|
310
|
+
next_commands: [
|
|
311
|
+
'npx create-quiver ai analyze-project --deep --dry-run --json',
|
|
312
|
+
'npx create-quiver ai analyze-project --deep --review',
|
|
313
|
+
],
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function limitProviderArtifactText(text, maxBytes = 12_000) {
|
|
318
|
+
let value = String(text || '');
|
|
319
|
+
const redacted = value;
|
|
320
|
+
if (byteLength(redacted) <= maxBytes) {
|
|
321
|
+
return {
|
|
322
|
+
text: redacted,
|
|
323
|
+
truncated: false,
|
|
324
|
+
bytes: byteLength(redacted),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
value = redacted;
|
|
329
|
+
while (byteLength(value) > maxBytes && value.length > 0) {
|
|
330
|
+
value = value.slice(0, Math.max(0, value.length - Math.ceil((byteLength(value) - maxBytes) / 2) - 16));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
text: `${value.trimEnd()}\n[TRUNCATED BY QUIVER]\n`,
|
|
335
|
+
truncated: true,
|
|
336
|
+
bytes: byteLength(redacted),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function buildAnalyzeProjectProviderArtifact(result, clean, repoRoot, options = {}) {
|
|
341
|
+
const rawOutput = clean?.cleanOutput || result?.stdout || result?.stderr || '';
|
|
342
|
+
const redactedOutput = redactSensitiveLocalValues(rawOutput, { projectRoot: repoRoot });
|
|
343
|
+
const limited = limitProviderArtifactText(redactedOutput, options.maxBytes || 12_000);
|
|
344
|
+
return {
|
|
345
|
+
schema_version: 1,
|
|
346
|
+
kind: 'quiver-analyze-project-provider-artifact',
|
|
347
|
+
persisted: false,
|
|
348
|
+
redacted: true,
|
|
349
|
+
size_limited: true,
|
|
350
|
+
provider: result?.provider || null,
|
|
351
|
+
command: result?.command || null,
|
|
352
|
+
exit_code: typeof result?.exitCode === 'number' ? result.exitCode : null,
|
|
353
|
+
output_source: clean?.source || 'unknown',
|
|
354
|
+
output_bytes: limited.bytes,
|
|
355
|
+
output_truncated: limited.truncated,
|
|
356
|
+
output: limited.text,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function formatAnalyzeProjectLiveReport(report) {
|
|
361
|
+
const warningCount = report.analysis_validation?.warnings?.length || 0;
|
|
362
|
+
const docUpdatePaths = report.analysis_validation?.doc_update_paths || [];
|
|
363
|
+
const lines = [
|
|
364
|
+
'AI analyze-project provider analysis',
|
|
365
|
+
`Mode: ${report.mode}`,
|
|
366
|
+
`Provider: ${report.provider}`,
|
|
367
|
+
`Provider execution: ${report.provider_execution}`,
|
|
368
|
+
`Writes: ${report.writes.length === 0 ? 'none' : report.writes.join(', ')}`,
|
|
369
|
+
`Privacy preflight: ${report.privacy_preflight.ok ? 'passed' : 'failed'}`,
|
|
370
|
+
`Prompt bytes: ${report.prompt.bytes}/${report.prompt.max_provider_prompt_bytes}`,
|
|
371
|
+
`Selected files: ${report.selected_files.length}`,
|
|
372
|
+
`Omitted files: ${report.omitted_files.length}`,
|
|
373
|
+
`Safety exclusions: ${report.safety_exclusions.length}`,
|
|
374
|
+
`Analysis validation: passed (${warningCount} warning${warningCount === 1 ? '' : 's'})`,
|
|
375
|
+
`Doc update proposals: ${docUpdatePaths.length > 0 ? docUpdatePaths.join(', ') : 'none'}`,
|
|
376
|
+
];
|
|
377
|
+
|
|
378
|
+
if (warningCount > 0) {
|
|
379
|
+
lines.push('', 'Warnings:');
|
|
380
|
+
for (const warning of report.analysis_validation.warnings.slice(0, 20)) {
|
|
381
|
+
lines.push(`- ${warning.path}: ${warning.issue}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
lines.push('', 'Next commands:');
|
|
386
|
+
lines.push('- npx create-quiver ai analyze-project --deep --review');
|
|
387
|
+
lines.push('- npx create-quiver ai analyze-project --deep --json');
|
|
388
|
+
|
|
389
|
+
return `${lines.join('\n')}\n`;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function formatAnalyzeProjectPostWriteValidation(validation) {
|
|
393
|
+
if (!validation) {
|
|
394
|
+
return [];
|
|
395
|
+
}
|
|
396
|
+
const warningCount = validation.warnings?.length || 0;
|
|
397
|
+
const errorCount = validation.errors?.length || 0;
|
|
398
|
+
const lines = [
|
|
399
|
+
`Post-write validation: ${validation.ok ? 'passed' : 'failed'} (${errorCount} error${errorCount === 1 ? '' : 's'}, ${warningCount} warning${warningCount === 1 ? '' : 's'})`,
|
|
400
|
+
];
|
|
401
|
+
for (const issue of [...(validation.errors || []), ...(validation.warnings || [])].slice(0, 20)) {
|
|
402
|
+
lines.push(`- ${issue.path || 'analysis'}: ${issue.issue} - ${issue.message}`);
|
|
403
|
+
}
|
|
404
|
+
return lines;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function formatAnalyzeProjectReviewPlan({ writePlan, reviewPath, snapshot, writtenDocs, completed = false, validation = null } = {}) {
|
|
408
|
+
const changed = (writePlan || []).filter((item) => item.action !== 'skip');
|
|
409
|
+
const dirty = changed.filter((item) => item.dirty);
|
|
410
|
+
const lines = [
|
|
411
|
+
completed ? 'AI analyze-project docs written' : 'AI analyze-project review write plan',
|
|
412
|
+
`Review artifact: ${reviewPath || 'none'}`,
|
|
413
|
+
`Writes: ${changed.length > 0 ? changed.map((item) => item.path).join(', ') : 'none'}`,
|
|
414
|
+
`Dirty target docs: ${dirty.length > 0 ? dirty.map((item) => item.path).join(', ') : 'none'}`,
|
|
415
|
+
];
|
|
416
|
+
|
|
417
|
+
if (snapshot) {
|
|
418
|
+
lines.push(`Snapshot: ${snapshot.root}`);
|
|
419
|
+
lines.push(`Manifest: ${snapshot.manifestPath}`);
|
|
420
|
+
}
|
|
421
|
+
if (completed) {
|
|
422
|
+
lines.push(`Written docs: ${writtenDocs && writtenDocs.length > 0 ? writtenDocs.join(', ') : 'none'}`);
|
|
423
|
+
lines.push(...formatAnalyzeProjectPostWriteValidation(validation));
|
|
424
|
+
return `${lines.join('\n')}\n`;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
lines.push('', 'Proposed changes:');
|
|
428
|
+
for (const item of writePlan || []) {
|
|
429
|
+
lines.push(`- ${item.path}: ${item.action}${item.reason ? ` (${item.reason})` : ''}`);
|
|
430
|
+
}
|
|
431
|
+
lines.push('', 'Final diff:');
|
|
432
|
+
lines.push(...formatAnalyzeProjectDiffPreview(writePlan || []));
|
|
433
|
+
lines.push('', 'Confirmation required before writing.');
|
|
434
|
+
|
|
435
|
+
return `${lines.join('\n')}\n`;
|
|
436
|
+
}
|
|
437
|
+
|
|
111
438
|
function formatLocalizedActionableError({ failure, impact, fix, nextCommand } = {}, options = {}) {
|
|
112
439
|
const translator = createTranslator(options.language);
|
|
113
440
|
const lines = [`create-quiver: ${String(failure || 'operation failed').trim()}`];
|
|
@@ -1541,6 +1868,199 @@ async function runPrepareContext(repoRoot, options = {}) {
|
|
|
1541
1868
|
};
|
|
1542
1869
|
}
|
|
1543
1870
|
|
|
1871
|
+
async function runAnalyzeProject(repoRoot, options = {}) {
|
|
1872
|
+
const report = buildAnalyzeProjectReport(repoRoot, options);
|
|
1873
|
+
if (options.dryRun === true) {
|
|
1874
|
+
if (options.json === true) {
|
|
1875
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
1876
|
+
return report;
|
|
1877
|
+
}
|
|
1878
|
+
process.stdout.write(formatAnalyzeProjectReport(report));
|
|
1879
|
+
return report;
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
const role = normalizeRole(options.role || DEFAULT_PLAN_ROLE);
|
|
1883
|
+
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, role, options, DEFAULT_PLAN_PROVIDER);
|
|
1884
|
+
const provider = runtimeProfile.provider;
|
|
1885
|
+
const timeoutMs = normalizeTimeout(options.timeout);
|
|
1886
|
+
const promptPackage = buildAnalyzeProjectPrompt({
|
|
1887
|
+
analysisPlan: report,
|
|
1888
|
+
repoRoot,
|
|
1889
|
+
maxFileBytes: options.maxPromptFileBytes,
|
|
1890
|
+
maxTotalFileBytes: options.maxPromptTotalBytes,
|
|
1891
|
+
});
|
|
1892
|
+
const prompt = promptPackage.prompt;
|
|
1893
|
+
const promptLimit = assertProviderPromptWithinLimit(prompt, options.promptLimitOptions || {});
|
|
1894
|
+
const privacyPreflight = promptPackage.privacyPreflight;
|
|
1895
|
+
|
|
1896
|
+
if (!privacyPreflight.ok) {
|
|
1897
|
+
const error = new Error(formatError('ai analyze-project privacy preflight failed; provider execution was blocked before sending repository content.'));
|
|
1898
|
+
error.code = 'AI_ANALYZE_PROJECT_PRIVACY_PREFLIGHT_FAILED';
|
|
1899
|
+
error.details = privacyPreflight;
|
|
1900
|
+
throw error;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
let invocation;
|
|
1904
|
+
try {
|
|
1905
|
+
invocation = buildProviderInvocation(provider, {
|
|
1906
|
+
prompt,
|
|
1907
|
+
cwd: repoRoot,
|
|
1908
|
+
timeoutMs,
|
|
1909
|
+
...runtimeModelExecutionOptions(runtimeProfile, options),
|
|
1910
|
+
enforceModelSelection: false,
|
|
1911
|
+
});
|
|
1912
|
+
} catch (error) {
|
|
1913
|
+
throw annotateProviderError(error, 'analyze-project');
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
if (options.printPrompt) {
|
|
1917
|
+
process.stdout.write(prompt.endsWith('\n') ? prompt : `${prompt}\n`);
|
|
1918
|
+
return {
|
|
1919
|
+
...report,
|
|
1920
|
+
provider,
|
|
1921
|
+
role,
|
|
1922
|
+
invocation,
|
|
1923
|
+
privacy_preflight: privacyPreflight,
|
|
1924
|
+
prompt: {
|
|
1925
|
+
bytes: promptLimit.bytes,
|
|
1926
|
+
max_provider_prompt_bytes: promptLimit.maxProviderPromptBytes,
|
|
1927
|
+
files: promptPackage.files,
|
|
1928
|
+
},
|
|
1929
|
+
};
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
let result;
|
|
1933
|
+
try {
|
|
1934
|
+
result = await (options.runProviderFn || runProvider)(provider, {
|
|
1935
|
+
prompt,
|
|
1936
|
+
cwd: repoRoot,
|
|
1937
|
+
timeoutMs,
|
|
1938
|
+
dryRun: false,
|
|
1939
|
+
probe: options.probe,
|
|
1940
|
+
spawn: options.spawn,
|
|
1941
|
+
tempRoot: options.tempRoot,
|
|
1942
|
+
tempFileName: options.tempFileName,
|
|
1943
|
+
tempFilePrefix: options.tempFilePrefix,
|
|
1944
|
+
...runtimeModelExecutionOptions(runtimeProfile, options),
|
|
1945
|
+
enforceModelSelection: false,
|
|
1946
|
+
});
|
|
1947
|
+
} catch (error) {
|
|
1948
|
+
throw annotateProviderError(error, 'analyze-project');
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
if (!result.ok) {
|
|
1952
|
+
throw annotateProviderError(result.error || new Error('provider run failed'), 'analyze-project');
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
const clean = extractCleanProviderOutput(result, { prompt, projectRoot: repoRoot });
|
|
1956
|
+
const parsed = parseAnalyzeProjectOutput(clean.cleanOutput, {
|
|
1957
|
+
selectedFiles: report.selected_files,
|
|
1958
|
+
promptFiles: promptPackage.files,
|
|
1959
|
+
});
|
|
1960
|
+
const completedReport = {
|
|
1961
|
+
...report,
|
|
1962
|
+
provider,
|
|
1963
|
+
role,
|
|
1964
|
+
provider_execution: 'completed',
|
|
1965
|
+
invocation,
|
|
1966
|
+
privacy_preflight: privacyPreflight,
|
|
1967
|
+
prompt: {
|
|
1968
|
+
bytes: promptLimit.bytes,
|
|
1969
|
+
max_provider_prompt_bytes: promptLimit.maxProviderPromptBytes,
|
|
1970
|
+
files: promptPackage.files,
|
|
1971
|
+
},
|
|
1972
|
+
analysis: parsed.analysis,
|
|
1973
|
+
analysis_validation: {
|
|
1974
|
+
parse_source: parsed.parseSource,
|
|
1975
|
+
warnings: parsed.warnings,
|
|
1976
|
+
doc_update_paths: parsed.docUpdatePaths,
|
|
1977
|
+
},
|
|
1978
|
+
provider_artifact: buildAnalyzeProjectProviderArtifact(result, clean, repoRoot),
|
|
1979
|
+
};
|
|
1980
|
+
|
|
1981
|
+
if (options.review === true) {
|
|
1982
|
+
const initialProposal = buildAnalyzeProjectDocProposal(parsed.analysis);
|
|
1983
|
+
const reviewed = await reviewAnalyzeProjectDocProposal(repoRoot, initialProposal, options);
|
|
1984
|
+
const writePlan = buildAnalyzeProjectWritePlan(repoRoot, reviewed.proposal);
|
|
1985
|
+
process.stdout.write(formatAnalyzeProjectReviewPlan({
|
|
1986
|
+
writePlan,
|
|
1987
|
+
reviewPath: reviewed.reviewPath,
|
|
1988
|
+
}));
|
|
1989
|
+
await confirmAnalyzeProjectWrites(writePlan, options);
|
|
1990
|
+
const lifecycleRun = ensureAiRun(repoRoot, {
|
|
1991
|
+
command: 'ai analyze-project',
|
|
1992
|
+
input: reviewed.reviewPath,
|
|
1993
|
+
runId: options.runId,
|
|
1994
|
+
phase: 'created',
|
|
1995
|
+
});
|
|
1996
|
+
const snapshot = createAnalyzeProjectSnapshot(repoRoot, lifecycleRun, writePlan, {
|
|
1997
|
+
providerArtifact: completedReport.provider_artifact,
|
|
1998
|
+
proposal: reviewed.proposal,
|
|
1999
|
+
now: options.now || new Date(),
|
|
2000
|
+
});
|
|
2001
|
+
const writtenDocs = writeAnalyzeProjectDocs(writePlan);
|
|
2002
|
+
let writeReport = {
|
|
2003
|
+
...completedReport,
|
|
2004
|
+
review: true,
|
|
2005
|
+
review_path: reviewed.reviewPath,
|
|
2006
|
+
doc_proposal: reviewed.proposal,
|
|
2007
|
+
write_plan: writePlan.map((item) => ({
|
|
2008
|
+
path: item.path,
|
|
2009
|
+
action: item.action,
|
|
2010
|
+
dirty: item.dirty,
|
|
2011
|
+
before_sha256: item.before_sha256,
|
|
2012
|
+
after_sha256: item.after_sha256,
|
|
2013
|
+
reason: item.reason,
|
|
2014
|
+
})),
|
|
2015
|
+
snapshot,
|
|
2016
|
+
written_docs: writtenDocs,
|
|
2017
|
+
run_id: lifecycleRun.run_id,
|
|
2018
|
+
};
|
|
2019
|
+
const postWriteValidation = validateAnalyzeProjectPostWrite(repoRoot, writeReport, {
|
|
2020
|
+
strict: options.strict === true,
|
|
2021
|
+
});
|
|
2022
|
+
writeReport = {
|
|
2023
|
+
...writeReport,
|
|
2024
|
+
post_write_validation: postWriteValidation,
|
|
2025
|
+
};
|
|
2026
|
+
|
|
2027
|
+
if (options.json === true) {
|
|
2028
|
+
process.stdout.write(`${JSON.stringify(writeReport, null, 2)}\n`);
|
|
2029
|
+
if (!postWriteValidation.ok) {
|
|
2030
|
+
const error = new Error(formatError('ai analyze-project post-write validation failed.'));
|
|
2031
|
+
error.code = 'AI_ANALYZE_PROJECT_POST_WRITE_VALIDATION_FAILED';
|
|
2032
|
+
error.validation = postWriteValidation;
|
|
2033
|
+
throw error;
|
|
2034
|
+
}
|
|
2035
|
+
return writeReport;
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
process.stdout.write(formatAnalyzeProjectReviewPlan({
|
|
2039
|
+
writePlan,
|
|
2040
|
+
reviewPath: reviewed.reviewPath,
|
|
2041
|
+
snapshot,
|
|
2042
|
+
writtenDocs,
|
|
2043
|
+
validation: postWriteValidation,
|
|
2044
|
+
completed: true,
|
|
2045
|
+
}));
|
|
2046
|
+
if (!postWriteValidation.ok) {
|
|
2047
|
+
const error = new Error(formatError('ai analyze-project post-write validation failed.'));
|
|
2048
|
+
error.code = 'AI_ANALYZE_PROJECT_POST_WRITE_VALIDATION_FAILED';
|
|
2049
|
+
error.validation = postWriteValidation;
|
|
2050
|
+
throw error;
|
|
2051
|
+
}
|
|
2052
|
+
return writeReport;
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
if (options.json === true) {
|
|
2056
|
+
process.stdout.write(`${JSON.stringify(completedReport, null, 2)}\n`);
|
|
2057
|
+
return completedReport;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
process.stdout.write(formatAnalyzeProjectLiveReport(completedReport));
|
|
2061
|
+
return completedReport;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
1544
2064
|
async function runPrepareContextWithPlanner(repoRoot, options = {}) {
|
|
1545
2065
|
const role = normalizeRole(options.role || DEFAULT_PLAN_ROLE);
|
|
1546
2066
|
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, role, options, DEFAULT_PLAN_PROVIDER);
|
|
@@ -3412,6 +3932,7 @@ module.exports = {
|
|
|
3412
3932
|
resolveInteractiveAgentSetOptions,
|
|
3413
3933
|
runAgent,
|
|
3414
3934
|
runActiveSlice,
|
|
3935
|
+
runAnalyzeProject,
|
|
3415
3936
|
runDoctor,
|
|
3416
3937
|
runExecutePlan,
|
|
3417
3938
|
runExecuteSlice,
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
function parseChangelog(content) {
|
|
5
|
+
const lines = String(content || '').split(/\r?\n/);
|
|
6
|
+
const entries = [];
|
|
7
|
+
let current = null;
|
|
8
|
+
|
|
9
|
+
for (const line of lines) {
|
|
10
|
+
const heading = line.match(/^##\s+\[?([^\]\n]+)\]?(?:\s+-\s+(.+))?$/);
|
|
11
|
+
if (heading) {
|
|
12
|
+
if (current) {
|
|
13
|
+
current.body = current.body.trim();
|
|
14
|
+
entries.push(current);
|
|
15
|
+
}
|
|
16
|
+
current = {
|
|
17
|
+
version: heading[1].trim(),
|
|
18
|
+
date: heading[2]?.trim() || null,
|
|
19
|
+
body: '',
|
|
20
|
+
};
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (current) {
|
|
25
|
+
current.body += `${line}\n`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (current) {
|
|
30
|
+
current.body = current.body.trim();
|
|
31
|
+
entries.push(current);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return entries;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function readChangelog(packageRoot) {
|
|
38
|
+
const changelogPath = path.join(packageRoot, 'CHANGELOG.md');
|
|
39
|
+
if (!fs.existsSync(changelogPath)) {
|
|
40
|
+
return { path: changelogPath, entries: [], missing: true };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const content = fs.readFileSync(changelogPath, 'utf8');
|
|
44
|
+
return { path: changelogPath, entries: parseChangelog(content), missing: false };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function formatHumanChangelog(report) {
|
|
48
|
+
if (report.missing) {
|
|
49
|
+
return 'Quiver changelog\n\nNo local CHANGELOG.md was found in the installed package.\n';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const entries = report.entries.slice(0, 3);
|
|
53
|
+
if (entries.length === 0) {
|
|
54
|
+
return 'Quiver changelog\n\nLocal CHANGELOG.md did not contain parseable release entries.\n';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const lines = ['Quiver changelog', ''];
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
lines.push(`## ${entry.version}${entry.date ? ` - ${entry.date}` : ''}`);
|
|
60
|
+
if (entry.body) {
|
|
61
|
+
lines.push(entry.body);
|
|
62
|
+
}
|
|
63
|
+
lines.push('');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return `${lines.join('\n').trimEnd()}\n`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function runChangelog(options = {}) {
|
|
70
|
+
const packageRoot = options.packageRoot || path.resolve(__dirname, '../..', '..');
|
|
71
|
+
const report = readChangelog(packageRoot);
|
|
72
|
+
const payload = {
|
|
73
|
+
schema_version: 1,
|
|
74
|
+
source: report.path,
|
|
75
|
+
missing: report.missing,
|
|
76
|
+
entries: report.entries.slice(0, 10),
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
if (options.json) {
|
|
80
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
81
|
+
return payload;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
process.stdout.write(formatHumanChangelog(report));
|
|
85
|
+
return payload;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
formatHumanChangelog,
|
|
90
|
+
parseChangelog,
|
|
91
|
+
readChangelog,
|
|
92
|
+
runChangelog,
|
|
93
|
+
};
|