@jaimevalasek/aioson 1.30.1 → 1.33.1

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 (136) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +19 -6
  3. package/docs/design-previews/cognitive-core-ui-auth.html +95 -0
  4. package/docs/design-previews/cognitive-core-ui-kanban.html +231 -0
  5. package/docs/design-previews/cognitive-core-ui-list-detail.html +174 -0
  6. package/docs/design-previews/cognitive-core-ui-preview.css +1315 -0
  7. package/docs/design-previews/cognitive-core-ui-settings.html +142 -0
  8. package/docs/design-previews/cognitive-core-ui-website.html +190 -1009
  9. package/docs/design-previews/cognitive-core-ui.html +281 -463
  10. package/docs/design-previews/index.html +83 -31
  11. package/docs/en/5-reference/cli-reference.md +1 -1
  12. package/docs/pt/5-referencia/comandos-cli.md +1 -1
  13. package/docs/pt/5-referencia/harness-retro.md +2 -1
  14. package/package.json +1 -1
  15. package/src/cli.js +38 -21
  16. package/src/commands/classify.js +389 -327
  17. package/src/commands/harness-retro-promote.js +387 -0
  18. package/src/commands/prototype-check.js +163 -0
  19. package/src/commands/verify-implementation.js +428 -0
  20. package/src/commands/workflow-next.js +222 -9
  21. package/src/constants.js +569 -511
  22. package/src/lib/retro/retro-render.js +10 -1
  23. package/src/lib/retro/retro-sources.js +45 -27
  24. package/src/lib/retro/verification-reports.js +230 -0
  25. package/src/runtime-store.js +13 -9
  26. package/src/verification/evidence-bundle.js +251 -0
  27. package/src/verification/ledger-store.js +221 -0
  28. package/src/verification/path-policy.js +74 -0
  29. package/src/verification/policy-engine.js +95 -0
  30. package/src/verification/prompt-package.js +314 -0
  31. package/src/verification/redaction.js +77 -0
  32. package/src/verification/report-parser.js +132 -0
  33. package/src/verification/report-store.js +97 -0
  34. package/src/verification/result.js +16 -0
  35. package/src/verification/runners/index.js +319 -0
  36. package/src/verification/runtime-telemetry.js +144 -0
  37. package/src/verification/schema.js +276 -0
  38. package/src/verification/source-discovery.js +153 -0
  39. package/template/.aioson/agents/analyst.md +9 -6
  40. package/template/.aioson/agents/briefing-refiner.md +22 -0
  41. package/template/.aioson/agents/briefing.md +69 -12
  42. package/template/.aioson/agents/design-hybrid-forge.md +18 -14
  43. package/template/.aioson/agents/dev.md +23 -10
  44. package/template/.aioson/agents/deyvin.md +3 -2
  45. package/template/.aioson/agents/product.md +15 -11
  46. package/template/.aioson/agents/qa.md +13 -4
  47. package/template/.aioson/agents/scope-check.md +19 -5
  48. package/template/.aioson/agents/sheldon.md +4 -3
  49. package/template/.aioson/agents/ux-ui.md +3 -2
  50. package/template/.aioson/docs/feature-expansion-taxonomy.md +31 -3
  51. package/template/.aioson/docs/play/README.md +2 -0
  52. package/template/.aioson/docs/play/agent-usage-guide.md +7 -1
  53. package/template/.aioson/docs/play/app-compatibility-guide.md +6 -1
  54. package/template/.aioson/docs/play/auth-services-and-testing.md +16 -1
  55. package/template/.aioson/docs/play/manifest-and-runtime.md +23 -0
  56. package/template/.aioson/docs/prototype-contract.md +81 -0
  57. package/template/.aioson/skills/design/aurora-command-ui/SKILL.md +266 -243
  58. package/template/.aioson/skills/design/aurora-command-ui/references/art-direction.md +293 -293
  59. package/template/.aioson/skills/design/aurora-command-ui/references/components.md +827 -827
  60. package/template/.aioson/skills/design/aurora-command-ui/references/dashboards.md +250 -250
  61. package/template/.aioson/skills/design/aurora-command-ui/references/design-tokens.md +585 -585
  62. package/template/.aioson/skills/design/aurora-command-ui/references/motion.md +365 -365
  63. package/template/.aioson/skills/design/aurora-command-ui/references/patterns.md +485 -482
  64. package/template/.aioson/skills/design/aurora-command-ui/references/websites.md +386 -387
  65. package/template/.aioson/skills/design/bold-editorial-ui/SKILL.md +228 -205
  66. package/template/.aioson/skills/design/bold-editorial-ui/references/art-direction.md +338 -338
  67. package/template/.aioson/skills/design/bold-editorial-ui/references/components.md +977 -977
  68. package/template/.aioson/skills/design/bold-editorial-ui/references/dashboards.md +218 -218
  69. package/template/.aioson/skills/design/bold-editorial-ui/references/design-tokens.md +326 -326
  70. package/template/.aioson/skills/design/bold-editorial-ui/references/motion.md +461 -461
  71. package/template/.aioson/skills/design/bold-editorial-ui/references/patterns.md +293 -293
  72. package/template/.aioson/skills/design/bold-editorial-ui/references/websites.md +352 -352
  73. package/template/.aioson/skills/design/clean-saas-ui/SKILL.md +233 -210
  74. package/template/.aioson/skills/design/clean-saas-ui/references/art-direction.md +319 -319
  75. package/template/.aioson/skills/design/clean-saas-ui/references/components.md +365 -365
  76. package/template/.aioson/skills/design/clean-saas-ui/references/dashboards.md +196 -196
  77. package/template/.aioson/skills/design/clean-saas-ui/references/design-tokens.md +244 -244
  78. package/template/.aioson/skills/design/clean-saas-ui/references/motion.md +235 -235
  79. package/template/.aioson/skills/design/clean-saas-ui/references/patterns.md +215 -215
  80. package/template/.aioson/skills/design/clean-saas-ui/references/websites.md +295 -295
  81. package/template/.aioson/skills/design/cognitive-core-ui/SKILL.md +239 -203
  82. package/template/.aioson/skills/design/cognitive-core-ui/references/art-direction.md +339 -339
  83. package/template/.aioson/skills/design/cognitive-core-ui/references/components.md +417 -407
  84. package/template/.aioson/skills/design/cognitive-core-ui/references/dashboards.md +289 -272
  85. package/template/.aioson/skills/design/cognitive-core-ui/references/design-tokens.md +525 -524
  86. package/template/.aioson/skills/design/cognitive-core-ui/references/motion.md +279 -279
  87. package/template/.aioson/skills/design/cognitive-core-ui/references/patterns.md +355 -289
  88. package/template/.aioson/skills/design/cognitive-core-ui/references/websites.md +443 -437
  89. package/template/.aioson/skills/design/glassmorphism-ui/SKILL.md +245 -222
  90. package/template/.aioson/skills/design/glassmorphism-ui/references/art-direction.md +159 -159
  91. package/template/.aioson/skills/design/glassmorphism-ui/references/components.md +498 -498
  92. package/template/.aioson/skills/design/glassmorphism-ui/references/dashboards.md +236 -236
  93. package/template/.aioson/skills/design/glassmorphism-ui/references/design-tokens.md +274 -274
  94. package/template/.aioson/skills/design/glassmorphism-ui/references/motion.md +355 -355
  95. package/template/.aioson/skills/design/glassmorphism-ui/references/patterns.md +198 -198
  96. package/template/.aioson/skills/design/glassmorphism-ui/references/websites.md +307 -307
  97. package/template/.aioson/skills/design/interface-design/SKILL.md +68 -47
  98. package/template/.aioson/skills/design/interface-design/references/components-and-states.md +105 -105
  99. package/template/.aioson/skills/design/interface-design/references/design-directions.md +101 -101
  100. package/template/.aioson/skills/design/interface-design/references/handoff-and-quality.md +92 -71
  101. package/template/.aioson/skills/design/interface-design/references/intent-and-domain.md +74 -74
  102. package/template/.aioson/skills/design/interface-design/references/tokens-and-depth.md +173 -173
  103. package/template/.aioson/skills/design/neo-brutalist-ui/SKILL.md +236 -213
  104. package/template/.aioson/skills/design/neo-brutalist-ui/references/art-direction.md +228 -228
  105. package/template/.aioson/skills/design/neo-brutalist-ui/references/components.md +855 -855
  106. package/template/.aioson/skills/design/neo-brutalist-ui/references/dashboards.md +334 -334
  107. package/template/.aioson/skills/design/neo-brutalist-ui/references/design-tokens.md +342 -342
  108. package/template/.aioson/skills/design/neo-brutalist-ui/references/motion.md +286 -286
  109. package/template/.aioson/skills/design/neo-brutalist-ui/references/patterns.md +458 -458
  110. package/template/.aioson/skills/design/neo-brutalist-ui/references/websites.md +723 -723
  111. package/template/.aioson/skills/design/premium-command-center-ui/SKILL.md +83 -62
  112. package/template/.aioson/skills/design/premium-command-center-ui/references/operations.md +74 -74
  113. package/template/.aioson/skills/design/premium-command-center-ui/references/patterns.md +116 -116
  114. package/template/.aioson/skills/design/premium-command-center-ui/references/validation.md +47 -47
  115. package/template/.aioson/skills/design/premium-command-center-ui/references/visual-system.md +215 -215
  116. package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -31
  117. package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +94 -66
  118. package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +366 -366
  119. package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -150
  120. package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -270
  121. package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -189
  122. package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +161 -161
  123. package/template/.aioson/skills/design/warm-craft-ui/SKILL.md +232 -209
  124. package/template/.aioson/skills/design/warm-craft-ui/references/art-direction.md +324 -324
  125. package/template/.aioson/skills/design/warm-craft-ui/references/components.md +508 -508
  126. package/template/.aioson/skills/design/warm-craft-ui/references/dashboards.md +223 -223
  127. package/template/.aioson/skills/design/warm-craft-ui/references/design-tokens.md +374 -374
  128. package/template/.aioson/skills/design/warm-craft-ui/references/motion.md +356 -356
  129. package/template/.aioson/skills/design/warm-craft-ui/references/patterns.md +288 -288
  130. package/template/.aioson/skills/design/warm-craft-ui/references/websites.md +289 -289
  131. package/template/.aioson/skills/process/briefing-expansion-scout/SKILL.md +25 -3
  132. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +5 -3
  133. package/template/.aioson/skills/process/design-hybrid-forge/references/external-source-ingestion.md +89 -0
  134. package/template/.aioson/skills/process/product-scope-expansion/SKILL.md +29 -2
  135. package/template/.aioson/skills/process/prototype-forge/SKILL.md +92 -0
  136. package/template/.aioson/skills/process/sheldon-expansion-audit/SKILL.md +23 -2
