@llm-dev-ops/agentics-cli 2.1.5 → 2.3.0

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 (76) hide show
  1. package/dist/pipeline/auto-chain.d.ts +73 -0
  2. package/dist/pipeline/auto-chain.d.ts.map +1 -1
  3. package/dist/pipeline/auto-chain.js +525 -38
  4. package/dist/pipeline/auto-chain.js.map +1 -1
  5. package/dist/pipeline/phase2/phases/prompt-generator.d.ts.map +1 -1
  6. package/dist/pipeline/phase2/phases/prompt-generator.js +53 -6
  7. package/dist/pipeline/phase2/phases/prompt-generator.js.map +1 -1
  8. package/dist/pipeline/phase2/schemas.d.ts +10 -10
  9. package/dist/pipeline/phase4/phases/http-server-generator.d.ts +12 -0
  10. package/dist/pipeline/phase4/phases/http-server-generator.d.ts.map +1 -1
  11. package/dist/pipeline/phase4/phases/http-server-generator.js +92 -25
  12. package/dist/pipeline/phase4/phases/http-server-generator.js.map +1 -1
  13. package/dist/pipeline/phase5-build/phase5-build-coordinator.d.ts.map +1 -1
  14. package/dist/pipeline/phase5-build/phase5-build-coordinator.js +44 -0
  15. package/dist/pipeline/phase5-build/phase5-build-coordinator.js.map +1 -1
  16. package/dist/pipeline/phase5-build/phases/post-generation-validator.d.ts +75 -0
  17. package/dist/pipeline/phase5-build/phases/post-generation-validator.d.ts.map +1 -0
  18. package/dist/pipeline/phase5-build/phases/post-generation-validator.js +728 -0
  19. package/dist/pipeline/phase5-build/phases/post-generation-validator.js.map +1 -0
  20. package/dist/pipeline/phase5-build/types.d.ts +1 -1
  21. package/dist/pipeline/phase5-build/types.d.ts.map +1 -1
  22. package/dist/pipeline/types.d.ts +84 -0
  23. package/dist/pipeline/types.d.ts.map +1 -1
  24. package/dist/pipeline/types.js +43 -1
  25. package/dist/pipeline/types.js.map +1 -1
  26. package/dist/synthesis/consensus-svg.d.ts +19 -0
  27. package/dist/synthesis/consensus-svg.d.ts.map +1 -0
  28. package/dist/synthesis/consensus-svg.js +95 -0
  29. package/dist/synthesis/consensus-svg.js.map +1 -0
  30. package/dist/synthesis/consensus-tiers.d.ts +99 -0
  31. package/dist/synthesis/consensus-tiers.d.ts.map +1 -0
  32. package/dist/synthesis/consensus-tiers.js +285 -0
  33. package/dist/synthesis/consensus-tiers.js.map +1 -0
  34. package/dist/synthesis/domain-labor-classifier.d.ts +101 -0
  35. package/dist/synthesis/domain-labor-classifier.d.ts.map +1 -0
  36. package/dist/synthesis/domain-labor-classifier.js +312 -0
  37. package/dist/synthesis/domain-labor-classifier.js.map +1 -0
  38. package/dist/synthesis/domain-unit-registry.d.ts +59 -0
  39. package/dist/synthesis/domain-unit-registry.d.ts.map +1 -0
  40. package/dist/synthesis/domain-unit-registry.js +294 -0
  41. package/dist/synthesis/domain-unit-registry.js.map +1 -0
  42. package/dist/synthesis/financial-claim-extractor.d.ts +52 -0
  43. package/dist/synthesis/financial-claim-extractor.d.ts.map +1 -0
  44. package/dist/synthesis/financial-claim-extractor.js +351 -0
  45. package/dist/synthesis/financial-claim-extractor.js.map +1 -0
  46. package/dist/synthesis/financial-consistency-rules.d.ts +66 -0
  47. package/dist/synthesis/financial-consistency-rules.d.ts.map +1 -0
  48. package/dist/synthesis/financial-consistency-rules.js +432 -0
  49. package/dist/synthesis/financial-consistency-rules.js.map +1 -0
  50. package/dist/synthesis/financial-consistency-runner.d.ts +73 -0
  51. package/dist/synthesis/financial-consistency-runner.d.ts.map +1 -0
  52. package/dist/synthesis/financial-consistency-runner.js +131 -0
  53. package/dist/synthesis/financial-consistency-runner.js.map +1 -0
  54. package/dist/synthesis/forbidden-spin-phrases.d.ts +32 -0
  55. package/dist/synthesis/forbidden-spin-phrases.d.ts.map +1 -0
  56. package/dist/synthesis/forbidden-spin-phrases.js +84 -0
  57. package/dist/synthesis/forbidden-spin-phrases.js.map +1 -0
  58. package/dist/synthesis/phase-gate-thresholds.d.ts +30 -0
  59. package/dist/synthesis/phase-gate-thresholds.d.ts.map +1 -0
  60. package/dist/synthesis/phase-gate-thresholds.js +34 -0
  61. package/dist/synthesis/phase-gate-thresholds.js.map +1 -0
  62. package/dist/synthesis/prompts/index.d.ts.map +1 -1
  63. package/dist/synthesis/prompts/index.js +22 -0
  64. package/dist/synthesis/prompts/index.js.map +1 -1
  65. package/dist/synthesis/simulation-artifact-generator.d.ts.map +1 -1
  66. package/dist/synthesis/simulation-artifact-generator.js +89 -1
  67. package/dist/synthesis/simulation-artifact-generator.js.map +1 -1
  68. package/dist/synthesis/simulation-renderers.d.ts +105 -2
  69. package/dist/synthesis/simulation-renderers.d.ts.map +1 -1
  70. package/dist/synthesis/simulation-renderers.js +1056 -92
  71. package/dist/synthesis/simulation-renderers.js.map +1 -1
  72. package/dist/synthesis/unit-economics-loader.d.ts +71 -0
  73. package/dist/synthesis/unit-economics-loader.d.ts.map +1 -0
  74. package/dist/synthesis/unit-economics-loader.js +200 -0
  75. package/dist/synthesis/unit-economics-loader.js.map +1 -0
  76. package/package.json +1 -1
