create-quiver 0.17.4 → 0.17.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/docs/CLI_UX_GUIDE.md +7 -0
  3. package/docs/TROUBLESHOOTING.md +62 -0
  4. package/docs/reference/commands.md +16 -0
  5. package/docs/workflows/existing-project-ai-quiver-setup.md +0 -1
  6. package/docs/workflows/existing-project.md +1 -0
  7. package/package.json +1 -1
  8. package/specs/quiver-v43-cli-i18n-audit-release-readiness/command-language-mode-matrix.json +1 -0
  9. package/specs/quiver-v56-analyze-project-usable-doc-merge/EVIDENCE_REPORT.md +11 -0
  10. package/specs/quiver-v56-analyze-project-usable-doc-merge/EXECUTION_PLAN.md +28 -0
  11. package/specs/quiver-v56-analyze-project-usable-doc-merge/SPEC.md +96 -0
  12. package/specs/quiver-v56-analyze-project-usable-doc-merge/STATUS.md +26 -0
  13. package/specs/quiver-v56-analyze-project-usable-doc-merge/pr.md +56 -0
  14. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-01-document-classification-merge-engine/CLOSURE_BRIEF.md +61 -0
  15. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-01-document-classification-merge-engine/EXECUTION_BRIEF.md +59 -0
  16. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-01-document-classification-merge-engine/pr.md +61 -0
  17. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-01-document-classification-merge-engine/slice.json +71 -0
  18. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-02-apply-integration-validation-contract/CLOSURE_BRIEF.md +30 -0
  19. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-02-apply-integration-validation-contract/EXECUTION_BRIEF.md +39 -0
  20. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-02-apply-integration-validation-contract/pr.md +62 -0
  21. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-02-apply-integration-validation-contract/slice.json +80 -0
  22. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-03-cli-docs-real-fixture-smoke/CLOSURE_BRIEF.md +29 -0
  23. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-03-cli-docs-real-fixture-smoke/EXECUTION_BRIEF.md +32 -0
  24. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-03-cli-docs-real-fixture-smoke/pr.md +61 -0
  25. package/specs/quiver-v56-analyze-project-usable-doc-merge/slices/slice-03-cli-docs-real-fixture-smoke/slice.json +79 -0
  26. package/specs/quiver-v57-evidence-budget-recovery-ux/EVIDENCE_REPORT.md +27 -0
  27. package/specs/quiver-v57-evidence-budget-recovery-ux/EXECUTION_PLAN.md +41 -0
  28. package/specs/quiver-v57-evidence-budget-recovery-ux/SPEC.md +139 -0
  29. package/specs/quiver-v57-evidence-budget-recovery-ux/STATUS.md +20 -0
  30. package/specs/quiver-v57-evidence-budget-recovery-ux/pr.md +124 -0
  31. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-01-recovery-contract-security-classifier/CLOSURE_BRIEF.md +22 -0
  32. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-01-recovery-contract-security-classifier/EXECUTION_BRIEF.md +58 -0
  33. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-01-recovery-contract-security-classifier/pr.md +12 -0
  34. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-01-recovery-contract-security-classifier/slice.json +60 -0
  35. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-02-budget-command-recommendation/CLOSURE_BRIEF.md +9 -0
  36. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-02-budget-command-recommendation/EXECUTION_BRIEF.md +54 -0
  37. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-02-budget-command-recommendation/pr.md +12 -0
  38. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-02-budget-command-recommendation/slice.json +60 -0
  39. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-03-cli-json-i18n-output/CLOSURE_BRIEF.md +10 -0
  40. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-03-cli-json-i18n-output/EXECUTION_BRIEF.md +58 -0
  41. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-03-cli-json-i18n-output/pr.md +13 -0
  42. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-03-cli-json-i18n-output/slice.json +68 -0
  43. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-04-integration-fixtures-docs-release-smoke/CLOSURE_BRIEF.md +14 -0
  44. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-04-integration-fixtures-docs-release-smoke/EXECUTION_BRIEF.md +55 -0
  45. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-04-integration-fixtures-docs-release-smoke/pr.md +14 -0
  46. package/specs/quiver-v57-evidence-budget-recovery-ux/slices/slice-04-integration-fixtures-docs-release-smoke/slice.json +65 -0
  47. package/src/create-quiver/commands/ai.js +132 -2
  48. package/src/create-quiver/lib/ai/analyze-project-docs.js +284 -4
  49. package/src/create-quiver/lib/ai/analyze-project-proposal.js +11 -0
  50. package/src/create-quiver/lib/ai/analyze-project-recovery.js +736 -0
  51. package/src/create-quiver/lib/ai/analyze-project-validation.js +27 -0
  52. package/src/create-quiver/lib/i18n/messages/en.js +6 -0
  53. package/src/create-quiver/lib/i18n/messages/es.js +6 -0
