create-quiver 0.17.0 → 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 +8 -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 +383 -34
- 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 +6 -0
- package/src/create-quiver/lib/i18n/messages/es.js +6 -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');
|
|
@@ -165,6 +178,53 @@ function limitList(items, maxItems = 30) {
|
|
|
165
178
|
};
|
|
166
179
|
}
|
|
167
180
|
|
|
181
|
+
function formatAnalyzeProjectIssues(issues = [], maxIssues = 8) {
|
|
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}`;
|
|
190
|
+
});
|
|
191
|
+
const hidden = groups.length - visible.length;
|
|
192
|
+
if (hidden > 0) {
|
|
193
|
+
lines.push(`- ... ${hidden} more issue group${hidden === 1 ? '' : 's'}`);
|
|
194
|
+
}
|
|
195
|
+
return lines;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function enhanceAnalyzeProjectAnalysisError(error, options = {}) {
|
|
199
|
+
if (!error || error.code !== 'AI_ANALYZE_PROJECT_INVALID') {
|
|
200
|
+
return error;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const issueLines = formatAnalyzeProjectIssues(error.issues);
|
|
204
|
+
if (issueLines.length === 0) {
|
|
205
|
+
return error;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const wrapped = new Error([
|
|
209
|
+
error.message,
|
|
210
|
+
'Issues:',
|
|
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}` : '',
|
|
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.',
|
|
216
|
+
].filter(Boolean).join('\n'));
|
|
217
|
+
wrapped.name = error.name;
|
|
218
|
+
wrapped.code = error.code;
|
|
219
|
+
wrapped.cause = error;
|
|
220
|
+
wrapped.issues = error.issues;
|
|
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;
|
|
225
|
+
return wrapped;
|
|
226
|
+
}
|
|
227
|
+
|
|
168
228
|
function formatAnalyzeProjectFileLine(file) {
|
|
169
229
|
const details = [];
|
|
170
230
|
if (Array.isArray(file.signals) && file.signals.length > 0) {
|
|
@@ -211,6 +271,9 @@ function formatAnalyzeProjectReport(report) {
|
|
|
211
271
|
lines.push(`Source roots: ${report.detected.source_roots.length > 0 ? report.detected.source_roots.join(', ') : 'none'}`);
|
|
212
272
|
lines.push(`Entrypoints: ${report.detected.entrypoints.length > 0 ? report.detected.entrypoints.join(', ') : 'none'}`);
|
|
213
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'}`);
|
|
214
277
|
|
|
215
278
|
lines.push('', 'Selected files:');
|
|
216
279
|
for (const file of selected.items) {
|
|
@@ -357,6 +420,60 @@ function buildAnalyzeProjectProviderArtifact(result, clean, repoRoot, options =
|
|
|
357
420
|
};
|
|
358
421
|
}
|
|
359
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
|
+
|
|
360
477
|
function formatAnalyzeProjectLiveReport(report) {
|
|
361
478
|
const warningCount = report.analysis_validation?.warnings?.length || 0;
|
|
362
479
|
const docUpdatePaths = report.analysis_validation?.doc_update_paths || [];
|
|
@@ -365,6 +482,7 @@ function formatAnalyzeProjectLiveReport(report) {
|
|
|
365
482
|
`Mode: ${report.mode}`,
|
|
366
483
|
`Provider: ${report.provider}`,
|
|
367
484
|
`Provider execution: ${report.provider_execution}`,
|
|
485
|
+
`Provider attempts: ${report.provider_attempts?.length || 1}`,
|
|
368
486
|
`Writes: ${report.writes.length === 0 ? 'none' : report.writes.join(', ')}`,
|
|
369
487
|
`Privacy preflight: ${report.privacy_preflight.ok ? 'passed' : 'failed'}`,
|
|
370
488
|
`Prompt bytes: ${report.prompt.bytes}/${report.prompt.max_provider_prompt_bytes}`,
|
|
@@ -569,7 +687,8 @@ function shouldShowHumanProgress(ux, options = {}) {
|
|
|
569
687
|
return options.progress !== false
|
|
570
688
|
&& options.dryRun !== true
|
|
571
689
|
&& options.printPrompt !== true
|
|
572
|
-
&& ux?.mode?.
|
|
690
|
+
&& ux?.mode?.json !== true
|
|
691
|
+
&& (ux?.mode?.decoration === true || options.linearProgress === true);
|
|
573
692
|
}
|
|
574
693
|
|
|
575
694
|
function plannerProgressTitle(action, runtimeProfile, options = {}) {
|
|
@@ -590,10 +709,32 @@ function writeProgressChecks(ux, enabled, title, checks = []) {
|
|
|
590
709
|
}
|
|
591
710
|
}
|
|
592
711
|
|
|
593
|
-
|
|
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
|
+
}) {
|
|
594
735
|
async function runAndFailOnProviderResult() {
|
|
595
736
|
const result = await run();
|
|
596
|
-
if (result && result.ok === false) {
|
|
737
|
+
if (failOnProviderResult && result && result.ok === false) {
|
|
597
738
|
const error = new Error(result.error?.message || 'provider run failed');
|
|
598
739
|
error.code = result.error?.code || 'AI_PROVIDER_RUN_FAILED';
|
|
599
740
|
error.providerResult = result;
|
|
@@ -1869,6 +2010,22 @@ async function runPrepareContext(repoRoot, options = {}) {
|
|
|
1869
2010
|
}
|
|
1870
2011
|
|
|
1871
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
|
+
|
|
1872
2029
|
const report = buildAnalyzeProjectReport(repoRoot, options);
|
|
1873
2030
|
if (options.dryRun === true) {
|
|
1874
2031
|
if (options.json === true) {
|
|
@@ -1879,10 +2036,10 @@ async function runAnalyzeProject(repoRoot, options = {}) {
|
|
|
1879
2036
|
return report;
|
|
1880
2037
|
}
|
|
1881
2038
|
|
|
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
2039
|
const timeoutMs = normalizeTimeout(options.timeout);
|
|
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'));
|
|
1886
2043
|
const promptPackage = buildAnalyzeProjectPrompt({
|
|
1887
2044
|
analysisPlan: report,
|
|
1888
2045
|
repoRoot,
|
|
@@ -1892,6 +2049,8 @@ async function runAnalyzeProject(repoRoot, options = {}) {
|
|
|
1892
2049
|
const prompt = promptPackage.prompt;
|
|
1893
2050
|
const promptLimit = assertProviderPromptWithinLimit(prompt, options.promptLimitOptions || {});
|
|
1894
2051
|
const privacyPreflight = promptPackage.privacyPreflight;
|
|
2052
|
+
const auditRunId = options.runId || createAnalyzeProjectAuditRunId(options.now || new Date());
|
|
2053
|
+
writeProgressCheck(ux, showProgress, progressTranslator.t('ai.planner.progress.preparing_prompt'));
|
|
1895
2054
|
|
|
1896
2055
|
if (!privacyPreflight.ok) {
|
|
1897
2056
|
const error = new Error(formatError('ai analyze-project privacy preflight failed; provider execution was blocked before sending repository content.'));
|
|
@@ -1929,34 +2088,216 @@ async function runAnalyzeProject(repoRoot, options = {}) {
|
|
|
1929
2088
|
};
|
|
1930
2089
|
}
|
|
1931
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 = [];
|
|
1932
2109
|
let result;
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
2110
|
+
let clean;
|
|
2111
|
+
let parsed;
|
|
2112
|
+
let repairManifest = null;
|
|
2113
|
+
let retryManifest = null;
|
|
2114
|
+
let currentPrompt = prompt;
|
|
2115
|
+
const rawProviderArtifacts = [];
|
|
2116
|
+
|
|
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
|
+
}
|
|
1950
2145
|
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
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
|
+
}
|
|
1954
2171
|
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
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
|
+
}
|
|
2300
|
+
}
|
|
1960
2301
|
const completedReport = {
|
|
1961
2302
|
...report,
|
|
1962
2303
|
provider,
|
|
@@ -1974,8 +2315,16 @@ async function runAnalyzeProject(repoRoot, options = {}) {
|
|
|
1974
2315
|
parse_source: parsed.parseSource,
|
|
1975
2316
|
warnings: parsed.warnings,
|
|
1976
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,
|
|
1977
2322
|
},
|
|
1978
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,
|
|
1979
2328
|
};
|
|
1980
2329
|
|
|
1981
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
|