create-agdf 0.14.1 → 0.14.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.
Files changed (112) hide show
  1. package/README.md +8 -2
  2. package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
  3. package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
  4. package/generated/plugins/agdf/meta/agdf-plugin.definition.json +6 -1
  5. package/generated/plugins/agdf/meta/copilot-payload-baseline.json +7 -0
  6. package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +6 -1
  7. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/local-validator.js +29 -17
  8. package/generated/plugins/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +50 -1
  9. package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
  10. package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
  11. package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +2 -1
  12. package/generated/plugins/agdf/submission/openai/availability.md +1 -1
  13. package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
  14. package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
  15. package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
  16. package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +771 -0
  17. package/generated/plugins/copilot/agdf/LICENSE +201 -0
  18. package/generated/plugins/copilot/agdf/meta/agdf-agent-router.md +129 -0
  19. package/generated/plugins/copilot/agdf/meta/agdf-constitution.md +329 -0
  20. package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +331 -0
  21. package/generated/plugins/copilot/agdf/meta/agdf-runtime-contract.md +16 -0
  22. package/generated/plugins/{agdf → copilot/agdf}/plugin.json +1 -1
  23. package/generated/plugins/copilot/agdf/runtime/agdf-local.js +18 -0
  24. package/generated/plugins/copilot/agdf/runtime/agdf-session-check.js +97 -0
  25. package/generated/plugins/copilot/agdf/runtime/create-agdf/NOTICE +10 -0
  26. package/generated/plugins/copilot/agdf/runtime/create-agdf/bin/agdf-validator.js +11 -0
  27. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +512 -0
  28. package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +331 -0
  29. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/command-registry.js +144 -0
  30. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +139 -0
  31. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/parse-args.js +173 -0
  32. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/runtime-context.js +83 -0
  33. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/validation-handlers.js +46 -0
  34. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/delivery-map.js +301 -0
  35. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +272 -0
  36. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +455 -0
  37. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/gate-policy.js +305 -0
  38. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/parent-reconciliation.js +284 -0
  39. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/required-files.js +9 -0
  40. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/run-state.js +217 -0
  41. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/shared.js +345 -0
  42. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-evaluation/verified-change.js +156 -0
  43. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/aggregate.js +18 -0
  44. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/gate-approval-validator.js +49 -0
  45. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/index.js +7 -0
  46. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/legacy-migration.js +95 -0
  47. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +265 -0
  48. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-repository.js +68 -0
  49. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-resolver.js +45 -0
  50. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/control-state/run-state-writer.js +97 -0
  51. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/candidate-policy.js +99 -0
  52. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +237 -0
  53. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/claude.js +35 -0
  54. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/codex.js +44 -0
  55. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/opencode.js +234 -0
  56. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/prompt.js +13 -0
  57. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/evaluators/protocol.js +13 -0
  58. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/claude.js +40 -0
  59. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/codex.js +38 -0
  60. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/generators/protocol.js +12 -0
  61. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +39 -0
  62. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/scoring.js +21 -0
  63. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +155 -0
  64. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +161 -0
  65. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/surfaces/capabilities.js +27 -0
  66. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/transports/read-only-guard.js +43 -0
  67. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/interaction-presentation.js +842 -0
  68. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/local-validator.js +239 -0
  69. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/plugin-provenance.js +255 -0
  70. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime/validator-application.js +40 -0
  71. package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/runtime-check-consent/contract.js +73 -0
  72. package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +6 -0
  73. package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +8 -0
  74. package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
  75. package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +6 -1
  76. package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +7 -0
  77. package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
  78. package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
  79. package/generated/submissions/openai/agdf/submission/openai/inventory.json +13 -9
  80. package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
  81. package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
  82. package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
  83. package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
  84. package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
  85. package/lib/installers/local-marketplace.js +112 -30
  86. package/lib/installers/plugin-installers.js +45 -9
  87. package/lib/public-plugin/copilot-profile.js +126 -0
  88. package/lib/release/version-coherence.js +4 -1
  89. package/lib/runtime/local-validator.js +29 -17
  90. package/lib/runtime/plugin-provenance.js +50 -1
  91. package/package.json +3 -2
  92. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-brownfield-analysis/SKILL.md +0 -0
  93. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-clean-implementation-review/SKILL.md +0 -0
  94. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-code-review/SKILL.md +0 -0
  95. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-delivery-closeout/SKILL.md +0 -0
  96. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-delivery-path-search/SKILL.md +0 -0
  97. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-gate-check/SKILL.md +0 -0
  98. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-interaction-locales.json +0 -0
  99. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-qa-gate/SKILL.md +0 -0
  100. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-release-or/SKILL.md +0 -0
  101. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-runtime-contract.md +0 -0
  102. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-task-plan-review/SKILL.md +0 -0
  103. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/agdf-ux-intent-definition/SKILL.md +0 -0
  104. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/closeout.md +0 -0
  105. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/context-graph.md +0 -0
  106. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/control-scaffold.md +0 -0
  107. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/gate-transition.md +0 -0
  108. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/interaction.md +0 -0
  109. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/modes.md +0 -0
  110. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/quality.md +0 -0
  111. /package/generated/plugins/{agdf → copilot/agdf}/copilot-skills/contracts/task-target-resolution.md +0 -0
  112. /package/generated/plugins/{agdf → copilot/agdf}/hooks/copilot-hooks.json +0 -0