@@ -0,0 +1,68 @@
1
+ {
2
+ "slice_id": "slice-03-cli-json-i18n-output",
3
+ "ticket": "QUIVER-57-03",
4
+ "type": "feature",
5
+ "title": "CLI + JSON + i18n Output",
6
+ "objective": "Expose recovery guidance in CLI output, JSON output, manifests, and English/Spanish messages.",
7
+ "description": "Integrates recovery payloads into analyze-project failure output, JSON error output, validation manifests, and English/Spanish copy.",
8
+ "git": {
9
+ "branch_type": "feature",
10
+ "base_branch": "main",
11
+ "branch_slug": "v57-cli-json-i18n-output",
12
+ "branch_name": "feature/QUIVER-57-03-v57-cli-json-i18n-output"
13
+ },
14
+ "files": [
15
+ "src/create-quiver/commands/ai.js",
16
+ "src/create-quiver/lib/ai/analyze-project-validation.js",
17
+ "src/create-quiver/lib/i18n/messages/en.js",
18
+ "src/create-quiver/lib/i18n/messages/es.js",
19
+ "tests/commands/ai-analyze-project-provider.test.js",
20
+ "tests/lib/i18n-catalog.test.js",
21
+ "specs/quiver-v57-evidence-budget-recovery-ux/**"
22
+ ],
23
+ "allowed_write_paths": [
24
+ "src/create-quiver/commands/ai.js",
25
+ "src/create-quiver/lib/ai/analyze-project-validation.js",
26
+ "src/create-quiver/lib/i18n/messages/en.js",
27
+ "src/create-quiver/lib/i18n/messages/es.js",
28
+ "tests/commands/ai-analyze-project-provider.test.js",
29
+ "tests/lib/i18n-catalog.test.js",
30
+ "specs/quiver-v57-evidence-budget-recovery-ux/**"
31
+ ],
32
+ "depends_on": ["slice-02-budget-command-recommendation"],
33
+ "parallel_safe": "never",
34
+ "parallel_safe_reason": "Consumes the recovery recommendation contract from slice 02.",
35
+ "must": [
36
+ "Detect evidence-not-selected validation failures and attach recovery guidance.",
37
+ "Render a prominent safe rerun command in human CLI output.",
38
+ "Expose recovery details in JSON output without breaking existing fields.",
39
+ "Persist recovery details in validation or repair manifests.",
40
+ "Provide English and Spanish copy for recovery guidance.",
41
+ "Keep analyze-project failing when final validation remains invalid."
42
+ ],
43
+ "not_included": [
44
+ "Weakening schema or evidence validation.",
45
+ "Automatically applying recovery budgets.",
46
+ "Changing budget recommendation formulas.",
47
+ "Adding live provider integration tests.",
48
+ "Writing final docs after invalid JSON."
49
+ ],
50
+ "acceptance": [
51
+ "Evidence validation failures include a highlighted next command.",
52
+ "Issue details remain grouped and truncated instead of producing noisy schema dumps.",
53
+ "JSON output remains valid and includes recovery details when available.",
54
+ "Spanish output includes equivalent actionable recovery guidance.",
55
+ "The command exits as a controlled failure until validation passes."
56
+ ],
57
+ "actual_hours": 4,
58
+ "tests": [
59
+ "node --test tests/commands/ai-analyze-project-provider.test.js",
60
+ "node --test tests/lib/i18n-catalog.test.js",
61
+ "node bin/create-quiver.js spec validate specs/quiver-v57-evidence-budget-recovery-ux --strict",
62
+ "git diff --check"
63
+ ],
64
+ "estimated_hours": 4,
65
+ "status": "completed",
66
+ "started_at": "2026-06-18T00:00:00.000Z",
67
+ "completed_at": "2026-06-18T00:00:00.000Z"
68
+ }
@@ -0,0 +1,14 @@
1
+ # CLOSURE_BRIEF - slice-04 Integration Fixtures + Docs + Release Smoke
2
+
3
+ ## Summary
4
+
5
+ Completed integration fixture coverage, documentation, and release evidence for evidence budget recovery UX.
6
+
7
+ ## Validation
8
+
9
+ - PASS `node --test tests/lib/ai-analyze-project-recovery.test.js`
10
+ - PASS `node --test tests/commands/ai-analyze-project-provider.test.js`
11
+ - PASS `node --test tests/lib/i18n-catalog.test.js`
12
+ - PASS `npm run docs:check`
13
+ - PASS `node bin/create-quiver.js spec validate specs/quiver-v57-evidence-budget-recovery-ux --strict`
14
+ - PASS `git diff --check`
@@ -0,0 +1,55 @@
1
+ # EXECUTION_BRIEF - slice-04 Integration Fixtures + Docs + Release Smoke
2
+
3
+ ## Objective
4
+
5
+ Validate the full recovery workflow with fixtures, docs, and release smoke evidence.
6
+
7
+ ## Context
8
+
9
+ This slice validates the feature end to end after the contracts and CLI output are implemented.
10
+
11
+ ## Scope
12
+
13
+ - Add sanitized nika-erp-style fixture coverage.
14
+ - Add docs/troubleshooting guidance.
15
+ - Validate manifests and JSON recovery payloads.
16
+ - Validate English and Spanish command output.
17
+ - Update release evidence.
18
+
19
+ ## Acceptance Criteria
20
+
21
+ - A nika-erp-style evidence failure produces a clear recovery command or safe fallback.
22
+ - Unsafe paths are never recommended.
23
+ - Manifests contain recovery classification and command data.
24
+ - Docs explain why `--max-bytes` exists and how to rerun safely.
25
+ - Release smoke evidence is recorded.
26
+
27
+ ## Expected Files
28
+
29
+ - `tests/commands/ai-analyze-project-provider.test.js`
30
+ - `docs/**`
31
+ - `specs/quiver-v57-evidence-budget-recovery-ux/**`
32
+
33
+ ## Validation
34
+
35
+ ```bash
36
+ node --test tests/lib/ai-analyze-project-recovery.test.js
37
+ node --test tests/commands/ai-analyze-project-provider.test.js
38
+ node --test tests/lib/i18n-catalog.test.js
39
+ npm run docs:check
40
+ node bin/create-quiver.js spec validate specs/quiver-v57-evidence-budget-recovery-ux --strict
41
+ git diff --check
42
+ ```
43
+
44
+ ## Completion Checklist
45
+
46
+ - Sanitized nika-erp-style fixture reproduces recovery guidance.
47
+ - Docs explain `--max-files`, `--max-bytes`, and safe rerun guidance.
48
+ - Release evidence records validation commands.
49
+ - No private repo content or secrets are stored.
50
+ - Slice closure brief records validation evidence.
51
+
52
+ ## Constraints
53
+
54
+ - Do not require a real private project fixture in CI.
55
+ - Do not store secrets or private project content.
@@ -0,0 +1,14 @@
1
+ # PR - slice-04 Integration Fixtures + Docs + Release Smoke
2
+
3
+ ## Summary
4
+
5
+ - Adds public troubleshooting guidance for `evidence-not-selected` recovery.
6
+ - Documents safe rerun commands and when to use `--max-files`, `--max-bytes`, `--include-tests`, `--include-db`, or `--scope`.
7
+ - Adds provider command coverage for Spanish recovery output, manifests, and `--json` recovery payloads.
8
+
9
+ ## Validation
10
+
11
+ - PASS `node --test tests/lib/ai-analyze-project-recovery.test.js`
12
+ - PASS `node --test tests/commands/ai-analyze-project-provider.test.js`
13
+ - PASS `node --test tests/lib/i18n-catalog.test.js`
14
+ - PASS `npm run docs:check`
@@ -0,0 +1,65 @@
1
+ {
2
+ "slice_id": "slice-04-integration-fixtures-docs-release-smoke",
3
+ "ticket": "QUIVER-57-04",
4
+ "type": "feature",
5
+ "title": "Integration Fixtures + Docs + Release Smoke",
6
+ "objective": "Validate recovery guidance end to end and document the safe rerun workflow.",
7
+ "description": "Completes integration evidence, documentation, troubleshooting guidance, and release-smoke coverage for the recovery workflow.",
8
+ "git": {
9
+ "branch_type": "feature",
10
+ "base_branch": "main",
11
+ "branch_slug": "v57-integration-fixtures-docs-release-smoke",
12
+ "branch_name": "feature/QUIVER-57-04-v57-integration-fixtures-docs-release-smoke"
13
+ },
14
+ "files": [
15
+ "tests/lib/ai-analyze-project-recovery.test.js",
16
+ "tests/commands/ai-analyze-project-provider.test.js",
17
+ "tests/lib/i18n-catalog.test.js",
18
+ "docs/**",
19
+ "specs/quiver-v57-evidence-budget-recovery-ux/**"
20
+ ],
21
+ "allowed_write_paths": [
22
+ "tests/lib/ai-analyze-project-recovery.test.js",
23
+ "tests/commands/ai-analyze-project-provider.test.js",
24
+ "tests/lib/i18n-catalog.test.js",
25
+ "docs/**",
26
+ "specs/quiver-v57-evidence-budget-recovery-ux/**"
27
+ ],
28
+ "depends_on": ["slice-03-cli-json-i18n-output"],
29
+ "parallel_safe": "after_dependencies",
30
+ "parallel_safe_reason": "Docs and fixture drafting can run in parallel after slice 03, but final smoke depends on all prior slices.",
31
+ "must": [
32
+ "Cover nika-erp-style evidence validation failures with sanitized fixtures.",
33
+ "Document how users should respond to budget and evidence recovery guidance.",
34
+ "Ensure recovery details are represented in manifests and JSON output.",
35
+ "Verify English and Spanish recovery output.",
36
+ "Record release-smoke evidence for the final workflow."
37
+ ],
38
+ "not_included": [
39
+ "Committing private real-project fixtures.",
40
+ "Storing secrets or private source content in tests.",
41
+ "Publishing npm packages.",
42
+ "Making live provider calls mandatory in CI.",
43
+ "Changing product code in analyzed repositories."
44
+ ],
45
+ "acceptance": [
46
+ "A nika-erp-style failure produces a clear recovery command.",
47
+ "Unsafe, generated, and metadata-only paths are not recommended as context expansion targets.",
48
+ "Validation manifests include recovery details when relevant.",
49
+ "Documentation explains why and how to adjust max-files and max-bytes.",
50
+ "Release evidence identifies the smoke command and expected controlled behavior."
51
+ ],
52
+ "actual_hours": 3,
53
+ "tests": [
54
+ "node --test tests/lib/ai-analyze-project-recovery.test.js",
55
+ "node --test tests/commands/ai-analyze-project-provider.test.js",
56
+ "node --test tests/lib/i18n-catalog.test.js",
57
+ "npm run docs:check",
58
+ "node bin/create-quiver.js spec validate specs/quiver-v57-evidence-budget-recovery-ux --strict",
59
+ "git diff --check"
60
+ ],
61
+ "estimated_hours": 3,
62
+ "status": "completed",
63
+ "started_at": "2026-06-18T00:00:00.000Z",
64
+ "completed_at": "2026-06-18T00:00:00.000Z"
65
+ }
@@ -32,6 +32,10 @@ const {
32
32
  parseAnalyzeProjectOutputWithRepair,
33
33
  writeAnalyzeProjectRepairManifest,
34
34
  } = require('../lib/ai/analyze-project-repair');
