create-quiver 0.17.1 → 0.17.2
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/ACTIVE_SLICES.md +43 -0
- package/CHANGELOG.md +4 -0
- package/auditoria-ux-ui-performance-documentacion.md +705 -0
- package/copys-landing-page.md +244 -0
- package/docs/TROUBLESHOOTING.md +53 -0
- package/docs/reference/commands.md +42 -0
- package/docs/workflows/existing-project-ai-quiver-setup.md +552 -0
- package/docs/workflows/existing-project.md +21 -0
- package/package.json +1 -1
- package/specs/quiver-v43-cli-i18n-audit-release-readiness/command-language-mode-matrix.json +1 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/EVIDENCE_REPORT.md +151 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/EXECUTION_PLAN.md +50 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/SPEC.md +207 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/STATUS.md +32 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/pr.md +73 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-00-analysis-run-contract/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-00-analysis-run-contract/EXECUTION_BRIEF.md +63 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-00-analysis-run-contract/slice.json +70 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-01-provider-fixture-harness/CLOSURE_BRIEF.md +38 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-01-provider-fixture-harness/EXECUTION_BRIEF.md +60 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-01-provider-fixture-harness/slice.json +74 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-02-safe-context-boundary/CLOSURE_BRIEF.md +33 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-02-safe-context-boundary/EXECUTION_BRIEF.md +68 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-02-safe-context-boundary/slice.json +85 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-03-schema-error-grouping/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-03-schema-error-grouping/EXECUTION_BRIEF.md +65 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-03-schema-error-grouping/slice.json +80 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-04-safe-repair-layer/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-04-safe-repair-layer/EXECUTION_BRIEF.md +63 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-04-safe-repair-layer/slice.json +80 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-05-controlled-retry-layer/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-05-controlled-retry-layer/EXECUTION_BRIEF.md +65 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-05-controlled-retry-layer/slice.json +81 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-06-audit-review-transaction/CLOSURE_BRIEF.md +35 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-06-audit-review-transaction/EXECUTION_BRIEF.md +71 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-06-audit-review-transaction/slice.json +88 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-07-semantic-validation-docs/CLOSURE_BRIEF.md +32 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-07-semantic-validation-docs/EXECUTION_BRIEF.md +66 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-07-semantic-validation-docs/slice.json +86 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-08-structural-map-hardening/CLOSURE_BRIEF.md +34 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-08-structural-map-hardening/EXECUTION_BRIEF.md +67 -0
- package/specs/quiver-v53-reliable-deep-project-analysis/slices/slice-08-structural-map-hardening/slice.json +81 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/EVIDENCE_REPORT.md +53 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/EXECUTION_PLAN.md +55 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/SPEC.md +184 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/STATUS.md +34 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-01-contract-regression-harness/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-01-contract-regression-harness/EXECUTION_BRIEF.md +54 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-01-contract-regression-harness/slice.json +72 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-02-safe-discovery-sampling/CLOSURE_BRIEF.md +11 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-02-safe-discovery-sampling/EXECUTION_BRIEF.md +53 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-02-safe-discovery-sampling/slice.json +69 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-03-run-lifecycle-cli-io/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-03-run-lifecycle-cli-io/EXECUTION_BRIEF.md +53 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-03-run-lifecycle-cli-io/slice.json +69 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-04-artifact-store-redaction/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-04-artifact-store-redaction/EXECUTION_BRIEF.md +54 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-04-artifact-store-redaction/slice.json +73 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-05-path-aware-repair-engine/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-05-path-aware-repair-engine/EXECUTION_BRIEF.md +57 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-05-path-aware-repair-engine/slice.json +72 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-06-retry-controller/CLOSURE_BRIEF.md +9 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-06-retry-controller/EXECUTION_BRIEF.md +52 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-06-retry-controller/slice.json +70 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-07-final-validation-review-write-gate/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-07-final-validation-review-write-gate/EXECUTION_BRIEF.md +57 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-07-final-validation-review-write-gate/slice.json +75 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-08-doctor-agents-guidance/CLOSURE_BRIEF.md +9 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-08-doctor-agents-guidance/EXECUTION_BRIEF.md +51 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-08-doctor-agents-guidance/slice.json +66 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-09-release-smoke-rollback-docs/CLOSURE_BRIEF.md +10 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-09-release-smoke-rollback-docs/EXECUTION_BRIEF.md +54 -0
- package/specs/quiver-v54-deep-project-analysis-hardening/slices/slice-09-release-smoke-rollback-docs/slice.json +69 -0
- package/src/create-quiver/commands/ai.js +353 -70
- package/src/create-quiver/index.js +3 -0
- package/src/create-quiver/lib/ai/analyze-project-discovery.js +213 -2
- package/src/create-quiver/lib/ai/analyze-project-docs.js +3 -1
- package/src/create-quiver/lib/ai/analyze-project-parser.js +1 -0
- package/src/create-quiver/lib/ai/analyze-project-prompts.js +130 -0
- package/src/create-quiver/lib/ai/analyze-project-repair.js +402 -0
- package/src/create-quiver/lib/ai/analyze-project-sampling.js +31 -4
- package/src/create-quiver/lib/ai/analyze-project-validation.js +168 -0
- package/src/create-quiver/lib/ai/artifacts.js +83 -2
- package/src/create-quiver/lib/doctor.js +107 -12
- package/src/create-quiver/lib/i18n/messages/en.js +5 -0
- package/src/create-quiver/lib/i18n/messages/es.js +5 -0
|
@@ -22,8 +22,16 @@ const {
|
|
|
22
22
|
formatAnalyzeProjectDiffPreview,
|
|
23
23
|
writeAnalyzeProjectDocs,
|
|
24
24
|
} = require('../lib/ai/analyze-project-docs');
|
|
25
|
-
const {
|
|
26
|
-
|
|
25
|
+
const {
|
|
26
|
+
buildAnalyzeProjectPrompt,
|
|
27
|
+
buildAnalyzeProjectRetryPrompt,
|
|
28
|
+
buildSelectedContextManifest,
|
|
29
|
+
writeSelectedContextManifest,
|
|
30
|
+
} = require('../lib/ai/analyze-project-prompts');
|
|
31
|
+
const {
|
|
32
|
+
parseAnalyzeProjectOutputWithRepair,
|
|
33
|
+
writeAnalyzeProjectRepairManifest,
|
|
34
|
+
} = require('../lib/ai/analyze-project-repair');
|
|
27
35
|
const {
|
|
28
36
|
confirmAnalyzeProjectWrites,
|
|
29
37
|
reviewAnalyzeProjectDocProposal,
|
|
@@ -33,7 +41,12 @@ const {
|
|
|
33
41
|
DEFAULT_MAX_FILES: DEFAULT_ANALYZE_MAX_FILES,
|
|
34
42
|
sampleProjectFiles,
|
|
35
43
|
} = require('../lib/ai/analyze-project-sampling');
|
|
36
|
-
const {
|
|
44
|
+
const {
|
|
45
|
+
groupAnalyzeProjectIssues,
|
|
46
|
+
validateAnalyzeProjectPostWrite,
|
|
47
|
+
writeAnalyzeProjectRetryManifest,
|
|
48
|
+
writeAnalyzeProjectValidationManifest,
|
|
49
|
+
} = require('../lib/ai/analyze-project-validation');
|
|
37
50
|
const { openEditor } = require('../lib/cli/editor');
|
|
38
51
|
const { selectOption, promptText } = require('../lib/cli/selectors');
|
|
39
52
|
const { createUx } = require('../lib/cli/ux');
|
|
@@ -166,22 +179,23 @@ function limitList(items, maxItems = 30) {
|
|
|
166
179
|
}
|
|
167
180
|
|
|
168
181
|
function formatAnalyzeProjectIssues(issues = [], maxIssues = 8) {
|
|
169
|
-
const
|
|
170
|
-
const visible =
|
|
171
|
-
const lines = visible.map((
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
const groups = groupAnalyzeProjectIssues(issues, { maxExamplesPerGroup: 1 });
|
|
183
|
+
const visible = groups.slice(0, maxIssues);
|
|
184
|
+
const lines = visible.map((group) => {
|
|
185
|
+
const example = group.examples[0];
|
|
186
|
+
const exampleText = example
|
|
187
|
+
? ` Example: ${example.path || 'analysis'} - ${example.message}`
|
|
188
|
+
: '';
|
|
189
|
+
return `- ${group.path_family}: ${group.type} (${group.count} issue${group.count === 1 ? '' : 's'}). Cause: ${group.cause_hint}${exampleText}`;
|
|
176
190
|
});
|
|
177
|
-
const hidden =
|
|
191
|
+
const hidden = groups.length - visible.length;
|
|
178
192
|
if (hidden > 0) {
|
|
179
|
-
lines.push(`- ... ${hidden} more issue${hidden === 1 ? '' : 's'}`);
|
|
193
|
+
lines.push(`- ... ${hidden} more issue group${hidden === 1 ? '' : 's'}`);
|
|
180
194
|
}
|
|
181
195
|
return lines;
|
|
182
196
|
}
|
|
183
197
|
|
|
184
|
-
function enhanceAnalyzeProjectAnalysisError(error) {
|
|
198
|
+
function enhanceAnalyzeProjectAnalysisError(error, options = {}) {
|
|
185
199
|
if (!error || error.code !== 'AI_ANALYZE_PROJECT_INVALID') {
|
|
186
200
|
return error;
|
|
187
201
|
}
|
|
@@ -195,13 +209,19 @@ function enhanceAnalyzeProjectAnalysisError(error) {
|
|
|
195
209
|
error.message,
|
|
196
210
|
'Issues:',
|
|
197
211
|
...issueLines,
|
|
212
|
+
options.repairManifest?.path ? `Repair manifest: ${options.repairManifest.path}` : '',
|
|
213
|
+
options.retryManifest?.path ? `Retry manifest: ${options.retryManifest.path}` : '',
|
|
214
|
+
options.validationManifest?.path ? `Validation manifest: ${options.validationManifest.path}` : '',
|
|
198
215
|
'Next safe step: inspect the selected evidence with `npx create-quiver ai analyze-project --deep --dry-run --json`, then rerun live. If provider drift repeats, reduce --max-files or --max-bytes.',
|
|
199
|
-
].join('\n'));
|
|
216
|
+
].filter(Boolean).join('\n'));
|
|
200
217
|
wrapped.name = error.name;
|
|
201
218
|
wrapped.code = error.code;
|
|
202
219
|
wrapped.cause = error;
|
|
203
220
|
wrapped.issues = error.issues;
|
|
204
221
|
wrapped.details = error.issues;
|
|
222
|
+
wrapped.repair_manifest = options.repairManifest || null;
|
|
223
|
+
wrapped.retry_manifest = options.retryManifest || null;
|
|
224
|
+
wrapped.validation_manifest = options.validationManifest || null;
|
|
205
225
|
return wrapped;
|
|
206
226
|
}
|
|
207
227
|
|
|
@@ -251,6 +271,9 @@ function formatAnalyzeProjectReport(report) {
|
|
|
251
271
|
lines.push(`Source roots: ${report.detected.source_roots.length > 0 ? report.detected.source_roots.join(', ') : 'none'}`);
|
|
252
272
|
lines.push(`Entrypoints: ${report.detected.entrypoints.length > 0 ? report.detected.entrypoints.join(', ') : 'none'}`);
|
|
253
273
|
lines.push(`Configs: ${report.detected.configs.length > 0 ? report.detected.configs.join(', ') : 'none'}`);
|
|
274
|
+
lines.push(`Lockfiles: ${(report.detected.lockfiles || []).length > 0
|
|
275
|
+
? report.detected.lockfiles.map((file) => `${file.path} (${file.package_manager}; metadata only)`).join(', ')
|
|
276
|
+
: 'none'}`);
|
|
254
277
|
|
|
255
278
|
lines.push('', 'Selected files:');
|
|
256
279
|
for (const file of selected.items) {
|
|
@@ -397,6 +420,60 @@ function buildAnalyzeProjectProviderArtifact(result, clean, repoRoot, options =
|
|
|
397
420
|
};
|
|
398
421
|
}
|
|
399
422
|
|
|
423
|
+
function createAnalyzeProjectAuditRunId(now = new Date()) {
|
|
424
|
+
const date = now instanceof Date ? now : new Date(now || Date.now());
|
|
425
|
+
return `run-${date.toISOString()
|
|
426
|
+
.replace(/\.\d{3}Z$/, 'z')
|
|
427
|
+
.replace(/[^0-9a-z]+/gi, '-')
|
|
428
|
+
.toLowerCase()
|
|
429
|
+
.replace(/^-+|-+$/g, '')}`;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function writeAnalyzeProjectRunStatus(repoRoot, runId, status, details = {}) {
|
|
433
|
+
const statusPath = path.join(repoRoot, '.quiver', 'runs', runId, 'status.json');
|
|
434
|
+
fs.mkdirSync(path.dirname(statusPath), { recursive: true });
|
|
435
|
+
fs.writeFileSync(statusPath, `${JSON.stringify({
|
|
436
|
+
schema_version: 1,
|
|
437
|
+
kind: 'quiver-analyze-project-run-status',
|
|
438
|
+
run_id: runId,
|
|
439
|
+
status,
|
|
440
|
+
updated_at: (details.now instanceof Date ? details.now : new Date(details.now || Date.now())).toISOString(),
|
|
441
|
+
provider: details.provider || null,
|
|
442
|
+
attempts: details.attempts || [],
|
|
443
|
+
artifacts: details.artifacts || {},
|
|
444
|
+
}, null, 2)}\n`);
|
|
445
|
+
return path.relative(repoRoot, statusPath).split(path.sep).join('/');
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function normalizeAnalyzeProjectMaxRetries(value) {
|
|
449
|
+
if (value === undefined || value === null || value === '') {
|
|
450
|
+
return 1;
|
|
451
|
+
}
|
|
452
|
+
const parsed = Number(value);
|
|
453
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
454
|
+
return 1;
|
|
455
|
+
}
|
|
456
|
+
return Math.min(2, Math.floor(parsed));
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function isAnalyzeProjectRetryableError(error) {
|
|
460
|
+
if (!error || error.code !== 'AI_ANALYZE_PROJECT_INVALID') {
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
const retryableIssues = new Set([
|
|
464
|
+
'empty-output',
|
|
465
|
+
'malformed-json',
|
|
466
|
+
'invalid_type',
|
|
467
|
+
'invalid_value',
|
|
468
|
+
'unrecognized_keys',
|
|
469
|
+
'missing-evidence',
|
|
470
|
+
'evidence-not-selected',
|
|
471
|
+
'unapproved-doc-update-path',
|
|
472
|
+
]);
|
|
473
|
+
const issues = Array.isArray(error.issues) ? error.issues : [];
|
|
474
|
+
return issues.length > 0 && issues.every((issue) => retryableIssues.has(issue.issue || ''));
|
|
475
|
+
}
|
|
476
|
+
|
|
400
477
|
function formatAnalyzeProjectLiveReport(report) {
|
|
401
478
|
const warningCount = report.analysis_validation?.warnings?.length || 0;
|
|
402
479
|
const docUpdatePaths = report.analysis_validation?.doc_update_paths || [];
|
|
@@ -405,6 +482,7 @@ function formatAnalyzeProjectLiveReport(report) {
|
|
|
405
482
|
`Mode: ${report.mode}`,
|
|
406
483
|
`Provider: ${report.provider}`,
|
|
407
484
|
`Provider execution: ${report.provider_execution}`,
|
|
485
|
+
`Provider attempts: ${report.provider_attempts?.length || 1}`,
|
|
408
486
|
`Writes: ${report.writes.length === 0 ? 'none' : report.writes.join(', ')}`,
|
|
409
487
|
`Privacy preflight: ${report.privacy_preflight.ok ? 'passed' : 'failed'}`,
|
|
410
488
|
`Prompt bytes: ${report.prompt.bytes}/${report.prompt.max_provider_prompt_bytes}`,
|
|
@@ -609,7 +687,8 @@ function shouldShowHumanProgress(ux, options = {}) {
|
|
|
609
687
|
return options.progress !== false
|
|
610
688
|
&& options.dryRun !== true
|
|
611
689
|
&& options.printPrompt !== true
|
|
612
|
-
&& ux?.mode?.
|
|
690
|
+
&& ux?.mode?.json !== true
|
|
691
|
+
&& (ux?.mode?.decoration === true || options.linearProgress === true);
|
|
613
692
|
}
|
|
614
693
|
|
|
615
694
|
function plannerProgressTitle(action, runtimeProfile, options = {}) {
|
|
@@ -630,10 +709,32 @@ function writeProgressChecks(ux, enabled, title, checks = []) {
|
|
|
630
709
|
}
|
|
631
710
|
}
|
|
632
711
|
|
|
633
|
-
|
|
712
|
+
function writeProgressCheck(ux, enabled, check) {
|
|
713
|
+
if (!enabled || !check) {
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
ux.check(check);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
function writeProgressInfo(ux, enabled, message) {
|
|
720
|
+
if (!enabled || !message) {
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
ux.info(message);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
async function runProviderWithProgress({
|
|
727
|
+
ux,
|
|
728
|
+
enabled,
|
|
729
|
+
message = 'Running agent...',
|
|
730
|
+
successMessage = 'Agent finished',
|
|
731
|
+
failureMessage = 'Agent failed',
|
|
732
|
+
failOnProviderResult = true,
|
|
733
|
+
run,
|
|
734
|
+
}) {
|
|
634
735
|
async function runAndFailOnProviderResult() {
|
|
635
736
|
const result = await run();
|
|
636
|
-
if (result && result.ok === false) {
|
|
737
|
+
if (failOnProviderResult && result && result.ok === false) {
|
|
637
738
|
const error = new Error(result.error?.message || 'provider run failed');
|
|
638
739
|
error.code = result.error?.code || 'AI_PROVIDER_RUN_FAILED';
|
|
639
740
|
error.providerResult = result;
|
|
@@ -1909,6 +2010,22 @@ async function runPrepareContext(repoRoot, options = {}) {
|
|
|
1909
2010
|
}
|
|
1910
2011
|
|
|
1911
2012
|
async function runAnalyzeProject(repoRoot, options = {}) {
|
|
2013
|
+
const role = normalizeRole(options.role || DEFAULT_PLAN_ROLE);
|
|
2014
|
+
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, role, options, DEFAULT_PLAN_PROVIDER);
|
|
2015
|
+
const provider = runtimeProfile.provider;
|
|
2016
|
+
const ux = createCommandUx(options);
|
|
2017
|
+
const showProgress = shouldShowHumanProgress(ux, { ...options, linearProgress: true });
|
|
2018
|
+
const progressTranslator = createTranslator(options.language);
|
|
2019
|
+
const progressTitle = plannerProgressTitle(
|
|
2020
|
+
progressTranslator.t('ai.planner.progress.analyze_project'),
|
|
2021
|
+
runtimeProfile,
|
|
2022
|
+
options,
|
|
2023
|
+
);
|
|
2024
|
+
|
|
2025
|
+
if (showProgress) {
|
|
2026
|
+
ux.heading(progressTitle);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
1912
2029
|
const report = buildAnalyzeProjectReport(repoRoot, options);
|
|
1913
2030
|
if (options.dryRun === true) {
|
|
1914
2031
|
if (options.json === true) {
|
|
@@ -1919,13 +2036,10 @@ async function runAnalyzeProject(repoRoot, options = {}) {
|
|
|
1919
2036
|
return report;
|
|
1920
2037
|
}
|
|
1921
2038
|
|
|
1922
|
-
const role = normalizeRole(options.role || DEFAULT_PLAN_ROLE);
|
|
1923
|
-
const runtimeProfile = resolveRuntimeAgentProfile(repoRoot, role, options, DEFAULT_PLAN_PROVIDER);
|
|
1924
|
-
const provider = runtimeProfile.provider;
|
|
1925
2039
|
const timeoutMs = normalizeTimeout(options.timeout);
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
2040
|
+
writeProgressCheck(ux, showProgress, progressTranslator.t('ai.planner.progress.reading_base_docs'));
|
|
2041
|
+
writeProgressCheck(ux, showProgress, progressTranslator.t('ai.planner.progress.detecting_structure'));
|
|
2042
|
+
writeProgressCheck(ux, showProgress, progressTranslator.t('ai.planner.progress.selecting_sample'));
|
|
1929
2043
|
const promptPackage = buildAnalyzeProjectPrompt({
|
|
1930
2044
|
analysisPlan: report,
|
|
1931
2045
|
repoRoot,
|
|
@@ -1935,17 +2049,8 @@ async function runAnalyzeProject(repoRoot, options = {}) {
|
|
|
1935
2049
|
const prompt = promptPackage.prompt;
|
|
1936
2050
|
const promptLimit = assertProviderPromptWithinLimit(prompt, options.promptLimitOptions || {});
|
|
1937
2051
|
const privacyPreflight = promptPackage.privacyPreflight;
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
ux,
|
|
1941
|
-
showProgress,
|
|
1942
|
-
plannerProgressTitle(progressTranslator.t('ai.planner.progress.analyze_project'), runtimeProfile, options),
|
|
1943
|
-
[
|
|
1944
|
-
progressTranslator.t('ai.planner.progress.reading_base_docs'),
|
|
1945
|
-
progressTranslator.t('ai.planner.progress.detecting_structure'),
|
|
1946
|
-
progressTranslator.t('ai.planner.progress.preparing_prompt'),
|
|
1947
|
-
],
|
|
1948
|
-
);
|
|
2052
|
+
const auditRunId = options.runId || createAnalyzeProjectAuditRunId(options.now || new Date());
|
|
2053
|
+
writeProgressCheck(ux, showProgress, progressTranslator.t('ai.planner.progress.preparing_prompt'));
|
|
1949
2054
|
|
|
1950
2055
|
if (!privacyPreflight.ok) {
|
|
1951
2056
|
const error = new Error(formatError('ai analyze-project privacy preflight failed; provider execution was blocked before sending repository content.'));
|
|
@@ -1983,45 +2088,215 @@ async function runAnalyzeProject(repoRoot, options = {}) {
|
|
|
1983
2088
|
};
|
|
1984
2089
|
}
|
|
1985
2090
|
|
|
2091
|
+
const selectedContextManifest = writeSelectedContextManifest(
|
|
2092
|
+
repoRoot,
|
|
2093
|
+
buildSelectedContextManifest({
|
|
2094
|
+
analysisPlan: report,
|
|
2095
|
+
promptPackage,
|
|
2096
|
+
promptLimit,
|
|
2097
|
+
provider,
|
|
2098
|
+
runId: auditRunId,
|
|
2099
|
+
now: options.now,
|
|
2100
|
+
}),
|
|
2101
|
+
{
|
|
2102
|
+
runId: auditRunId,
|
|
2103
|
+
now: options.now,
|
|
2104
|
+
},
|
|
2105
|
+
);
|
|
2106
|
+
|
|
2107
|
+
const maxRetries = normalizeAnalyzeProjectMaxRetries(options.maxAnalyzeProjectRetries);
|
|
2108
|
+
const providerAttempts = [];
|
|
1986
2109
|
let result;
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
failureMessage: progressTranslator.t('ai.planner.progress.agent_failed'),
|
|
1994
|
-
run: () => (options.runProviderFn || runProvider)(provider, {
|
|
1995
|
-
prompt,
|
|
1996
|
-
cwd: repoRoot,
|
|
1997
|
-
timeoutMs,
|
|
1998
|
-
dryRun: false,
|
|
1999
|
-
probe: options.probe,
|
|
2000
|
-
spawn: options.spawn,
|
|
2001
|
-
tempRoot: options.tempRoot,
|
|
2002
|
-
tempFileName: options.tempFileName,
|
|
2003
|
-
tempFilePrefix: options.tempFilePrefix,
|
|
2004
|
-
...runtimeModelExecutionOptions(runtimeProfile, options),
|
|
2005
|
-
enforceModelSelection: false,
|
|
2006
|
-
}),
|
|
2007
|
-
});
|
|
2008
|
-
} catch (error) {
|
|
2009
|
-
throw annotateProviderError(error, 'analyze-project');
|
|
2010
|
-
}
|
|
2110
|
+
let clean;
|
|
2111
|
+
let parsed;
|
|
2112
|
+
let repairManifest = null;
|
|
2113
|
+
let retryManifest = null;
|
|
2114
|
+
let currentPrompt = prompt;
|
|
2115
|
+
const rawProviderArtifacts = [];
|
|
2011
2116
|
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2117
|
+
for (let attemptIndex = 0; attemptIndex <= maxRetries; attemptIndex += 1) {
|
|
2118
|
+
try {
|
|
2119
|
+
result = await runProviderWithProgress({
|
|
2120
|
+
ux,
|
|
2121
|
+
enabled: showProgress,
|
|
2122
|
+
message: attemptIndex === 0
|
|
2123
|
+
? progressTranslator.t('ai.planner.progress.running_agent')
|
|
2124
|
+
: `Retrying agent (${attemptIndex}/${maxRetries})...`,
|
|
2125
|
+
successMessage: progressTranslator.t('ai.planner.progress.agent_finished'),
|
|
2126
|
+
failureMessage: progressTranslator.t('ai.planner.progress.agent_failed'),
|
|
2127
|
+
failOnProviderResult: false,
|
|
2128
|
+
run: () => (options.runProviderFn || runProvider)(provider, {
|
|
2129
|
+
prompt: currentPrompt,
|
|
2130
|
+
cwd: repoRoot,
|
|
2131
|
+
timeoutMs,
|
|
2132
|
+
dryRun: false,
|
|
2133
|
+
probe: options.probe,
|
|
2134
|
+
spawn: options.spawn,
|
|
2135
|
+
tempRoot: options.tempRoot,
|
|
2136
|
+
tempFileName: options.tempFileName,
|
|
2137
|
+
tempFilePrefix: options.tempFilePrefix,
|
|
2138
|
+
...runtimeModelExecutionOptions(runtimeProfile, options),
|
|
2139
|
+
enforceModelSelection: false,
|
|
2140
|
+
}),
|
|
2141
|
+
});
|
|
2142
|
+
} catch (error) {
|
|
2143
|
+
throw annotateProviderError(error, 'analyze-project');
|
|
2144
|
+
}
|
|
2015
2145
|
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
});
|
|
2023
|
-
|
|
2024
|
-
|
|
2146
|
+
rawProviderArtifacts.push(writeRawProviderArtifact(repoRoot, auditRunId, `analyze-project-provider-attempt-${attemptIndex + 1}`, result, {
|
|
2147
|
+
now: options.now,
|
|
2148
|
+
metadata: {
|
|
2149
|
+
attempt: attemptIndex + 1,
|
|
2150
|
+
retry: attemptIndex > 0,
|
|
2151
|
+
},
|
|
2152
|
+
}));
|
|
2153
|
+
writeProgressCheck(ux, showProgress, progressTranslator.t('ai.planner.progress.writing_artifacts'));
|
|
2154
|
+
if (!result.ok) {
|
|
2155
|
+
writeProgressInfo(ux, showProgress, progressTranslator.t('ai.planner.progress.agent_failed'));
|
|
2156
|
+
writeAnalyzeProjectRunStatus(repoRoot, auditRunId, 'failed', {
|
|
2157
|
+
now: options.now,
|
|
2158
|
+
provider,
|
|
2159
|
+
attempts: [{
|
|
2160
|
+
attempt: attemptIndex + 1,
|
|
2161
|
+
status: 'provider-failed',
|
|
2162
|
+
retry: attemptIndex > 0,
|
|
2163
|
+
}],
|
|
2164
|
+
artifacts: {
|
|
2165
|
+
selected_context: selectedContextManifest,
|
|
2166
|
+
raw_provider: rawProviderArtifacts.map((artifact) => artifact.path),
|
|
2167
|
+
},
|
|
2168
|
+
});
|
|
2169
|
+
throw annotateProviderError(result.error || new Error('provider run failed'), 'analyze-project');
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
clean = extractCleanProviderOutput(result, { prompt: currentPrompt, projectRoot: repoRoot });
|
|
2173
|
+
try {
|
|
2174
|
+
parsed = parseAnalyzeProjectOutputWithRepair(clean.cleanOutput, {
|
|
2175
|
+
selectedFiles: report.selected_files,
|
|
2176
|
+
promptFiles: promptPackage.files,
|
|
2177
|
+
});
|
|
2178
|
+
writeProgressCheck(ux, showProgress, progressTranslator.t('ai.planner.progress.validating_schema'));
|
|
2179
|
+
if (parsed.repairManifest) {
|
|
2180
|
+
repairManifest = writeAnalyzeProjectRepairManifest(repoRoot, parsed.repairManifest, {
|
|
2181
|
+
runId: auditRunId,
|
|
2182
|
+
now: options.now,
|
|
2183
|
+
});
|
|
2184
|
+
writeProgressCheck(ux, showProgress, progressTranslator.t('ai.planner.progress.repairing_schema'));
|
|
2185
|
+
}
|
|
2186
|
+
providerAttempts.push({
|
|
2187
|
+
attempt: attemptIndex + 1,
|
|
2188
|
+
status: 'valid',
|
|
2189
|
+
retry: attemptIndex > 0,
|
|
2190
|
+
parse_source: parsed.parseSource,
|
|
2191
|
+
repaired: parsed.repaired === true,
|
|
2192
|
+
repair_manifest: repairManifest,
|
|
2193
|
+
});
|
|
2194
|
+
if (providerAttempts.length > 1) {
|
|
2195
|
+
retryManifest = writeAnalyzeProjectRetryManifest(repoRoot, {
|
|
2196
|
+
provider,
|
|
2197
|
+
command: 'ai analyze-project',
|
|
2198
|
+
runId: auditRunId,
|
|
2199
|
+
now: options.now,
|
|
2200
|
+
maxRetries,
|
|
2201
|
+
finalStatus: 'valid',
|
|
2202
|
+
attempts: providerAttempts,
|
|
2203
|
+
});
|
|
2204
|
+
}
|
|
2205
|
+
writeAnalyzeProjectRunStatus(repoRoot, auditRunId, 'completed', {
|
|
2206
|
+
now: options.now,
|
|
2207
|
+
provider,
|
|
2208
|
+
attempts: providerAttempts,
|
|
2209
|
+
artifacts: {
|
|
2210
|
+
selected_context: selectedContextManifest,
|
|
2211
|
+
raw_provider: rawProviderArtifacts.map((artifact) => artifact.path),
|
|
2212
|
+
repair: repairManifest,
|
|
2213
|
+
retry: retryManifest,
|
|
2214
|
+
},
|
|
2215
|
+
});
|
|
2216
|
+
break;
|
|
2217
|
+
} catch (error) {
|
|
2218
|
+
let attemptRepairManifest = null;
|
|
2219
|
+
if (error.repair_manifest) {
|
|
2220
|
+
try {
|
|
2221
|
+
attemptRepairManifest = writeAnalyzeProjectRepairManifest(repoRoot, error.repair_manifest, {
|
|
2222
|
+
runId: auditRunId,
|
|
2223
|
+
now: options.now,
|
|
2224
|
+
});
|
|
2225
|
+
} catch {
|
|
2226
|
+
attemptRepairManifest = null;
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
const retryable = isAnalyzeProjectRetryableError(error);
|
|
2230
|
+
providerAttempts.push({
|
|
2231
|
+
attempt: attemptIndex + 1,
|
|
2232
|
+
status: 'invalid',
|
|
2233
|
+
retry: attemptIndex > 0,
|
|
2234
|
+
retryable,
|
|
2235
|
+
issue_count: Array.isArray(error.issues) ? error.issues.length : 0,
|
|
2236
|
+
groups: groupAnalyzeProjectIssues(error.issues, { maxExamplesPerGroup: 2 }),
|
|
2237
|
+
repair_manifest: attemptRepairManifest,
|
|
2238
|
+
});
|
|
2239
|
+
|
|
2240
|
+
if (retryable && attemptIndex < maxRetries) {
|
|
2241
|
+
writeProgressInfo(ux, showProgress, progressTranslator.t('ai.planner.progress.retrying_agent'));
|
|
2242
|
+
currentPrompt = buildAnalyzeProjectRetryPrompt({
|
|
2243
|
+
previousOutput: clean.cleanOutput,
|
|
2244
|
+
issueLines: formatAnalyzeProjectIssues(error.issues, 6),
|
|
2245
|
+
attempt: attemptIndex + 1,
|
|
2246
|
+
maxRetries,
|
|
2247
|
+
});
|
|
2248
|
+
continue;
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
if (providerAttempts.length > 1) {
|
|
2252
|
+
retryManifest = writeAnalyzeProjectRetryManifest(repoRoot, {
|
|
2253
|
+
provider,
|
|
2254
|
+
command: 'ai analyze-project',
|
|
2255
|
+
runId: auditRunId,
|
|
2256
|
+
now: options.now,
|
|
2257
|
+
maxRetries,
|
|
2258
|
+
finalStatus: 'invalid',
|
|
2259
|
+
attempts: providerAttempts,
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
let validationManifest = null;
|
|
2264
|
+
try {
|
|
2265
|
+
validationManifest = writeAnalyzeProjectValidationManifest(repoRoot, {
|
|
2266
|
+
error,
|
|
2267
|
+
provider,
|
|
2268
|
+
command: 'ai analyze-project',
|
|
2269
|
+
runId: auditRunId,
|
|
2270
|
+
now: options.now,
|
|
2271
|
+
retry: {
|
|
2272
|
+
attempts: providerAttempts.length,
|
|
2273
|
+
max_retries: maxRetries,
|
|
2274
|
+
retryable,
|
|
2275
|
+
exhausted: retryable && attemptIndex >= maxRetries,
|
|
2276
|
+
manifest: retryManifest,
|
|
2277
|
+
},
|
|
2278
|
+
});
|
|
2279
|
+
} catch {
|
|
2280
|
+
validationManifest = null;
|
|
2281
|
+
}
|
|
2282
|
+
writeAnalyzeProjectRunStatus(repoRoot, auditRunId, 'failed', {
|
|
2283
|
+
now: options.now,
|
|
2284
|
+
provider,
|
|
2285
|
+
attempts: providerAttempts,
|
|
2286
|
+
artifacts: {
|
|
2287
|
+
selected_context: selectedContextManifest,
|
|
2288
|
+
raw_provider: rawProviderArtifacts.map((artifact) => artifact.path),
|
|
2289
|
+
repair: attemptRepairManifest,
|
|
2290
|
+
retry: retryManifest,
|
|
2291
|
+
validation: validationManifest,
|
|
2292
|
+
},
|
|
2293
|
+
});
|
|
2294
|
+
throw enhanceAnalyzeProjectAnalysisError(error, {
|
|
2295
|
+
validationManifest,
|
|
2296
|
+
repairManifest: attemptRepairManifest,
|
|
2297
|
+
retryManifest,
|
|
2298
|
+
});
|
|
2299
|
+
}
|
|
2025
2300
|
}
|
|
2026
2301
|
const completedReport = {
|
|
2027
2302
|
...report,
|
|
@@ -2040,8 +2315,16 @@ async function runAnalyzeProject(repoRoot, options = {}) {
|
|
|
2040
2315
|
parse_source: parsed.parseSource,
|
|
2041
2316
|
warnings: parsed.warnings,
|
|
2042
2317
|
doc_update_paths: parsed.docUpdatePaths,
|
|
2318
|
+
repaired: parsed.repaired === true,
|
|
2319
|
+
repair_manifest: repairManifest,
|
|
2320
|
+
retry_count: Math.max(0, providerAttempts.length - 1),
|
|
2321
|
+
retry_manifest: retryManifest,
|
|
2043
2322
|
},
|
|
2044
2323
|
provider_artifact: buildAnalyzeProjectProviderArtifact(result, clean, repoRoot),
|
|
2324
|
+
raw_provider_artifacts: rawProviderArtifacts.map((artifact) => artifact.path),
|
|
2325
|
+
provider_attempts: providerAttempts,
|
|
2326
|
+
run_status_path: path.join('.quiver', 'runs', auditRunId, 'status.json').split(path.sep).join('/'),
|
|
2327
|
+
selected_context_manifest: selectedContextManifest,
|
|
2045
2328
|
};
|
|
2046
2329
|
|
|
2047
2330
|
if (options.review === true) {
|
|
@@ -2862,6 +2862,9 @@ function buildDoctorCommandReport(projectRoot) {
|
|
|
2862
2862
|
|
|
2863
2863
|
const suggestedFixes = [
|
|
2864
2864
|
...doctorReport.recommendations,
|
|
2865
|
+
doctorReport.warnings.some((warning) => String(warning).includes('AGENTS.md'))
|
|
2866
|
+
? 'Repair AGENTS.md contract: npx create-quiver doctor --fix --dry-run, then npx create-quiver doctor --fix'
|
|
2867
|
+
: '',
|
|
2865
2868
|
!hasQuiverState
|
|
2866
2869
|
? 'Run migration first: npx create-quiver migrate'
|
|
2867
2870
|
: !hasScanArtifacts
|