@@ -0,0 +1,428 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * aioson verify:implementation — deterministic local implementation verification pilot.
5
+ *
6
+ * Pilot modes:
7
+ * aioson verify:implementation . --feature=<slug> --prepare-ledger --json
8
+ * aioson verify:implementation . --feature=<slug> --check-ledger --json
9
+ * aioson verify:implementation . --feature=<slug> --build-prompt --json
10
+ * aioson verify:implementation . --feature=<slug> --check-report=<path> --policy=strict --json
11
+ * aioson verify:implementation . --feature=<slug> --tool=<codex|claude|opencode> --json
12
+ *
13
+ * This command prepares, validates, and can optionally run a constrained clean
14
+ * auditor. It does not claim final correctness and does not replace QA.
15
+ */
16
+
17
+ const fs = require('node:fs/promises');
18
+
19
+ const {
20
+ validateFeatureSlug,
21
+ resolveProjectRoot,
22
+ resolveInsideRoot
23
+ } = require('../verification/path-policy');
24
+ const { normalizePolicy, makeError } = require('../verification/result');
25
+ const { discoverSourceArtifacts } = require('../verification/source-discovery');
26
+ const {
27
+ prepareLedger,
28
+ checkLedger
29
+ } = require('../verification/ledger-store');
30
+ const { buildEvidenceBundle } = require('../verification/evidence-bundle');
31
+ const { buildAndWritePromptPackage } = require('../verification/prompt-package');
32
+ const { parseVerificationReport } = require('../verification/report-parser');
33
+ const { applyPolicy } = require('../verification/policy-engine');
34
+ const {
35
+ normalizeRunnerTool,
36
+ normalizeRunnerModel,
37
+ runnerLimits,
38
+ runAuditorTool
39
+ } = require('../verification/runners');
40
+ const {
41
+ runnerRunStem,
42
+ writeVerificationRunFile,
43
+ promoteLatestReport,
44
+ systemInconclusiveReport
45
+ } = require('../verification/report-store');
46
+ const { recordVerificationTelemetry } = require('../verification/runtime-telemetry');
47
+
48
+ const BAR = '━'.repeat(42);
49
+
50
+ function hasMode(options, mode) {
51
+ return Boolean(options && options[mode]);
52
+ }
53
+
54
+ function detectMode(options) {
55
+ const modes = [
56
+ 'prepare-ledger',
57
+ 'check-ledger',
58
+ 'build-prompt',
59
+ 'check-report'
60
+ ].filter((mode) => hasMode(options, mode));
61
+ if (options && options.tool) modes.push('run-tool');
62
+ if (modes.length === 0) return { ok: false, reason: 'missing_mode' };
63
+ if (modes.length > 1) return { ok: false, reason: 'multiple_modes', modes };
64
+ return { ok: true, mode: modes[0] };
65
+ }
66
+
67
+ function emit(result, options, logger) {
68
+ if (options.json) return result;
69
+ logger.log('');
70
+ logger.log(`Implementation verification — ${result.feature_slug || 'unknown'}`);
71
+ logger.log(BAR);
72
+ logger.log(`Status: ${result.ok ? 'ok' : 'blocked'}`);
73
+ if (result.reason) logger.log(`Reason: ${result.reason}`);
74
+ if (result.mode) logger.log(`Mode: ${result.mode}`);
75
+ if (result.ledger_path) logger.log(`Ledger: ${result.ledger_path}`);
76
+ if (result.prompt_path) logger.log(`Prompt: ${result.prompt_path}`);
77
+ if (result.raw_report_path) logger.log(`Raw report: ${result.raw_report_path}`);
78
+ if (result.report_path) logger.log(`Report: ${result.report_path}`);
79
+ if (result.tool) logger.log(`Tool: ${result.tool}`);
80
+ if (result.model) logger.log(`Model: ${result.model}`);
81
+ if (result.verdict) logger.log(`Verdict: ${result.verdict}`);
82
+ if (result.recommended_route) logger.log(`Route: ${result.recommended_route}`);
83
+ if (Array.isArray(result.missing_sections) && result.missing_sections.length) {
84
+ logger.log(`Missing sections: ${result.missing_sections.join(', ')}`);
85
+ }
86
+ if (Array.isArray(result.errors) && result.errors.length) {
87
+ logger.log(`Errors: ${result.errors.map((e) => `${e.field}:${e.reason}`).join(', ')}`);
88
+ }
89
+ logger.log('');
90
+ return result;
91
+ }
92
+
93
+ async function runPrepareLedger({ rootDir, slug, options }) {
94
+ const sourceArtifacts = await discoverSourceArtifacts(rootDir, slug);
95
+ const result = await prepareLedger(rootDir, slug, sourceArtifacts);
96
+ return {
97
+ mode: 'prepare-ledger',
98
+ ...result
99
+ };
100
+ }
101
+
102
+ async function runCheckLedger({ rootDir, slug }) {
103
+ const result = await checkLedger(rootDir, slug);
104
+ return {
105
+ mode: 'check-ledger',
106
+ ...result
107
+ };
108
+ }
109
+
110
+ async function runBuildPrompt({ rootDir, slug, policy, options }) {
111
+ const ledgerResult = await checkLedger(rootDir, slug);
112
+ if (!ledgerResult.ok) {
113
+ return {
114
+ mode: 'build-prompt',
115
+ ...ledgerResult,
116
+ ready_for_prompt: false
117
+ };
118
+ }
119
+ if (!ledgerResult.ready_for_prompt) {
120
+ return {
121
+ mode: 'build-prompt',
122
+ ok: false,
123
+ reason: 'ledger_not_ready_for_prompt',
124
+ feature_slug: slug,
125
+ ledger_path: ledgerResult.ledger_path,
126
+ missing_evidence: ledgerResult.missing_evidence || [],
127
+ ready_for_prompt: false
128
+ };
129
+ }
130
+
131
+ const sourceArtifacts = await discoverSourceArtifacts(rootDir, slug, ledgerResult.ledger);
132
+ const evidenceBundle = await buildEvidenceBundle(rootDir, slug, ledgerResult.ledger, sourceArtifacts, policy);
133
+ return {
134
+ mode: 'build-prompt',
135
+ ...(await buildAndWritePromptPackage({
136
+ rootDir,
137
+ slug,
138
+ policy,
139
+ ledger: ledgerResult.ledger,
140
+ evidenceBundle,
141
+ outPath: options.out || null
142
+ }))
143
+ };
144
+ }
145
+
146
+ function runnerFailureReason(status) {
147
+ if (status === 'timeout') return 'runner_timeout';
148
+ if (status === 'output_limit') return 'runner_output_limit';
149
+ if (status === 'spawn_error') return 'runner_spawn_error';
150
+ if (status === 'failed') return 'runner_failed';
151
+ return 'runner_inconclusive';
152
+ }
153
+
154
+ async function buildPromptForRunner({ rootDir, slug, policy, options }) {
155
+ const promptResult = await runBuildPrompt({ rootDir, slug, policy, options: { ...options, out: null } });
156
+ if (!promptResult.ok) return promptResult;
157
+ const safePrompt = resolveInsideRoot(rootDir, promptResult.prompt_path);
158
+ if (!safePrompt.ok) return safePrompt;
159
+ const promptText = await fs.readFile(safePrompt.path, 'utf8');
160
+ return {
161
+ ...promptResult,
162
+ prompt_absolute_path: safePrompt.path,
163
+ prompt_text: promptText
164
+ };
165
+ }
166
+
167
+ async function writeSystemRunnerReport({ rootDir, slug, policy, stem, runner, reason, summary, stderrPath = null }) {
168
+ const command = runner && runner.command ? runner.command : 'auditor runner';
169
+ const evidence = stderrPath
170
+ ? `Runner stderr was stored separately at ${stderrPath}; raw stderr is intentionally omitted from the latest verification report.`
171
+ : summary;
172
+ const markdown = systemInconclusiveReport({
173
+ slug,
174
+ policy,
175
+ summary,
176
+ command,
177
+ status: reason,
178
+ evidence
179
+ });
180
+ const runReport = await writeVerificationRunFile(rootDir, slug, stem, 'system-report.md', markdown);
181
+ const latest = await promoteLatestReport(rootDir, slug, markdown);
182
+ const parsed = await parseVerificationReport(rootDir, slug, latest.relative_path, policy);
183
+ const policyResult = parsed.ok
184
+ ? applyPolicy(parsed.report, policy)
185
+ : { verdict: 'INCONCLUSIVE', recommended_route: 'qa', blocking_findings_count: 0, policy, reason };
186
+ return {
187
+ ok: false,
188
+ reason,
189
+ verdict: policyResult.verdict,
190
+ recommended_route: policyResult.recommended_route,
191
+ blocking_findings_count: policyResult.blocking_findings_count,
192
+ report: parsed.ok ? parsed.report : null,
193
+ report_path: latest.relative_path,
194
+ run_report_path: runReport.relative_path
195
+ };
196
+ }
197
+
198
+ async function runToolAudit({ rootDir, slug, policy, options, spawnImpl }) {
199
+ const toolResult = normalizeRunnerTool(options.tool);
200
+ if (!toolResult.ok) {
201
+ return {
202
+ mode: 'run-tool',
203
+ ok: false,
204
+ verdict: 'INCONCLUSIVE',
205
+ recommended_route: 'qa',
206
+ ...toolResult
207
+ };
208
+ }
209
+ const modelResult = normalizeRunnerModel(options.model);
210
+ if (!modelResult.ok) {
211
+ return {
212
+ mode: 'run-tool',
213
+ ok: false,
214
+ verdict: 'INCONCLUSIVE',
215
+ recommended_route: 'qa',
216
+ tool: toolResult.tool,
217
+ ...modelResult
218
+ };
219
+ }
220
+
221
+ const prompt = await buildPromptForRunner({ rootDir, slug, policy, options });
222
+ if (!prompt.ok) {
223
+ return {
224
+ mode: 'run-tool',
225
+ ...prompt
226
+ };
227
+ }
228
+
229
+ const limits = runnerLimits(options);
230
+ const runner = await runAuditorTool({
231
+ rootDir,
232
+ tool: options.tool,
233
+ model: options.model,
234
+ promptPath: prompt.prompt_absolute_path,
235
+ promptText: prompt.prompt_text,
236
+ limits,
237
+ spawnImpl
238
+ });
239
+
240
+ if (!runner.ok && ['unsupported_tool', 'missing_tool', 'invalid_model', 'tool_not_found'].includes(runner.reason)) {
241
+ return {
242
+ mode: 'run-tool',
243
+ ok: false,
244
+ verdict: 'INCONCLUSIVE',
245
+ recommended_route: 'qa',
246
+ ...runner
247
+ };
248
+ }
249
+
250
+ const stem = runnerRunStem({ tool: runner.tool || options.tool, model: runner.model || options.model });
251
+ const raw = await writeVerificationRunFile(rootDir, slug, stem, 'raw.md', runner.stdout || '');
252
+ let stderrFile = null;
253
+ if (runner.stderr) {
254
+ stderrFile = await writeVerificationRunFile(rootDir, slug, stem, 'stderr.txt', runner.stderr);
255
+ }
256
+
257
+ const base = {
258
+ mode: 'run-tool',
259
+ feature_slug: slug,
260
+ policy,
261
+ tool: runner.tool,
262
+ model: runner.model,
263
+ prompt_path: prompt.prompt_path,
264
+ raw_report_path: raw.relative_path,
265
+ stderr_path: stderrFile ? stderrFile.relative_path : null,
266
+ runner: {
267
+ status: runner.status,
268
+ command: runner.command,
269
+ permission_mode: runner.permission_mode,
270
+ destructive_commands_allowed: runner.destructive_commands_allowed,
271
+ timeout_ms: runner.timeout_ms,
272
+ max_output_bytes: runner.max_output_bytes,
273
+ duration_ms: runner.duration_ms,
274
+ exit_code: runner.exit_code,
275
+ signal: runner.signal,
276
+ output_bytes: runner.output_bytes,
277
+ output_truncated: runner.output_truncated,
278
+ detected: runner.detected
279
+ }
280
+ };
281
+
282
+ if (!runner.ok) {
283
+ const reason = runnerFailureReason(runner.status);
284
+ return {
285
+ ...base,
286
+ ...(await writeSystemRunnerReport({
287
+ rootDir,
288
+ slug,
289
+ policy,
290
+ stem,
291
+ runner,
292
+ reason,
293
+ summary: `Auditor runner did not complete successfully: ${runner.status}.`,
294
+ stderrPath: stderrFile ? stderrFile.relative_path : null
295
+ }))
296
+ };
297
+ }
298
+
299
+ const parsed = await parseVerificationReport(rootDir, slug, raw.relative_path, policy);
300
+ if (!parsed.ok) {
301
+ return {
302
+ ...base,
303
+ parse_error: parsed,
304
+ ...(await writeSystemRunnerReport({
305
+ rootDir,
306
+ slug,
307
+ policy,
308
+ stem,
309
+ runner,
310
+ reason: 'invalid_runner_report',
311
+ summary: `Auditor output did not match the verification report contract: ${parsed.reason}.`,
312
+ stderrPath: stderrFile ? stderrFile.relative_path : null
313
+ }))
314
+ };
315
+ }
316
+
317
+ const latest = await promoteLatestReport(rootDir, slug, runner.stdout);
318
+ const machineJson = await writeVerificationRunFile(
319
+ rootDir,
320
+ slug,
321
+ stem,
322
+ 'report.json',
323
+ `${JSON.stringify(parsed.report, null, 2)}\n`
324
+ );
325
+ const policyResult = applyPolicy(parsed.report, policy);
326
+ return {
327
+ ...base,
328
+ ok: policyResult.verdict === 'PASS',
329
+ report_path: latest.relative_path,
330
+ report_json_path: machineJson.relative_path,
331
+ run_report_path: raw.relative_path,
332
+ report: parsed.report,
333
+ verdict: policyResult.verdict,
334
+ recommended_route: policyResult.recommended_route,
335
+ blocking_findings_count: policyResult.blocking_findings_count,
336
+ reason: policyResult.reason
337
+ };
338
+ }
339
+
340
+ async function runCheckReport({ rootDir, slug, policy, options }) {
341
+ const reportPath = options['check-report'];
342
+ if (reportPath === true || !reportPath) {
343
+ return makeError('missing_report_path', {
344
+ mode: 'check-report',
345
+ feature_slug: slug
346
+ });
347
+ }
348
+
349
+ const parsed = await parseVerificationReport(rootDir, slug, reportPath, policy);
350
+ if (!parsed.ok) {
351
+ return {
352
+ mode: 'check-report',
353
+ verdict: 'INCONCLUSIVE',
354
+ recommended_route: 'qa',
355
+ ...parsed
356
+ };
357
+ }
358
+
359
+ const policyResult = applyPolicy(parsed.report, policy);
360
+ return {
361
+ mode: 'check-report',
362
+ ok: policyResult.verdict === 'PASS',
363
+ feature_slug: slug,
364
+ report_path: parsed.report_path,
365
+ report: parsed.report,
366
+ verdict: policyResult.verdict,
367
+ recommended_route: policyResult.recommended_route,
368
+ blocking_findings_count: policyResult.blocking_findings_count,
369
+ policy: policyResult.policy,
370
+ reason: policyResult.reason
371
+ };
372
+ }
373
+
374
+ async function runVerifyImplementation({ args, options = {}, logger, spawnImpl }) {
375
+ const startedAt = Date.now();
376
+ const rootDir = resolveProjectRoot(process.cwd(), args && args[0] ? args[0] : '.');
377
+ const slugResult = validateFeatureSlug(options.feature || options.slug);
378
+ if (!slugResult.ok) {
379
+ return emit(makeError(slugResult.reason, {
380
+ mode: 'verify-implementation',
381
+ feature_slug: slugResult.feature_slug || null
382
+ }), options, logger);
383
+ }
384
+
385
+ const modeResult = detectMode(options);
386
+ if (!modeResult.ok) {
387
+ return emit(makeError(modeResult.reason, {
388
+ feature_slug: slugResult.feature_slug,
389
+ modes: modeResult.modes || []
390
+ }), options, logger);
391
+ }
392
+
393
+ const policy = normalizePolicy(options.policy || 'standard');
394
+ if (!policy) {
395
+ return emit(makeError('invalid_policy', {
396
+ feature_slug: slugResult.feature_slug,
397
+ policy: options.policy
398
+ }), options, logger);
399
+ }
400
+
401
+ const slug = slugResult.feature_slug;
402
+ let result;
403
+ if (modeResult.mode === 'prepare-ledger') {
404
+ result = await runPrepareLedger({ rootDir, slug, options });
405
+ } else if (modeResult.mode === 'check-ledger') {
406
+ result = await runCheckLedger({ rootDir, slug });
407
+ } else if (modeResult.mode === 'build-prompt') {
408
+ result = await runBuildPrompt({ rootDir, slug, policy, options });
409
+ } else if (modeResult.mode === 'check-report') {
410
+ result = await runCheckReport({ rootDir, slug, policy, options });
411
+ } else if (modeResult.mode === 'run-tool') {
412
+ result = await runToolAudit({ rootDir, slug, policy, options, spawnImpl });
413
+ }
414
+
415
+ const finalResult = {
416
+ feature_slug: slug,
417
+ policy,
418
+ ...result
419
+ };
420
+ finalResult.telemetry = await recordVerificationTelemetry(rootDir, finalResult, { startedAt });
421
+
422
+ return emit(finalResult, options, logger);
423
+ }
424
+
425
+ module.exports = {
426
+ runVerifyImplementation,
427
+ detectMode
428
+ };