35
+ const {
36
+ buildEvidenceRecoveryPayload,
37
+ classifyEvidenceRecoveryIssues,
38
+ } = require('../lib/ai/analyze-project-recovery');
35
39
  const {
36
40
  confirmAnalyzeProjectWrites,
37
41
  reviewAnalyzeProjectDocProposal,
@@ -207,6 +211,40 @@ function formatAnalyzeProjectIssues(issues = [], maxIssues = 8) {
207
211
  return lines;
208
212
  }
209
213
 
214
+ function formatAnalyzeProjectRecoveryLines(recovery, translator = createTranslator('en')) {
215
+ if (!recovery || recovery.reason !== 'evidence_not_selected') {
216
+ return [];
217
+ }
218
+
219
+ const lines = [
220
+ '',
221
+ translator.t('analyze_project.recovery.title'),
222
+ ];
223
+
224
+ if (recovery.command) {
225
+ lines.push(
226
+ translator.t('analyze_project.recovery.reason'),
227
+ translator.t('analyze_project.recovery.recommended_command'),
228
+ recovery.command,
229
+ );
230
+ } else {
231
+ lines.push(translator.t('analyze_project.recovery.safe_fallback'));
232
+ }
233
+
234
+ if (recovery.budget) {
235
+ lines.push(translator.t('analyze_project.recovery.budget', {
236
+ files: recovery.budget.recommended_max_files || 0,
237
+ bytes: recovery.budget.recommended_max_bytes || 0,
238
+ }));
239
+ }
240
+
241
+ for (const warning of recovery.warnings || []) {
242
+ lines.push(`${translator.t('analyze_project.recovery.warning')}: ${warning}`);
243
+ }
244
+
245
+ return lines;
246
+ }
247
+
210
248
  function enhanceAnalyzeProjectAnalysisError(error, options = {}) {
211
249
  if (!error || error.code !== 'AI_ANALYZE_PROJECT_INVALID') {
212
250
  return error;
@@ -219,6 +257,7 @@ function enhanceAnalyzeProjectAnalysisError(error, options = {}) {
219
257
 
220
258
  const wrapped = new Error([
221
259
  error.message,
260
+ ...formatAnalyzeProjectRecoveryLines(options.recovery, options.translator),
222
261
  'Issues:',
223
262
  ...issueLines,
224
263
  options.repairManifest?.path ? `Repair manifest: ${options.repairManifest.path}` : '',
@@ -234,9 +273,40 @@ function enhanceAnalyzeProjectAnalysisError(error, options = {}) {
234
273
  wrapped.repair_manifest = options.repairManifest || null;
235
274
  wrapped.retry_manifest = options.retryManifest || null;
236
275
  wrapped.validation_manifest = options.validationManifest || null;
276
+ wrapped.recovery = options.recovery || null;
237
277
  return wrapped;
238
278
  }
239
279
 
280
+ function buildAnalyzeProjectEvidenceRecovery(repoRoot, error, report, options = {}) {
281
+ const issues = Array.isArray(error?.issues) ? error.issues : [];
282
+ if (!issues.some((issue) => (issue.issue || issue.code) === 'evidence-not-selected')) {
283
+ return null;
284
+ }
285
+
286
+ const classification = classifyEvidenceRecoveryIssues(repoRoot, issues, {
287
+ selectedFiles: report.selected_files || [],
288
+ omittedFiles: report.omitted_files || [],
289
+ safetyExclusions: report.safety_exclusions || [],
290
+ });
291
+ const payload = buildEvidenceRecoveryPayload(classification, {
292
+ budgets: report.budgets || {},
293
+ deep: report.options?.deep === true || options.deep === true,
294
+ includeDb: report.options?.include_db === true,
295
+ includeSource: report.options?.include_source === true,
296
+ includeTests: report.options?.include_tests === true,
297
+ lang: options.language,
298
+ model: options.model,
299
+ provider: options.provider,
300
+ scope: options.scope,
301
+ strict: options.strict === true,
302
+ });
303
+
304
+ return {
305
+ ...payload,
306
+ classification,
307
+ };
308
+ }
309
+
240
310
  function formatAnalyzeProjectFileLine(file) {
241
311
  const details = [];
242
312
  if (Array.isArray(file.signals) && file.signals.length > 0) {
@@ -528,6 +598,7 @@ function summarizeAnalyzeProjectWritePlan(writePlan = []) {
528
598
  before_sha256: item.before_sha256,
529
599
  after_sha256: item.after_sha256,
530
600
  reason: item.reason,
601
+ merge_report: item.merge_report,
531
602
  }));
532
603
  }
533
604
 
@@ -545,14 +616,46 @@ function formatAnalyzeProjectSavedProposalReport(report = {}) {
545
616
  `Proposal summary: ${artifacts.proposal_markdown || 'none'}`,
546
617
  `Proposal diff: ${artifacts.proposal_diff || 'none'}`,
547
618
  `Manifest: ${artifacts.manifest || 'none'}`,
619
+ ];
620
+ lines.push(...formatAnalyzeProjectMergeSummary(report.write_plan));
621
+ lines.push(
548
622
  '',
549
623
  'Next commands:',
550
624
  `- npx create-quiver ai analyze-project apply --run ${report.run_id || '<run-id>'}`,
551
625
  '- npx create-quiver ai analyze-project --deep --apply-docs --provider <provider> --model <model>',
552
- ];
626
+ );
553
627
  return `${lines.join('\n')}\n`;
554
628
  }
555
629
 
630
+ function formatAnalyzeProjectMergeSummary(writePlan = []) {
631
+ const changed = (Array.isArray(writePlan) ? writePlan : []).filter((item) => item.action !== 'skip');
632
+ if (changed.length === 0) {
633
+ return [];
634
+ }
635
+
636
+ const lines = ['', 'Merge decisions:'];
637
+ for (const item of changed.slice(0, 10)) {
638
+ const merge = item.merge_report || {};
639
+ const details = [
640
+ merge.classification ? `class=${merge.classification}` : '',
641
+ merge.scaffold_replaced ? 'scaffold replaced' : '',
642
+ merge.human_content_preserved ? 'human preserved' : '',
643
+ merge.context_prep_removed ? 'context-prep removed' : '',
644
+ Array.isArray(merge.critical_placeholders) && merge.critical_placeholders.length > 0
645
+ ? `placeholders=${merge.critical_placeholders.length}`
646
+ : '',
647
+ ].filter(Boolean);
648
+ lines.push(`- ${item.path}: ${merge.strategy || 'unknown'}${details.length > 0 ? ` (${details.join(', ')})` : ''}`);
649
+ for (const warning of Array.isArray(merge.warnings) ? merge.warnings.slice(0, 2) : []) {
650
+ lines.push(` warning: ${warning}`);
651
+ }
652
+ }
653
+ if (changed.length > 10) {
654
+ lines.push(`- ... ${changed.length - 10} more doc merge decision${changed.length - 10 === 1 ? '' : 's'}`);
655
+ }
656
+ return lines;
657
+ }
658
+
556
659
  function formatAnalyzeProjectPostWriteValidation(validation) {
557
660
  if (!validation) {
558
661
  return [];
@@ -592,6 +695,7 @@ function formatAnalyzeProjectReviewPlan({ writePlan, reviewPath, snapshot, writt
592
695
  for (const item of writePlan || []) {
593
696
  lines.push(`- ${item.path}: ${item.action}${item.reason ? ` (${item.reason})` : ''}`);
594
697
  }
698
+ lines.push(...formatAnalyzeProjectMergeSummary(writePlan));
595
699
  lines.push('', 'Final diff:');
596
700
  lines.push(...formatAnalyzeProjectDiffPreview(writePlan || []));
597
701
  lines.push('', 'Confirmation required before writing.');
@@ -617,6 +721,7 @@ function formatAnalyzeProjectApplyReport(report = {}) {
617
721
  `Proposal manifest: ${artifacts.manifest || 'none'}`,
618
722
  `Write manifest: ${writeManifest.path || 'none'}`,
619
723
  ].filter(Boolean);
724
+ lines.push(...formatAnalyzeProjectMergeSummary(report.write_plan));
620
725
  lines.push(...formatAnalyzeProjectPostWriteValidation(report.post_write_validation));
621
726
  return `${lines.join('\n')}\n`;
622
727
  }
@@ -2819,6 +2924,10 @@ async function runAnalyzeProject(repoRoot, options = {}) {
2819
2924
  });
2820
2925
  }
2821
2926
 
2927
+ const recovery = buildAnalyzeProjectEvidenceRecovery(repoRoot, error, report, {
2928
+ ...options,
2929
+ provider,
2930
+ });
2822
2931
  let validationManifest = null;
2823
2932
  try {
2824
2933
  validationManifest = writeAnalyzeProjectValidationManifest(repoRoot, {
@@ -2827,6 +2936,7 @@ async function runAnalyzeProject(repoRoot, options = {}) {
2827
2936
  command: 'ai analyze-project',
2828
2937
  runId: auditRunId,
2829
2938
  now: options.now,
2939
+ recovery,
2830
2940
  retry: {
2831
2941
  attempts: providerAttempts.length,
2832
2942
  max_retries: maxRetries,
@@ -2850,11 +2960,31 @@ async function runAnalyzeProject(repoRoot, options = {}) {
2850
2960
  validation: validationManifest,
2851
2961
  },
2852
2962
  });
2853
- throw enhanceAnalyzeProjectAnalysisError(error, {
2963
+ const enhancedError = enhanceAnalyzeProjectAnalysisError(error, {
2854
2964
  validationManifest,
2855
2965
  repairManifest: attemptRepairManifest,
2856
2966
  retryManifest,
2967
+ recovery,
2968
+ translator: progressTranslator,
2857
2969
  });
2970
+ if (options.json === true) {
2971
+ process.stdout.write(`${JSON.stringify({
2972
+ schema_version: 1,
2973
+ kind: 'quiver-analyze-project-error',
2974
+ ok: false,
2975
+ error: {
2976
+ code: enhancedError.code || null,
2977
+ message: error.message,
2978
+ },
2979
+ recovery,
2980
+ manifests: {
2981
+ repair: attemptRepairManifest,
2982
+ retry: retryManifest,
2983
+ validation: validationManifest,
2984
+ },
2985
+ }, null, 2)}\n`);
2986
+ }
2987
+ throw enhancedError;
2858
2988
  }
2859
2989
  }
2860
2990
  const completedReport = {