@@ -0,0 +1,432 @@
1
+ /**
2
+ * ADR-PIPELINE-067: Financial Consistency Rules (FCR-001..009)
3
+ *
4
+ * Pure functions over the output of financial-claim-extractor + an optional
5
+ * unit-economics manifest. Each rule returns zero or more Violation objects.
6
+ *
7
+ * Rule IDs:
8
+ * FCR-001 Same scope + same kind across documents ⇒ numeric ranges must overlap
9
+ * FCR-002 Pilot investment MUST be ≤ full-program investment
10
+ * FCR-003 Phase-1 range MUST be a subset of full-program range
11
+ * FCR-004 Every currency claim MUST have a non-unscoped scope
12
+ * FCR-005 Timeline claims for the same scope MUST match within ±1 week
13
+ * FCR-006 Savings + investment for the same scope MUST yield the ROI stated
14
+ * FCR-007 When unit-economics manifest exists, top-line figures match ±1%
15
+ * FCR-008 Pilot savings × (enterprise/pilot units) MUST equal enterprise savings ±5%
16
+ * FCR-009 At most one "headline" figure per document
17
+ */
18
+ import { findForbiddenSpinPhrases } from './forbidden-spin-phrases.js';
19
+ // ============================================================================
20
+ // Helpers
21
+ // ============================================================================
22
+ function anchorValue(claim) {
23
+ if (claim.pointValue !== undefined)
24
+ return claim.pointValue;
25
+ if (claim.rangeLow !== undefined)
26
+ return claim.rangeLow;
27
+ return 0;
28
+ }
29
+ function rangeOf(claim) {
30
+ if (claim.rangeLow !== undefined && claim.rangeHigh !== undefined) {
31
+ return [claim.rangeLow, claim.rangeHigh];
32
+ }
33
+ const v = claim.pointValue ?? 0;
34
+ return [v, v];
35
+ }
36
+ function rangesOverlap(a, b) {
37
+ return a[0] <= b[1] && b[0] <= a[1];
38
+ }
39
+ function isCurrencyClaim(c) {
40
+ return c.unit === 'USD';
41
+ }
42
+ function byKey(items, key) {
43
+ const out = new Map();
44
+ for (const item of items) {
45
+ const k = key(item);
46
+ const list = out.get(k) ?? [];
47
+ list.push(item);
48
+ out.set(k, list);
49
+ }
50
+ return out;
51
+ }
52
+ /**
53
+ * Two scopes are considered "same" for FCR-001 when they match exactly,
54
+ * or when both map to the pilot/phase-1 concept.
55
+ */
56
+ function canonicalScope(scope) {
57
+ if (scope === 'phase-1')
58
+ return 'pilot';
59
+ return scope;
60
+ }
61
+ // ============================================================================
62
+ // FCR-001 — Same scope + same kind across documents ⇒ ranges must overlap
63
+ // ============================================================================
64
+ function ruleFcr001(claims) {
65
+ const violations = [];
66
+ const currency = claims.filter(isCurrencyClaim);
67
+ const grouped = byKey(currency, c => `${canonicalScope(c.scope)}|${c.kind}`);
68
+ for (const [key, group] of grouped) {
69
+ if (group.length < 2)
70
+ continue;
71
+ const byDoc = byKey(group, c => c.document);
72
+ if (byDoc.size < 2)
73
+ continue;
74
+ // Compare each pair of documents' widest range.
75
+ const docEntries = Array.from(byDoc.entries()).map(([doc, list]) => {
76
+ const lows = [];
77
+ const highs = [];
78
+ for (const c of list) {
79
+ const [lo, hi] = rangeOf(c);
80
+ lows.push(lo);
81
+ highs.push(hi);
82
+ }
83
+ return {
84
+ document: doc,
85
+ low: Math.min(...lows),
86
+ high: Math.max(...highs),
87
+ claims: list,
88
+ };
89
+ });
90
+ for (let i = 0; i < docEntries.length; i++) {
91
+ for (let j = i + 1; j < docEntries.length; j++) {
92
+ const a = docEntries[i];
93
+ const b = docEntries[j];
94
+ if (!rangesOverlap([a.low, a.high], [b.low, b.high])) {
95
+ violations.push({
96
+ ruleId: 'FCR-001',
97
+ severity: 'error',
98
+ message: `[${key}] ${a.document} [$${a.low.toLocaleString()}–$${a.high.toLocaleString()}] does not overlap with ${b.document} [$${b.low.toLocaleString()}–$${b.high.toLocaleString()}]`,
99
+ claims: [...a.claims, ...b.claims],
100
+ suggestedFix: 'Reconcile figures — either widen the scope label on one side or relabel the divergent figure with the correct scope.',
101
+ });
102
+ }
103
+ }
104
+ }
105
+ }
106
+ return violations;
107
+ }
108
+ // ============================================================================
109
+ // FCR-002 — Pilot investment ≤ full-program investment
110
+ // FCR-003 — Phase-1 range MUST be a subset of full-program range
111
+ // ============================================================================
112
+ function ruleFcr002and003(claims) {
113
+ const violations = [];
114
+ const investments = claims.filter(c => isCurrencyClaim(c) && c.kind === 'investment');
115
+ const pilots = investments.filter(c => c.scope === 'pilot' || c.scope === 'phase-1');
116
+ const fulls = investments.filter(c => c.scope === 'full-program');
117
+ if (pilots.length === 0 || fulls.length === 0)
118
+ return violations;
119
+ const fullHigh = Math.max(...fulls.map(c => rangeOf(c)[1]));
120
+ // FCR-002 — pilot must not exceed the full-program ceiling.
121
+ for (const pilot of pilots) {
122
+ const [pLow] = rangeOf(pilot);
123
+ if (pLow > fullHigh) {
124
+ violations.push({
125
+ ruleId: 'FCR-002',
126
+ severity: 'error',
127
+ message: `pilot investment ${pilot.rawText} exceeds full-program ceiling $${fullHigh.toLocaleString()}`,
128
+ claims: [pilot, ...fulls],
129
+ suggestedFix: 'Lower the pilot figure or correct the full-program range.',
130
+ });
131
+ }
132
+ }
133
+ // FCR-003 — the same numeric range must not appear with different scope
134
+ // labels across documents. This catches the OPERA regression where the
135
+ // executive summary labels $2.7M–$4.1M as (pilot) while the decision memo
136
+ // labels the identical range as (full-program).
137
+ const rangesApproxEqual = (a, b) => {
138
+ const [alo, ahi] = rangeOf(a);
139
+ const [blo, bhi] = rangeOf(b);
140
+ const loDelta = Math.abs(alo - blo) / Math.max(1, Math.max(alo, blo));
141
+ const hiDelta = Math.abs(ahi - bhi) / Math.max(1, Math.max(ahi, bhi));
142
+ return loDelta <= 0.1 && hiDelta <= 0.1;
143
+ };
144
+ for (const pilot of pilots) {
145
+ for (const full of fulls) {
146
+ if (pilot.document === full.document)
147
+ continue;
148
+ if (!rangesApproxEqual(pilot, full))
149
+ continue;
150
+ violations.push({
151
+ ruleId: 'FCR-003',
152
+ severity: 'error',
153
+ message: `${pilot.document} declares ${pilot.rawText} (${pilot.scope}) but ${full.document} labels the same range as (full-program)`,
154
+ claims: [pilot, full],
155
+ suggestedFix: "Relabel the pilot figure to '(full program)' if it covers the whole program, or split into distinct pilot + full-program lines.",
156
+ });
157
+ }
158
+ }
159
+ return violations;
160
+ }
161
+ // ============================================================================
162
+ // FCR-004 — Every currency claim MUST have a non-unscoped scope
163
+ // ============================================================================
164
+ function ruleFcr004(claims) {
165
+ const unscoped = claims.filter(c => isCurrencyClaim(c) && c.scope === 'unscoped' && !c.tagged);
166
+ if (unscoped.length === 0)
167
+ return [];
168
+ // One violation per claim so callers can map it to a file:line
169
+ return unscoped.map(claim => ({
170
+ ruleId: 'FCR-004',
171
+ severity: 'error',
172
+ message: `${claim.document} line ${claim.line}: ${claim.rawText} has no scope label`,
173
+ claims: [claim],
174
+ suggestedFix: "Append a scope label in parens — e.g. '(pilot)' or '(full program)' — or add an HTML fcv:scope= tag.",
175
+ }));
176
+ }
177
+ // ============================================================================
178
+ // FCR-005 — Timeline claims for the same scope match within ±1 week
179
+ // ============================================================================
180
+ const WEEK_IN_WEEKS = 1;
181
+ function timelineToWeeks(c) {
182
+ const v = c.pointValue ?? 0;
183
+ if (c.unit === 'weeks')
184
+ return v;
185
+ if (c.unit === 'months')
186
+ return v * 4.34524;
187
+ if (c.unit === 'years')
188
+ return v * 52;
189
+ return v;
190
+ }
191
+ function ruleFcr005(claims) {
192
+ const violations = [];
193
+ const timelines = claims.filter(c => c.kind === 'timeline' && c.scope !== 'unscoped');
194
+ const grouped = byKey(timelines, c => canonicalScope(c.scope));
195
+ for (const [scope, group] of grouped) {
196
+ if (group.length < 2)
197
+ continue;
198
+ const byDoc = byKey(group, c => c.document);
199
+ if (byDoc.size < 2)
200
+ continue;
201
+ const weeksByDoc = Array.from(byDoc.entries()).map(([doc, list]) => ({
202
+ document: doc,
203
+ weeks: Math.max(...list.map(timelineToWeeks)),
204
+ claims: list,
205
+ }));
206
+ for (let i = 0; i < weeksByDoc.length; i++) {
207
+ for (let j = i + 1; j < weeksByDoc.length; j++) {
208
+ const a = weeksByDoc[i];
209
+ const b = weeksByDoc[j];
210
+ if (Math.abs(a.weeks - b.weeks) > WEEK_IN_WEEKS) {
211
+ violations.push({
212
+ ruleId: 'FCR-005',
213
+ severity: 'error',
214
+ message: `[${scope}] timeline mismatch: ${a.document} says ${Math.round(a.weeks)} weeks, ${b.document} says ${Math.round(b.weeks)} weeks`,
215
+ claims: [...a.claims, ...b.claims],
216
+ suggestedFix: 'Align timelines or split into distinct scopes (pilot vs. full program).',
217
+ });
218
+ }
219
+ }
220
+ }
221
+ }
222
+ return violations;
223
+ }
224
+ // ============================================================================
225
+ // FCR-006 — Savings ÷ investment ≈ ROI for the same scope (WARN)
226
+ // ============================================================================
227
+ function ruleFcr006(claims) {
228
+ const violations = [];
229
+ const byDoc = byKey(claims, c => c.document);
230
+ for (const [doc, docClaims] of byDoc) {
231
+ const investments = docClaims.filter(c => isCurrencyClaim(c) && c.kind === 'investment');
232
+ const savings = docClaims.filter(c => isCurrencyClaim(c) && c.kind === 'savings');
233
+ const rois = docClaims.filter(c => c.kind === 'roi' && c.unit === 'percent');
234
+ if (investments.length === 0 || savings.length === 0 || rois.length === 0)
235
+ continue;
236
+ // Use the largest investment and savings in this document.
237
+ const topInvest = investments.reduce((a, b) => (anchorValue(a) >= anchorValue(b) ? a : b));
238
+ const topSavings = savings.reduce((a, b) => (anchorValue(a) >= anchorValue(b) ? a : b));
239
+ const topRoi = rois.reduce((a, b) => ((a.pointValue ?? 0) >= (b.pointValue ?? 0) ? a : b));
240
+ const investVal = anchorValue(topInvest);
241
+ const savingsVal = anchorValue(topSavings);
242
+ if (investVal <= 0)
243
+ continue;
244
+ const computed = (savingsVal / investVal) * 100;
245
+ const stated = topRoi.pointValue ?? 0;
246
+ if (Math.abs(computed - stated) / Math.max(1, stated) > 0.5) {
247
+ violations.push({
248
+ ruleId: 'FCR-006',
249
+ severity: 'warn',
250
+ message: `${doc}: savings $${savingsVal.toLocaleString()} ÷ investment $${investVal.toLocaleString()} ≈ ${Math.round(computed)}% but document states ROI of ${stated}%`,
251
+ claims: [topInvest, topSavings, topRoi],
252
+ suggestedFix: 'Restate the ROI line or the underlying savings/investment figures so they reconcile.',
253
+ });
254
+ }
255
+ }
256
+ return violations;
257
+ }
258
+ // ============================================================================
259
+ // FCR-007 — Match unit-economics manifest within ±1%
260
+ // ============================================================================
261
+ function ruleFcr007(claims, manifest) {
262
+ if (!manifest)
263
+ return [];
264
+ const tol = 0.01;
265
+ const violations = [];
266
+ const savings = claims.filter(c => isCurrencyClaim(c) && c.kind === 'savings');
267
+ const enterpriseSavings = savings.filter(c => c.scope === 'full-program');
268
+ const pilotSavings = savings.filter(c => c.scope === 'pilot' || c.scope === 'phase-1');
269
+ const checkAgainst = (printed, target, label) => {
270
+ for (const claim of printed) {
271
+ const [lo, hi] = rangeOf(claim);
272
+ const value = (lo + hi) / 2;
273
+ const delta = Math.abs(value - target) / Math.max(1, target);
274
+ if (delta > tol) {
275
+ violations.push({
276
+ ruleId: 'FCR-007',
277
+ severity: 'error',
278
+ message: `${claim.document} ${label} ${claim.rawText} deviates from unit-economics.json ($${target.toLocaleString()}) by ${(delta * 100).toFixed(1)}% (tolerance ±1%)`,
279
+ claims: [claim],
280
+ suggestedFix: 'Regenerate the executive document or correct the unit-economics manifest so the two agree.',
281
+ });
282
+ }
283
+ }
284
+ };
285
+ checkAgainst(enterpriseSavings, manifest.annual_extrapolated_savings_usd, 'enterprise savings');
286
+ checkAgainst(pilotSavings, manifest.annual_measured_savings_usd, 'pilot savings');
287
+ return violations;
288
+ }
289
+ // ============================================================================
290
+ // FCR-008 — Pilot × scope-ratio ≈ enterprise savings within ±5%
291
+ // ============================================================================
292
+ function ruleFcr008(claims, manifest) {
293
+ if (!manifest)
294
+ return [];
295
+ if (manifest.annual_measured_savings_usd <= 0)
296
+ return [];
297
+ const tol = 0.05;
298
+ const violations = [];
299
+ const manifestRatio = manifest.annual_extrapolated_savings_usd / manifest.annual_measured_savings_usd;
300
+ const savings = claims.filter(c => isCurrencyClaim(c) && c.kind === 'savings');
301
+ const byDoc = byKey(savings, c => c.document);
302
+ for (const [doc, docSavings] of byDoc) {
303
+ const pilot = docSavings.find(c => c.scope === 'pilot' || c.scope === 'phase-1');
304
+ const full = docSavings.find(c => c.scope === 'full-program');
305
+ if (!pilot || !full)
306
+ continue;
307
+ const pilotVal = anchorValue(pilot);
308
+ const fullVal = anchorValue(full);
309
+ if (pilotVal <= 0)
310
+ continue;
311
+ const ratio = fullVal / pilotVal;
312
+ const delta = Math.abs(ratio - manifestRatio) / Math.max(0.01, manifestRatio);
313
+ if (delta > tol) {
314
+ violations.push({
315
+ ruleId: 'FCR-008',
316
+ severity: 'error',
317
+ message: `${doc}: pilot→enterprise ratio ${ratio.toFixed(1)}× deviates from manifest scope ratio ${manifestRatio.toFixed(1)}× by ${(delta * 100).toFixed(1)}% (tolerance ±5%)`,
318
+ claims: [pilot, full],
319
+ suggestedFix: 'Align the printed figures with the manifest scope ratio or widen the extrapolation method explanation.',
320
+ });
321
+ }
322
+ }
323
+ return violations;
324
+ }
325
+ // ============================================================================
326
+ // FCR-009 — At most one headline figure per document (WARN)
327
+ // ============================================================================
328
+ function ruleFcr009(claims) {
329
+ const violations = [];
330
+ const byDoc = byKey(claims, c => c.document);
331
+ for (const [doc, docClaims] of byDoc) {
332
+ const headlines = docClaims.filter(c => isCurrencyClaim(c) && c.kind === 'savings' && c.scope === 'full-program');
333
+ if (headlines.length <= 1)
334
+ continue;
335
+ // Collapse identical numbers (same anchor) before flagging — a doc that
336
+ // states "$30M/yr" twice isn't a problem, two *different* $30M and $4.1M
337
+ // headline figures is.
338
+ const distinct = new Set(headlines.map(c => Math.round(anchorValue(c))));
339
+ if (distinct.size <= 1)
340
+ continue;
341
+ violations.push({
342
+ ruleId: 'FCR-009',
343
+ severity: 'warn',
344
+ message: `${doc} has ${distinct.size} distinct full-program headline savings figures: ${[...distinct].map(v => '$' + v.toLocaleString()).join(' and ')}`,
345
+ claims: headlines,
346
+ suggestedFix: 'Pick one headline savings figure and demote the others to a pilot/phase-1 scope or a sensitivity range.',
347
+ });
348
+ }
349
+ return violations;
350
+ }
351
+ function ruleFcr010(documents, consensus) {
352
+ if (!consensus || consensus.tier !== 'contested')
353
+ return [];
354
+ const violations = [];
355
+ for (const doc of documents) {
356
+ const findings = findForbiddenSpinPhrases(doc.content);
357
+ if (findings.length === 0)
358
+ continue;
359
+ for (const f of findings) {
360
+ const claim = {
361
+ document: doc.document,
362
+ section: '(spin scan)',
363
+ kind: 'investment',
364
+ scope: 'unscoped',
365
+ unit: 'USD',
366
+ rawText: f.rawText,
367
+ line: f.line,
368
+ tagged: false,
369
+ };
370
+ violations.push({
371
+ ruleId: 'FCR-010',
372
+ severity: 'error',
373
+ message: `${doc.document} line ${f.line}: forbidden spin phrase "${f.rawText}" — ${f.note} (consensus is contested at agreement ${consensus.agreementLevelPct}%, precision ${consensus.precisionConfidencePct}%)`,
374
+ claims: [claim],
375
+ suggestedFix: 'Remove the phrase or relabel the document — under contested consensus the executive narrative must NOT minimize dissent.',
376
+ });
377
+ }
378
+ }
379
+ return violations;
380
+ }
381
+ export function runConsistencyRules(input) {
382
+ const { claims, manifest = null, documents = [], consensus = null } = input;
383
+ return [
384
+ ...ruleFcr001(claims),
385
+ ...ruleFcr002and003(claims),
386
+ ...ruleFcr004(claims),
387
+ ...ruleFcr005(claims),
388
+ ...ruleFcr006(claims),
389
+ ...ruleFcr007(claims, manifest),
390
+ ...ruleFcr008(claims, manifest),
391
+ ...ruleFcr009(claims),
392
+ ...ruleFcr010(documents, consensus),
393
+ ];
394
+ }
395
+ // Exported for unit tests so individual rules can be exercised in isolation.
396
+ export const __internal = {
397
+ ruleFcr001,
398
+ ruleFcr002and003,
399
+ ruleFcr004,
400
+ ruleFcr005,
401
+ ruleFcr006,
402
+ ruleFcr007,
403
+ ruleFcr008,
404
+ ruleFcr009,
405
+ ruleFcr010,
406
+ };
407
+ // Back-compat alias for callers that only need the counts.
408
+ export function countViolations(vs) {
409
+ let errors = 0;
410
+ let warnings = 0;
411
+ for (const v of vs) {
412
+ if (v.severity === 'error')
413
+ errors++;
414
+ else
415
+ warnings++;
416
+ }
417
+ return { errors, warnings };
418
+ }
419
+ // Keep a helper so the runner can prefix per-document warnings easily.
420
+ export function violationsByDocument(vs) {
421
+ const out = new Map();
422
+ for (const v of vs) {
423
+ for (const c of v.claims) {
424
+ const list = out.get(c.document) ?? [];
425
+ if (!list.includes(v))
426
+ list.push(v);
427
+ out.set(c.document, list);
428
+ }
429
+ }
430
+ return out;
431
+ }
432
+ //# sourceMappingURL=financial-consistency-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"financial-consistency-rules.js","sourceRoot":"","sources":["../../src/synthesis/financial-consistency-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * ADR-PIPELINE-067: Financial Consistency Runner
3
+ *
4
+ * Orchestrates the extract → rules → report pipeline. Writes a structured
5
+ * violations report to the run directory, prepends a warning header to any
6
+ * affected markdown document, and escalates to a hard failure under
7
+ * AGENTICS_STRICT_FCV=true.
8
+ */
9
+ import { type FinancialClaim, type FinancialClaimDocument } from './financial-claim-extractor.js';
10
+ import { type Violation } from './financial-consistency-rules.js';
11
+ import type { UnitEconomics } from '../pipeline/types.js';
12
+ import type { ConsensusSnapshot } from './consensus-tiers.js';
13
+ export interface InputDocument {
14
+ readonly kind: FinancialClaimDocument;
15
+ readonly path: string;
16
+ readonly content: string;
17
+ }
18
+ export interface ConsistencyReport {
19
+ readonly run_id: string;
20
+ readonly generated_at: string;
21
+ readonly passed: boolean;
22
+ readonly strict: boolean;
23
+ readonly totals: {
24
+ errors: number;
25
+ warnings: number;
26
+ };
27
+ readonly violations: readonly ReportViolation[];
28
+ readonly documents_scanned: number;
29
+ readonly claims_extracted: number;
30
+ }
31
+ export interface ReportViolation {
32
+ readonly rule_id: string;
33
+ readonly severity: 'error' | 'warn';
34
+ readonly message: string;
35
+ readonly suggested_fix?: string;
36
+ readonly claims: readonly ReportClaim[];
37
+ }
38
+ export interface ReportClaim {
39
+ readonly document: FinancialClaimDocument;
40
+ readonly section: string;
41
+ readonly kind: string;
42
+ readonly scope: string;
43
+ readonly line: number;
44
+ readonly rawText: string;
45
+ }
46
+ export declare class FinancialConsistencyError extends Error {
47
+ readonly code: string;
48
+ constructor(message: string, code?: string);
49
+ }
50
+ export interface RunOptions {
51
+ readonly documents: readonly InputDocument[];
52
+ readonly runDir: string;
53
+ readonly runId?: string;
54
+ readonly manifest?: UnitEconomics | null;
55
+ /** Optional consensus snapshot — required for FCR-010 (ADR-PIPELINE-071). */
56
+ readonly consensus?: ConsensusSnapshot | null;
57
+ /** Override for testing. Defaults to AGENTICS_STRICT_FCV env check. */
58
+ readonly strict?: boolean;
59
+ /** When true, write affected documents back with a warning header. */
60
+ readonly annotateDocuments?: boolean;
61
+ }
62
+ export interface RunResult {
63
+ readonly report: ConsistencyReport;
64
+ readonly reportPath: string;
65
+ readonly violations: readonly Violation[];
66
+ readonly claims: readonly FinancialClaim[];
67
+ }
68
+ /**
69
+ * Run the extractor + rules against a set of documents and write the report.
70
+ * Returns the structured result so callers can log, annotate, or branch.
71
+ */
72
+ export declare function runConsistencyCheck(options: RunOptions): RunResult;
73
+ //# sourceMappingURL=financial-consistency-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"financial-consistency-runner.d.ts","sourceRoot":"","sources":["../../src/synthesis/financial-consistency-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC5B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;aACL,IAAI;gBAArC,OAAO,EAAE,MAAM,EAAkB,IAAI,SAAiB;CAInE;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACzC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC9C,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;CAC5C;AAmCD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,CAqFlE"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * ADR-PIPELINE-067: Financial Consistency Runner
3
+ *
4
+ * Orchestrates the extract → rules → report pipeline. Writes a structured
5
+ * violations report to the run directory, prepends a warning header to any
6
+ * affected markdown document, and escalates to a hard failure under
7
+ * AGENTICS_STRICT_FCV=true.
8
+ */
9
+ import * as fs from 'node:fs';
10
+ import * as path from 'node:path';
11
+ import { extractClaims, } from './financial-claim-extractor.js';
12
+ import { runConsistencyRules, countViolations, } from './financial-consistency-rules.js';
13
+ import { loadUnitEconomics } from './unit-economics-loader.js';
14
+ export class FinancialConsistencyError extends Error {
15
+ code;
16
+ constructor(message, code = 'ECLI-SYN-067') {
17
+ super(`${code}: ${message}`);
18
+ this.code = code;
19
+ this.name = 'FinancialConsistencyError';
20
+ }
21
+ }
22
+ function toReportViolation(v) {
23
+ return {
24
+ rule_id: v.ruleId,
25
+ severity: v.severity,
26
+ message: v.message,
27
+ ...(v.suggestedFix ? { suggested_fix: v.suggestedFix } : {}),
28
+ claims: v.claims.map(c => ({
29
+ document: c.document,
30
+ section: c.section,
31
+ kind: c.kind,
32
+ scope: c.scope,
33
+ line: c.line,
34
+ rawText: c.rawText,
35
+ })),
36
+ };
37
+ }
38
+ function buildWarningHeader(docViolations) {
39
+ const totals = countViolations(docViolations);
40
+ if (totals.errors === 0 && totals.warnings === 0)
41
+ return '';
42
+ const lines = [
43
+ `> ⚠️ **Financial consistency:** ${totals.errors} error${totals.errors === 1 ? '' : 's'}, ${totals.warnings} warning${totals.warnings === 1 ? '' : 's'} — see \`financial-consistency.report.json\`.`,
44
+ ];
45
+ for (const v of docViolations.slice(0, 3)) {
46
+ lines.push(`> - ${v.ruleId} (${v.severity}): ${v.message}`);
47
+ }
48
+ if (docViolations.length > 3) {
49
+ lines.push(`> - …and ${docViolations.length - 3} more`);
50
+ }
51
+ lines.push('');
52
+ return lines.join('\n');
53
+ }
54
+ /**
55
+ * Run the extractor + rules against a set of documents and write the report.
56
+ * Returns the structured result so callers can log, annotate, or branch.
57
+ */
58
+ export function runConsistencyCheck(options) {
59
+ const { documents, runDir, runId = path.basename(runDir), manifest = null, annotateDocuments = true, } = options;
60
+ const strict = options.strict ?? process.env['AGENTICS_STRICT_FCV'] === 'true';
61
+ // 1. Extract claims across all documents.
62
+ const claims = [];
63
+ for (const doc of documents) {
64
+ claims.push(...extractClaims(doc.content, doc.kind));
65
+ }
66
+ // 2. Load the manifest if the caller didn't pre-supply one.
67
+ const resolvedManifest = manifest ?? loadUnitEconomics(runDir).manifest;
68
+ // 3. Run rules. Pass through consensus + raw document bodies so FCR-010
69
+ // (ADR-PIPELINE-071) can scan for forbidden spin phrases on contested
70
+ // runs without re-reading the markdown.
71
+ const ruleDocuments = documents.map(d => ({ document: d.kind, content: d.content }));
72
+ const violations = runConsistencyRules({
73
+ claims,
74
+ manifest: resolvedManifest,
75
+ documents: ruleDocuments,
76
+ consensus: options.consensus ?? null,
77
+ });
78
+ const totals = countViolations(violations);
79
+ const passed = totals.errors === 0;
80
+ // 4. Build and write the report.
81
+ const report = {
82
+ run_id: runId,
83
+ generated_at: new Date().toISOString(),
84
+ passed,
85
+ strict,
86
+ totals,
87
+ violations: violations.map(toReportViolation),
88
+ documents_scanned: documents.length,
89
+ claims_extracted: claims.length,
90
+ };
91
+ const reportPath = path.join(runDir, 'financial-consistency.report.json');
92
+ try {
93
+ fs.mkdirSync(runDir, { recursive: true });
94
+ fs.writeFileSync(reportPath, JSON.stringify(report, null, 2) + '\n', 'utf-8');
95
+ }
96
+ catch {
97
+ // Report write is best-effort; don't block the pipeline on an I/O failure.
98
+ }
99
+ // 5. Optionally annotate affected documents in place.
100
+ if (annotateDocuments && violations.length > 0) {
101
+ const byDoc = new Map();
102
+ for (const v of violations) {
103
+ for (const c of v.claims) {
104
+ const list = byDoc.get(c.document) ?? [];
105
+ if (!list.includes(v))
106
+ list.push(v);
107
+ byDoc.set(c.document, list);
108
+ }
109
+ }
110
+ for (const doc of documents) {
111
+ const docViolations = byDoc.get(doc.kind);
112
+ if (!docViolations || docViolations.length === 0)
113
+ continue;
114
+ const header = buildWarningHeader(docViolations);
115
+ if (!header)
116
+ continue;
117
+ try {
118
+ fs.writeFileSync(doc.path, header + '\n' + doc.content, 'utf-8');
119
+ }
120
+ catch {
121
+ // annotate is best-effort
122
+ }
123
+ }
124
+ }
125
+ // 6. Escalate on errors when strict.
126
+ if (!passed && strict) {
127
+ throw new FinancialConsistencyError(`${totals.errors} error-severity violation${totals.errors === 1 ? '' : 's'} across ${documents.length} documents`);
128
+ }
129
+ return { report, reportPath, violations, claims };
130
+ }
131
+ //# sourceMappingURL=financial-consistency-runner.js.map