@@ -0,0 +1,272 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { aggregate, resolveRuns, verifyLegacyProjection } from '../control-state/index.js';
4
+ import { doctorRequiredFiles } from './required-files.js';
5
+ import { analyzeDeliveryMap } from './delivery-map.js';
6
+ import { evaluateVerifiedChange } from './verified-change.js';
7
+ import { analyzeArtefactRoleConsistency, analyzeDurableGateArtefactConsistency, modeSliceDecision, readRunState, resolvedArtefactFile } from './run-state.js';
8
+ import { addFinding, allowNoActiveRuns, filled, hasFilledEvidenceRow, hasFilledTableRow, isPlaceholderValue, markdownSection, nonEmptyTableRows, parseBacklogSection, parseQualityContracts, readTargetFile, runSelectionRecovery, tableRows } from './shared.js';
9
+
10
+ export function evaluateDoctor(targetDir, selection = {}) {
11
+ if (selection.allActive) {
12
+ const selected = resolveRuns(targetDir, { allActive: true });
13
+ const runs = selected.runs.map((run) => ({
14
+ run_id: run.run_id,
15
+ report: evaluateDoctor(targetDir, { runId: run.run_id }),
16
+ }));
17
+ const status = selected.findings.length
18
+ ? "block"
19
+ : aggregate(
20
+ runs.map((item) => ({ run_id: item.run_id, status: item.report.status })),
21
+ { allowNoActiveRuns: allowNoActiveRuns(targetDir) },
22
+ ).status;
23
+ const findings = [
24
+ ...selected.findings.map((finding) => ({
25
+ ...finding,
26
+ severity: "block",
27
+ message: "Invalid canonical run entry.",
28
+ next_step: "Repair or remove the invalid run entry.",
29
+ })),
30
+ ...runs.flatMap((item) => item.report.findings.map((finding) => ({ ...finding, run_id: item.run_id }))),
31
+ ];
32
+ return {
33
+ schema_version: "1",
34
+ status,
35
+ checked_at: new Date().toISOString(),
36
+ target_dir: targetDir,
37
+ summary: {
38
+ findings: findings.length,
39
+ block: findings.filter((finding) => finding.severity === "block").length,
40
+ revise: findings.filter((finding) => finding.severity === "revise").length,
41
+ warn: findings.filter((finding) => finding.severity === "warn").length,
42
+ },
43
+ findings,
44
+ runs,
45
+ };
46
+ }
47
+ const findings = [];
48
+ let reconciliation;
49
+ const hasCanonicalRuns = existsSync(join(targetDir, ".agdf", "control", "runs"));
50
+ if (hasCanonicalRuns) {
51
+ const projection = verifyLegacyProjection(targetDir);
52
+ if (!["absent", "valid"].includes(projection.status)) {
53
+ addFinding(
54
+ findings,
55
+ "block",
56
+ "AGDF_LEGACY_PROJECTION_DRIFT",
57
+ `Legacy compatibility state is not a valid projection: ${projection.status}.`,
58
+ join(".agdf", "control", "AGDF_RUN.md"),
59
+ "Regenerate the explicit legacy projection or remove it after legacy consumers are retired.",
60
+ );
61
+ }
62
+ }
63
+ const missing = doctorRequiredFiles.filter(
64
+ (relativePath) => !(relativePath.endsWith("AGDF_RUN.md") && hasCanonicalRuns) && !existsSync(join(targetDir, relativePath)),
65
+ );
66
+
67
+ for (const relativePath of missing) {
68
+ const templatePath = join(dirname(relativePath), "templates", relativePath.split("/").at(-1));
69
+ const hasTemplate = existsSync(join(targetDir, templatePath));
70
+ addFinding(
71
+ findings,
72
+ "block",
73
+ "AGDF_CONTROL_FILE_MISSING",
74
+ hasTemplate
75
+ ? "Live control file is missing; only the template exists."
76
+ : "Required live control file is missing.",
77
+ relativePath,
78
+ "Run npx --yes @agdf/cli@latest init only when the repository should own durable AGDF control state or deterministic setup is explicitly needed.",
79
+ );
80
+ }
81
+
82
+ if (missing.length === 0) {
83
+ const selectedRunState = readRunState(targetDir, selection);
84
+ const runPath = selectedRunState.path;
85
+ const run = selectedRunState.content;
86
+
87
+ if (selectedRunState.resolution_error) {
88
+ addFinding(
89
+ findings,
90
+ "block",
91
+ selectedRunState.resolution_error.split(":")[0] || "AGDF_ACTIVE_RUN_UNRESOLVED",
92
+ `Run selection failed: ${selectedRunState.resolution_error}`,
93
+ runPath,
94
+ runSelectionRecovery(selection.target),
95
+ );
96
+ } else {
97
+ const currentGateLine = run.match(/^- current_gate:[^\S\r\n]*(.*)$/m)?.[1]?.trim() ?? "";
98
+ const nextActionLine = run.match(/^- next_allowed_action:[^\S\r\n]*(.*)$/m)?.[1]?.trim() ?? "";
99
+ const hasEvidence = hasFilledEvidenceRow(run);
100
+
101
+ if (isPlaceholderValue(currentGateLine)) {
102
+ addFinding(
103
+ findings,
104
+ "revise",
105
+ "AGDF_CURRENT_GATE_MISSING",
106
+ "The selected run state does not name the current gate.",
107
+ runPath,
108
+ "Set current_gate to the current delivery gate or none.",
109
+ );
110
+ }
111
+
112
+ if (isPlaceholderValue(nextActionLine)) {
113
+ addFinding(
114
+ findings,
115
+ "revise",
116
+ "AGDF_NEXT_ALLOWED_ACTION_MISSING",
117
+ "The selected run state does not state the next allowed action.",
118
+ runPath,
119
+ "Fill the next allowed action before asking an agent to continue delivery work.",
120
+ );
121
+ }
122
+
123
+ if (!hasEvidence) {
124
+ addFinding(
125
+ findings,
126
+ "warn",
127
+ "AGDF_EVIDENCE_EMPTY",
128
+ "The selected run state has no visible evidence row yet.",
129
+ runPath,
130
+ "Add at least one evidence row or explicitly document that no evidence exists yet.",
131
+ );
132
+ }
133
+ }
134
+
135
+ const backlogPath = join(".agdf", "control", "MASTER_BACKLOG.md");
136
+ const backlog = readTargetFile(targetDir, backlogPath);
137
+ parseBacklogSection(markdownSection(backlog, "Active Backlog"), findings, backlogPath);
138
+ parseBacklogSection(markdownSection(backlog, "Planned / Parking Lot"), findings, backlogPath);
139
+ const completedRows = tableRows(markdownSection(backlog, "Completed / Superseded Pointers"))
140
+ .slice(1)
141
+ .filter((cells) => cells.some((cell) => filled(cell)));
142
+ if (!hasFilledTableRow(backlog, /^P[0-9]/) && completedRows.length === 0) {
143
+ addFinding(
144
+ findings,
145
+ "warn",
146
+ "AGDF_BACKLOG_POINTER_EMPTY",
147
+ "MASTER_BACKLOG.md does not contain an active or planned work pointer.",
148
+ backlogPath,
149
+ "Add the active item or document that no governed delivery item is active.",
150
+ );
151
+ }
152
+
153
+ const sotPath = join(".agdf", "control", "SOT_REGISTRY.md");
154
+ const sot = readTargetFile(targetDir, sotPath);
155
+ if (!hasFilledTableRow(sot, /Product intent|Architecture|Runtime contracts|UX \/ user flows|Operations \/ release/)) {
156
+ addFinding(
157
+ findings,
158
+ "warn",
159
+ "AGDF_SOT_REGISTRY_EMPTY",
160
+ "SOT_REGISTRY.md has no filled primary source-of-truth row.",
161
+ sotPath,
162
+ "Assign one primary source of truth for at least the domains relevant to the next run.",
163
+ );
164
+ }
165
+
166
+ const activeDomains = new Map();
167
+ for (const cells of nonEmptyTableRows(sot)) {
168
+ const [domain, document, status] = cells;
169
+ if (!domain || !document || status !== "active") continue;
170
+ activeDomains.set(domain, (activeDomains.get(domain) ?? 0) + 1);
171
+ }
172
+ for (const [domain, count] of activeDomains.entries()) {
173
+ if (count > 1) {
174
+ addFinding(
175
+ findings,
176
+ "block",
177
+ "AGDF_PARALLEL_SOT",
178
+ `Domain has ${count} active source-of-truth rows: ${domain}.`,
179
+ sotPath,
180
+ "Keep exactly one active primary source of truth for this domain.",
181
+ );
182
+ }
183
+ }
184
+
185
+ const contextPath = join(".agdf", "control", "CONTEXT_GRAPH.md");
186
+ const contextGraph = readTargetFile(targetDir, contextPath);
187
+ if (contextGraph.includes("### CG-001 Example")) {
188
+ addFinding(
189
+ findings,
190
+ "warn",
191
+ "AGDF_CONTEXT_GRAPH_TEMPLATE_NODE",
192
+ "CONTEXT_GRAPH.md still contains the example node.",
193
+ contextPath,
194
+ "Remove the example or replace it with an evidenced node that has an exit criterion.",
195
+ );
196
+ }
197
+
198
+ const contractsPath = join(".agdf", "control", "AGENT_QUALITY_CONTRACTS.json");
199
+ try {
200
+ parseQualityContracts(readTargetFile(targetDir, contractsPath));
201
+ } catch (error) {
202
+ addFinding(
203
+ findings,
204
+ "block",
205
+ "AGDF_QUALITY_CONTRACTS_INVALID",
206
+ `AGENT_QUALITY_CONTRACTS.json is invalid: ${error.message}`,
207
+ contractsPath,
208
+ "Restore the generated contracts or fix the JSON contract schema.",
209
+ );
210
+ }
211
+
212
+ const runState = selectedRunState;
213
+ if (modeSliceDecision(runState) === "verified_change") {
214
+ const verifiedChange = evaluateVerifiedChange(targetDir, runState);
215
+ for (const finding of verifiedChange.findings) {
216
+ addFinding(findings, finding.severity, finding.code, finding.message, finding.path, finding.next_step);
217
+ }
218
+ }
219
+ for (const finding of analyzeDurableGateArtefactConsistency(runState)) {
220
+ addFinding(findings, finding.severity, finding.code, finding.message, finding.path, finding.next_step);
221
+ }
222
+ for (const finding of analyzeArtefactRoleConsistency(targetDir, runState)) {
223
+ addFinding(findings, finding.severity, finding.code, finding.message, finding.path, finding.next_step);
224
+ }
225
+ reconciliation = analyzeDeliveryMap(runState, {
226
+ loadRun: (runId) => readRunState(targetDir, { runId }),
227
+ resolveFile: (path) => resolvedArtefactFile(targetDir, path),
228
+ });
229
+ for (const finding of reconciliation.findings) {
230
+ addFinding(findings, finding.severity, finding.code, finding.message, finding.path, finding.next_step);
231
+ }
232
+ }
233
+
234
+ const severityRank = { block: 3, revise: 2, warn: 1 };
235
+ const maxSeverity = findings.reduce((max, finding) => Math.max(max, severityRank[finding.severity] ?? 0), 0);
236
+ const status = maxSeverity >= 3 ? "block" : maxSeverity === 2 ? "revise" : maxSeverity === 1 ? "warn" : "pass";
237
+
238
+ return {
239
+ schema_version: "1",
240
+ status,
241
+ checked_at: new Date().toISOString(),
242
+ target_dir: targetDir,
243
+ summary: {
244
+ findings: findings.length,
245
+ block: findings.filter((finding) => finding.severity === "block").length,
246
+ revise: findings.filter((finding) => finding.severity === "revise").length,
247
+ warn: findings.filter((finding) => finding.severity === "warn").length,
248
+ },
249
+ parent_reconciliation: reconciliation?.parent_reconciliation,
250
+ programme_aggregation: reconciliation?.programme_aggregation,
251
+ findings,
252
+ };
253
+ }
254
+
255
+ export function printDoctorReport(report, json, io = console) {
256
+ if (json) {
257
+ io.log(JSON.stringify(report, null, 2));
258
+ return;
259
+ }
260
+
261
+ io.log(`AGDF doctor: ${report.status}`);
262
+ io.log(`Checked: ${report.target_dir}`);
263
+ io.log(`Findings: ${report.summary.findings} (${report.summary.block} block, ${report.summary.revise} revise, ${report.summary.warn} warn)`);
264
+
265
+ for (const finding of report.findings) {
266
+ io.log("");
267
+ io.log(`[${finding.severity}] ${finding.code}`);
268
+ io.log(`Path: ${finding.path}`);
269
+ io.log(finding.message);
270
+ io.log(`Next step: ${finding.next_step}`);
271
+ }
272
+ }