@llm-dev-ops/agentics-cli 2.1.5 → 2.4.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.
- package/dist/pipeline/auto-chain.d.ts +190 -0
- package/dist/pipeline/auto-chain.d.ts.map +1 -1
- package/dist/pipeline/auto-chain.js +1571 -72
- package/dist/pipeline/auto-chain.js.map +1 -1
- package/dist/pipeline/phase2/phases/prompt-generator.d.ts.map +1 -1
- package/dist/pipeline/phase2/phases/prompt-generator.js +205 -12
- package/dist/pipeline/phase2/phases/prompt-generator.js.map +1 -1
- package/dist/pipeline/phase2/schemas.d.ts +10 -10
- package/dist/pipeline/phase4/phases/http-server-generator.d.ts +12 -0
- package/dist/pipeline/phase4/phases/http-server-generator.d.ts.map +1 -1
- package/dist/pipeline/phase4/phases/http-server-generator.js +92 -25
- package/dist/pipeline/phase4/phases/http-server-generator.js.map +1 -1
- package/dist/pipeline/phase4-5-pre-render/financial-model.d.ts +51 -0
- package/dist/pipeline/phase4-5-pre-render/financial-model.d.ts.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/financial-model.js +118 -0
- package/dist/pipeline/phase4-5-pre-render/financial-model.js.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/post-render-reconciler.d.ts +53 -0
- package/dist/pipeline/phase4-5-pre-render/post-render-reconciler.d.ts.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/post-render-reconciler.js +130 -0
- package/dist/pipeline/phase4-5-pre-render/post-render-reconciler.js.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/pre-render-coordinator.d.ts +47 -0
- package/dist/pipeline/phase4-5-pre-render/pre-render-coordinator.d.ts.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/pre-render-coordinator.js +105 -0
- package/dist/pipeline/phase4-5-pre-render/pre-render-coordinator.js.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/sector-baselines.d.ts +42 -0
- package/dist/pipeline/phase4-5-pre-render/sector-baselines.d.ts.map +1 -0
- package/dist/pipeline/phase4-5-pre-render/sector-baselines.js +117 -0
- package/dist/pipeline/phase4-5-pre-render/sector-baselines.js.map +1 -0
- package/dist/pipeline/phase5-build/phase5-build-coordinator.d.ts.map +1 -1
- package/dist/pipeline/phase5-build/phase5-build-coordinator.js +44 -0
- package/dist/pipeline/phase5-build/phase5-build-coordinator.js.map +1 -1
- package/dist/pipeline/phase5-build/phases/post-generation-validator.d.ts +75 -0
- package/dist/pipeline/phase5-build/phases/post-generation-validator.d.ts.map +1 -0
- package/dist/pipeline/phase5-build/phases/post-generation-validator.js +1068 -0
- package/dist/pipeline/phase5-build/phases/post-generation-validator.js.map +1 -0
- package/dist/pipeline/phase5-build/types.d.ts +1 -1
- package/dist/pipeline/phase5-build/types.d.ts.map +1 -1
- package/dist/pipeline/types.d.ts +87 -0
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +51 -1
- package/dist/pipeline/types.js.map +1 -1
- package/dist/synthesis/consensus-svg.d.ts +19 -0
- package/dist/synthesis/consensus-svg.d.ts.map +1 -0
- package/dist/synthesis/consensus-svg.js +95 -0
- package/dist/synthesis/consensus-svg.js.map +1 -0
- package/dist/synthesis/consensus-tiers.d.ts +99 -0
- package/dist/synthesis/consensus-tiers.d.ts.map +1 -0
- package/dist/synthesis/consensus-tiers.js +285 -0
- package/dist/synthesis/consensus-tiers.js.map +1 -0
- package/dist/synthesis/domain-labor-classifier.d.ts +101 -0
- package/dist/synthesis/domain-labor-classifier.d.ts.map +1 -0
- package/dist/synthesis/domain-labor-classifier.js +312 -0
- package/dist/synthesis/domain-labor-classifier.js.map +1 -0
- package/dist/synthesis/domain-unit-registry.d.ts +59 -0
- package/dist/synthesis/domain-unit-registry.d.ts.map +1 -0
- package/dist/synthesis/domain-unit-registry.js +320 -0
- package/dist/synthesis/domain-unit-registry.js.map +1 -0
- package/dist/synthesis/financial-claim-extractor.d.ts +72 -0
- package/dist/synthesis/financial-claim-extractor.d.ts.map +1 -0
- package/dist/synthesis/financial-claim-extractor.js +382 -0
- package/dist/synthesis/financial-claim-extractor.js.map +1 -0
- package/dist/synthesis/financial-consistency-rules.d.ts +70 -0
- package/dist/synthesis/financial-consistency-rules.d.ts.map +1 -0
- package/dist/synthesis/financial-consistency-rules.js +483 -0
- package/dist/synthesis/financial-consistency-rules.js.map +1 -0
- package/dist/synthesis/financial-consistency-runner.d.ts +73 -0
- package/dist/synthesis/financial-consistency-runner.d.ts.map +1 -0
- package/dist/synthesis/financial-consistency-runner.js +131 -0
- package/dist/synthesis/financial-consistency-runner.js.map +1 -0
- package/dist/synthesis/forbidden-spin-phrases.d.ts +32 -0
- package/dist/synthesis/forbidden-spin-phrases.d.ts.map +1 -0
- package/dist/synthesis/forbidden-spin-phrases.js +84 -0
- package/dist/synthesis/forbidden-spin-phrases.js.map +1 -0
- package/dist/synthesis/phase-gate-thresholds.d.ts +30 -0
- package/dist/synthesis/phase-gate-thresholds.d.ts.map +1 -0
- package/dist/synthesis/phase-gate-thresholds.js +34 -0
- package/dist/synthesis/phase-gate-thresholds.js.map +1 -0
- package/dist/synthesis/prompts/index.d.ts.map +1 -1
- package/dist/synthesis/prompts/index.js +22 -0
- package/dist/synthesis/prompts/index.js.map +1 -1
- package/dist/synthesis/roadmap-dates.d.ts +72 -0
- package/dist/synthesis/roadmap-dates.d.ts.map +1 -0
- package/dist/synthesis/roadmap-dates.js +203 -0
- package/dist/synthesis/roadmap-dates.js.map +1 -0
- package/dist/synthesis/simulation-artifact-generator.d.ts.map +1 -1
- package/dist/synthesis/simulation-artifact-generator.js +135 -1
- package/dist/synthesis/simulation-artifact-generator.js.map +1 -1
- package/dist/synthesis/simulation-renderers.d.ts +105 -2
- package/dist/synthesis/simulation-renderers.d.ts.map +1 -1
- package/dist/synthesis/simulation-renderers.js +1192 -123
- package/dist/synthesis/simulation-renderers.js.map +1 -1
- package/dist/synthesis/unit-economics-loader.d.ts +71 -0
- package/dist/synthesis/unit-economics-loader.d.ts.map +1 -0
- package/dist/synthesis/unit-economics-loader.js +200 -0
- package/dist/synthesis/unit-economics-loader.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-PIPELINE-067: Financial Claim Extractor
|
|
3
|
+
*
|
|
4
|
+
* Parses rendered executive markdown and returns a structured list of
|
|
5
|
+
* FinancialClaim records. Used by the cross-document consistency runner to
|
|
6
|
+
* compare dollar figures, timelines, and scope labels across documents.
|
|
7
|
+
*
|
|
8
|
+
* Pure functions. Regex-based — no LLM calls.
|
|
9
|
+
*
|
|
10
|
+
* Renderers can short-circuit extraction by emitting an HTML comment tag
|
|
11
|
+
* immediately before the figure:
|
|
12
|
+
*
|
|
13
|
+
* <!-- fcv:kind=investment scope=pilot -->
|
|
14
|
+
* **Pilot investment:** $1.0M–$1.4M
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* ADR-PIPELINE-073: Documents that MUST carry authoritative fcv tags on
|
|
18
|
+
* every money figure. Untagged money figures in these docs fire FCR-011.
|
|
19
|
+
* Other documents (narrative memos, agent output) continue to use
|
|
20
|
+
* proximity-based scope detection as a fallback.
|
|
21
|
+
*/
|
|
22
|
+
export const EXPECTS_TAGS = new Set([
|
|
23
|
+
'executive-summary',
|
|
24
|
+
'decision-memo',
|
|
25
|
+
'financial-analysis',
|
|
26
|
+
'roadmap',
|
|
27
|
+
'business-case',
|
|
28
|
+
]);
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Currency / money parsing
|
|
31
|
+
// ============================================================================
|
|
32
|
+
const CURRENCY_SUFFIX = {
|
|
33
|
+
K: 1_000,
|
|
34
|
+
M: 1_000_000,
|
|
35
|
+
B: 1_000_000_000,
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Parse a single currency token like "$1.2M", "$600K", "$1,200,000",
|
|
39
|
+
* "USD 1.2M", or "1.2 million dollars". Returns NaN when the input does not
|
|
40
|
+
* look like a currency amount.
|
|
41
|
+
*/
|
|
42
|
+
export function parseCurrency(token) {
|
|
43
|
+
const cleaned = token.trim().replace(/\s+/g, ' ');
|
|
44
|
+
// "$1.2M" / "$600K" / "$1.2B"
|
|
45
|
+
const suffixMatch = cleaned.match(/^\$?\s*([\d.]+)\s*([KMB])\b/i);
|
|
46
|
+
if (suffixMatch) {
|
|
47
|
+
const num = parseFloat(suffixMatch[1]);
|
|
48
|
+
const mult = CURRENCY_SUFFIX[suffixMatch[2].toUpperCase()] ?? 1;
|
|
49
|
+
if (!Number.isNaN(num))
|
|
50
|
+
return num * mult;
|
|
51
|
+
}
|
|
52
|
+
// "USD 1.2M"
|
|
53
|
+
const usdMatch = cleaned.match(/^USD\s*([\d.]+)\s*([KMB])?\b/i);
|
|
54
|
+
if (usdMatch) {
|
|
55
|
+
const num = parseFloat(usdMatch[1]);
|
|
56
|
+
const mult = usdMatch[2] ? (CURRENCY_SUFFIX[usdMatch[2].toUpperCase()] ?? 1) : 1;
|
|
57
|
+
if (!Number.isNaN(num))
|
|
58
|
+
return num * mult;
|
|
59
|
+
}
|
|
60
|
+
// "1.2 million dollars" / "600 thousand dollars" — check BEFORE plain match
|
|
61
|
+
// so the magnitude word is consumed before the bare number branch.
|
|
62
|
+
const spelledMatch = cleaned.match(/^([\d.]+)\s*(thousand|million|billion)\s*(?:dollars?|USD)?/i);
|
|
63
|
+
if (spelledMatch) {
|
|
64
|
+
const num = parseFloat(spelledMatch[1]);
|
|
65
|
+
const mults = { thousand: 1_000, million: 1_000_000, billion: 1_000_000_000 };
|
|
66
|
+
const mult = mults[spelledMatch[2].toLowerCase()] ?? 1;
|
|
67
|
+
if (!Number.isNaN(num))
|
|
68
|
+
return num * mult;
|
|
69
|
+
}
|
|
70
|
+
// "$1,200,000" or "$600,000" — bare number must have a $ prefix to avoid
|
|
71
|
+
// consuming the "1.2" in "1.2 million" before the spelled branch runs.
|
|
72
|
+
const plainMatch = cleaned.match(/^\$\s*([\d,]+(?:\.\d+)?)\b/);
|
|
73
|
+
if (plainMatch) {
|
|
74
|
+
const num = parseFloat(plainMatch[1].replace(/,/g, ''));
|
|
75
|
+
if (!Number.isNaN(num) && num > 0)
|
|
76
|
+
return num;
|
|
77
|
+
}
|
|
78
|
+
return NaN;
|
|
79
|
+
}
|
|
80
|
+
// Currency range: "$1.2M–$1.4M" / "$1.2M - $1.4M" / "$1.2M to $1.4M"
|
|
81
|
+
const CURRENCY_RANGE_RE = /\$[\d.,]+\s*[KMB]?(?:\s*(?:[-–—]|to)\s*\$?[\d.,]+\s*[KMB]?)?/gi;
|
|
82
|
+
// ============================================================================
|
|
83
|
+
// Scope label detection
|
|
84
|
+
// ============================================================================
|
|
85
|
+
const SCOPE_PATTERNS = [
|
|
86
|
+
{ re: /\b(?:pilot|phase[\s-]?1|first[\s-]phase)\b/i, scope: 'phase-1' },
|
|
87
|
+
{ re: /\bphase[\s-]?2\b/i, scope: 'phase-2' },
|
|
88
|
+
{ re: /\bphase[\s-]?3\b/i, scope: 'phase-3' },
|
|
89
|
+
{ re: /\b(?:full\s*(?:program|deployment|rollout|scale)|enterprise[\s-]wide|full[\s-]program)\b/i, scope: 'full-program' },
|
|
90
|
+
];
|
|
91
|
+
function detectScope(context) {
|
|
92
|
+
const lower = context.toLowerCase();
|
|
93
|
+
if (/\bpilot\b/.test(lower))
|
|
94
|
+
return 'pilot';
|
|
95
|
+
for (const { re, scope } of SCOPE_PATTERNS) {
|
|
96
|
+
if (re.test(context))
|
|
97
|
+
return scope;
|
|
98
|
+
}
|
|
99
|
+
return 'unscoped';
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Scope detection around a specific match index. Scans a ±WINDOW char
|
|
103
|
+
* window centered on the match and chooses the nearest scope keyword. This
|
|
104
|
+
* lets a single line like "$1.0M pilot, $2.7M–$4.1M full deployment"
|
|
105
|
+
* assign different scopes to each figure.
|
|
106
|
+
*/
|
|
107
|
+
function detectScopeNearIndex(context, matchStart, matchEnd) {
|
|
108
|
+
const WINDOW = 60;
|
|
109
|
+
const start = Math.max(0, matchStart - WINDOW);
|
|
110
|
+
const end = Math.min(context.length, matchEnd + WINDOW);
|
|
111
|
+
const window = context.slice(start, end);
|
|
112
|
+
const hits = [];
|
|
113
|
+
const scanners = [
|
|
114
|
+
{ re: /\bpilot\b/gi, scope: 'pilot' },
|
|
115
|
+
{ re: /\bphase[\s-]?1\b|first[\s-]phase/gi, scope: 'phase-1' },
|
|
116
|
+
{ re: /\bphase[\s-]?2\b/gi, scope: 'phase-2' },
|
|
117
|
+
{ re: /\bphase[\s-]?3\b/gi, scope: 'phase-3' },
|
|
118
|
+
{ re: /\b(?:full\s*(?:program|deployment|rollout|scale)|enterprise[\s-]wide|full[\s-]program)\b/gi, scope: 'full-program' },
|
|
119
|
+
];
|
|
120
|
+
for (const s of scanners) {
|
|
121
|
+
let m;
|
|
122
|
+
s.re.lastIndex = 0;
|
|
123
|
+
while ((m = s.re.exec(window)) !== null) {
|
|
124
|
+
const absIdx = start + m.index;
|
|
125
|
+
const distance = absIdx < matchStart ? matchStart - absIdx : absIdx - matchEnd;
|
|
126
|
+
hits.push({ scope: s.scope, distance });
|
|
127
|
+
if (m.index === s.re.lastIndex)
|
|
128
|
+
s.re.lastIndex++;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (hits.length === 0) {
|
|
132
|
+
// Fall back to a broader context scan — may return 'pilot' etc.
|
|
133
|
+
return detectScope(context);
|
|
134
|
+
}
|
|
135
|
+
hits.sort((a, b) => a.distance - b.distance);
|
|
136
|
+
return hits[0].scope;
|
|
137
|
+
}
|
|
138
|
+
const TAG_RE = /<!--\s*fcv:([^>]+?)\s*-->/;
|
|
139
|
+
/** Global flag for the extractor's inline-tag counting pass. */
|
|
140
|
+
const TAG_RE_G = /<!--\s*fcv:([^>]+?)\s*-->/g;
|
|
141
|
+
function parseTag(line) {
|
|
142
|
+
const m = line.match(TAG_RE);
|
|
143
|
+
if (!m)
|
|
144
|
+
return null;
|
|
145
|
+
const tag = {};
|
|
146
|
+
for (const pair of m[1].split(/\s+/)) {
|
|
147
|
+
const eq = pair.indexOf('=');
|
|
148
|
+
if (eq === -1)
|
|
149
|
+
continue;
|
|
150
|
+
const key = pair.slice(0, eq).trim();
|
|
151
|
+
const val = pair.slice(eq + 1).trim();
|
|
152
|
+
if (key === 'kind')
|
|
153
|
+
tag.kind = val;
|
|
154
|
+
else if (key === 'scope')
|
|
155
|
+
tag.scope = val;
|
|
156
|
+
else if (key === 'unit')
|
|
157
|
+
tag.unit = val;
|
|
158
|
+
else if (key === 'doc')
|
|
159
|
+
tag.doc = val;
|
|
160
|
+
}
|
|
161
|
+
return tag;
|
|
162
|
+
}
|
|
163
|
+
/** ADR-PIPELINE-073: count fcv tags in a document body. */
|
|
164
|
+
export function countFcvTags(body) {
|
|
165
|
+
const matches = body.match(TAG_RE_G);
|
|
166
|
+
return matches ? matches.length : 0;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* ADR-PIPELINE-073: emit an fcv HTML comment tag. Used by renderers.
|
|
170
|
+
* Exported here (not in simulation-renderers) so the extractor and the
|
|
171
|
+
* renderer speak the same grammar.
|
|
172
|
+
*/
|
|
173
|
+
export function fcvTag(kind, scope, doc) {
|
|
174
|
+
return `<!-- fcv:kind=${kind} scope=${scope} doc=${doc} -->`;
|
|
175
|
+
}
|
|
176
|
+
// ============================================================================
|
|
177
|
+
// Kind inference from surrounding prose
|
|
178
|
+
// ============================================================================
|
|
179
|
+
function detectKind(context, defaultKind) {
|
|
180
|
+
const lower = context.toLowerCase();
|
|
181
|
+
if (/\b(?:5[-\s]?year\s*)?npv\b/.test(lower))
|
|
182
|
+
return 'npv';
|
|
183
|
+
if (/\broi\b|return\s+on\s+investment/.test(lower))
|
|
184
|
+
return 'roi';
|
|
185
|
+
if (/\bsavings?\b|annual\s+(?:value|impact|benefit)/.test(lower))
|
|
186
|
+
return 'savings';
|
|
187
|
+
if (/\binvestment\b|\bcapex\b|\bcost\b|\bbudget\b|\bspend\b/.test(lower))
|
|
188
|
+
return 'investment';
|
|
189
|
+
return defaultKind;
|
|
190
|
+
}
|
|
191
|
+
// ============================================================================
|
|
192
|
+
// Section tracker — most-recent H1/H2/H3 heading
|
|
193
|
+
// ============================================================================
|
|
194
|
+
function updateSection(current, line) {
|
|
195
|
+
const m = line.match(/^(#{1,3})\s+(.*?)\s*$/);
|
|
196
|
+
if (!m)
|
|
197
|
+
return current;
|
|
198
|
+
return m[2].trim();
|
|
199
|
+
}
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// Entry point
|
|
202
|
+
// ============================================================================
|
|
203
|
+
/**
|
|
204
|
+
* Extract FinancialClaim records from a markdown document. The document name
|
|
205
|
+
* is recorded on every claim and becomes the primary key for
|
|
206
|
+
* cross-document rule evaluation.
|
|
207
|
+
*
|
|
208
|
+
* Scoping heuristic:
|
|
209
|
+
* 1. If an HTML fcv: tag precedes the figure (same line or prior line),
|
|
210
|
+
* use its declared kind/scope verbatim.
|
|
211
|
+
* 2. Otherwise scan a ±60 char window around the figure for scope words
|
|
212
|
+
* ("pilot", "phase 1", "full program", ...).
|
|
213
|
+
*/
|
|
214
|
+
export function extractClaims(markdown, document) {
|
|
215
|
+
const claims = [];
|
|
216
|
+
const lines = markdown.split(/\r?\n/);
|
|
217
|
+
let section = '(preamble)';
|
|
218
|
+
let pendingTag = null;
|
|
219
|
+
for (let i = 0; i < lines.length; i++) {
|
|
220
|
+
const line = lines[i];
|
|
221
|
+
section = updateSection(section, line);
|
|
222
|
+
// Accumulate a pending tag on its own line — consume it on the next
|
|
223
|
+
// non-empty, non-tag line.
|
|
224
|
+
const tag = parseTag(line);
|
|
225
|
+
if (tag) {
|
|
226
|
+
// Inline tag on the same line as the figure is also supported.
|
|
227
|
+
// In that case we use it immediately and skip the pending cycle.
|
|
228
|
+
const withoutTag = line.replace(TAG_RE, '').trim();
|
|
229
|
+
if (withoutTag.length > 0) {
|
|
230
|
+
extractFromLine(withoutTag, i + 1, section, tag, claims, document);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
pendingTag = tag;
|
|
234
|
+
}
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (line.trim().length === 0)
|
|
238
|
+
continue;
|
|
239
|
+
const useTag = pendingTag;
|
|
240
|
+
pendingTag = null;
|
|
241
|
+
extractFromLine(line, i + 1, section, useTag, claims, document);
|
|
242
|
+
}
|
|
243
|
+
return claims;
|
|
244
|
+
}
|
|
245
|
+
function extractFromLine(line, lineNumber, section, tag, out, document) {
|
|
246
|
+
// Currency claims
|
|
247
|
+
const currencyMatches = Array.from(line.matchAll(CURRENCY_RANGE_RE));
|
|
248
|
+
for (const match of currencyMatches) {
|
|
249
|
+
const raw = match[0];
|
|
250
|
+
// Ignore obvious context-only mentions like "$/sqft" or "$0"
|
|
251
|
+
if (/\$\s*\/|\$0\b|\$\s*X\b/i.test(raw))
|
|
252
|
+
continue;
|
|
253
|
+
const hasRange = /[-–—]|to/.test(raw);
|
|
254
|
+
let rangeLow;
|
|
255
|
+
let rangeHigh;
|
|
256
|
+
let pointValue;
|
|
257
|
+
if (hasRange) {
|
|
258
|
+
const parts = raw.split(/\s*(?:[-–—]|to)\s*/i);
|
|
259
|
+
if (parts.length === 2) {
|
|
260
|
+
const a = parseCurrency(parts[0]);
|
|
261
|
+
const b = parseCurrency(parts[1]);
|
|
262
|
+
if (!Number.isNaN(a) && !Number.isNaN(b)) {
|
|
263
|
+
rangeLow = Math.min(a, b);
|
|
264
|
+
rangeHigh = Math.max(a, b);
|
|
265
|
+
}
|
|
266
|
+
else if (!Number.isNaN(a)) {
|
|
267
|
+
pointValue = a;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
const v = parseCurrency(raw);
|
|
273
|
+
if (!Number.isNaN(v))
|
|
274
|
+
pointValue = v;
|
|
275
|
+
}
|
|
276
|
+
if (rangeLow === undefined && pointValue === undefined)
|
|
277
|
+
continue;
|
|
278
|
+
// Small-dollar amounts (< $1000) are almost never "financial claims" in
|
|
279
|
+
// an executive doc — they're unit prices, per-capita figures, etc.
|
|
280
|
+
// Skip them to reduce false positives. Real investment/savings figures
|
|
281
|
+
// are always ≥ $1K.
|
|
282
|
+
const anchorValue = pointValue ?? rangeLow ?? 0;
|
|
283
|
+
if (anchorValue < 1_000)
|
|
284
|
+
continue;
|
|
285
|
+
const context = line;
|
|
286
|
+
const kindDefault = 'investment';
|
|
287
|
+
const matchStart = match.index ?? 0;
|
|
288
|
+
const matchEnd = matchStart + raw.length;
|
|
289
|
+
const kind = tag?.kind ?? detectKind(context, kindDefault);
|
|
290
|
+
const scope = tag?.scope ?? detectScopeNearIndex(context, matchStart, matchEnd);
|
|
291
|
+
const claim = {
|
|
292
|
+
document,
|
|
293
|
+
section,
|
|
294
|
+
kind,
|
|
295
|
+
scope,
|
|
296
|
+
...(rangeLow !== undefined ? { rangeLow } : {}),
|
|
297
|
+
...(rangeHigh !== undefined ? { rangeHigh } : {}),
|
|
298
|
+
...(pointValue !== undefined ? { pointValue } : {}),
|
|
299
|
+
unit: 'USD',
|
|
300
|
+
rawText: raw,
|
|
301
|
+
line: lineNumber,
|
|
302
|
+
tagged: tag !== null,
|
|
303
|
+
...(tag?.doc ? { docTag: tag.doc } : {}),
|
|
304
|
+
};
|
|
305
|
+
out.push(claim);
|
|
306
|
+
}
|
|
307
|
+
// Timeline claims — weeks or months
|
|
308
|
+
const timelineMatches = Array.from(line.matchAll(/(\d+)[\s-]*(week|month|year)s?/gi));
|
|
309
|
+
for (const tm of timelineMatches) {
|
|
310
|
+
const value = parseInt(tm[1], 10);
|
|
311
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
312
|
+
continue;
|
|
313
|
+
const unitWord = tm[2].toLowerCase();
|
|
314
|
+
const unit = unitWord.startsWith('week') ? 'weeks' :
|
|
315
|
+
unitWord.startsWith('month') ? 'months' : 'years';
|
|
316
|
+
const tmStart = tm.index ?? 0;
|
|
317
|
+
const tmEnd = tmStart + tm[0].length;
|
|
318
|
+
const HISTORY_WINDOW = 30;
|
|
319
|
+
const windowStart = Math.max(0, tmStart - HISTORY_WINDOW);
|
|
320
|
+
const windowEnd = Math.min(line.length, tmEnd + HISTORY_WINDOW);
|
|
321
|
+
const window = line.slice(windowStart, windowEnd).toLowerCase();
|
|
322
|
+
// Ignore history references like "last 3 years" — check ONLY the window
|
|
323
|
+
// around this match, not the whole line, so legitimate forward-looking
|
|
324
|
+
// timelines aren't dropped when a history reference appears elsewhere.
|
|
325
|
+
if (/\b(last|past|previous|over the (?:past|last))\b/.test(window))
|
|
326
|
+
continue;
|
|
327
|
+
// Ignore payback-style tokens — those are covered by FCR-006 ROI, not timeline.
|
|
328
|
+
if (/payback/.test(window))
|
|
329
|
+
continue;
|
|
330
|
+
const scope = tag?.scope ?? detectScopeNearIndex(line, tmStart, tmEnd);
|
|
331
|
+
out.push({
|
|
332
|
+
document,
|
|
333
|
+
section,
|
|
334
|
+
kind: 'timeline',
|
|
335
|
+
scope,
|
|
336
|
+
pointValue: value,
|
|
337
|
+
unit,
|
|
338
|
+
rawText: tm[0],
|
|
339
|
+
line: lineNumber,
|
|
340
|
+
tagged: tag !== null,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
// Headcount claims — "91,000 employees" / "3,200 roles"
|
|
344
|
+
const headcountMatches = Array.from(line.matchAll(/([\d][\d,]{2,})\s*(?:employees|roles|headcount|staff)\b/gi));
|
|
345
|
+
for (const hm of headcountMatches) {
|
|
346
|
+
const v = parseInt(hm[1].replace(/,/g, ''), 10);
|
|
347
|
+
if (!Number.isFinite(v) || v <= 0)
|
|
348
|
+
continue;
|
|
349
|
+
out.push({
|
|
350
|
+
document,
|
|
351
|
+
section,
|
|
352
|
+
kind: 'headcount',
|
|
353
|
+
scope: tag?.scope ?? detectScope(line),
|
|
354
|
+
pointValue: v,
|
|
355
|
+
unit: 'count',
|
|
356
|
+
rawText: hm[0],
|
|
357
|
+
line: lineNumber,
|
|
358
|
+
tagged: tag !== null,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
// ROI percent claims — "217% projected" / "ROI 300%"
|
|
362
|
+
const roiMatches = Array.from(line.matchAll(/(\d+)\s*%/g));
|
|
363
|
+
for (const rm of roiMatches) {
|
|
364
|
+
if (!/\broi\b|return\s+on\s+investment/i.test(line))
|
|
365
|
+
continue;
|
|
366
|
+
const v = parseInt(rm[1], 10);
|
|
367
|
+
if (!Number.isFinite(v))
|
|
368
|
+
continue;
|
|
369
|
+
out.push({
|
|
370
|
+
document,
|
|
371
|
+
section,
|
|
372
|
+
kind: 'roi',
|
|
373
|
+
scope: tag?.scope ?? detectScope(line),
|
|
374
|
+
pointValue: v,
|
|
375
|
+
unit: 'percent',
|
|
376
|
+
rawText: rm[0],
|
|
377
|
+
line: lineNumber,
|
|
378
|
+
tagged: tag !== null,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
//# sourceMappingURL=financial-claim-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"financial-claim-extractor.js","sourceRoot":"","sources":["../../src/synthesis/financial-claim-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
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 type { FinancialClaim, FinancialClaimDocument, FinancialClaimKind, FinancialClaimScope } from './financial-claim-extractor.js';
|
|
19
|
+
import type { UnitEconomics } from '../pipeline/types.js';
|
|
20
|
+
import type { ConsensusSnapshot } from './consensus-tiers.js';
|
|
21
|
+
export type Severity = 'error' | 'warn';
|
|
22
|
+
export interface Violation {
|
|
23
|
+
readonly ruleId: string;
|
|
24
|
+
readonly severity: Severity;
|
|
25
|
+
readonly message: string;
|
|
26
|
+
readonly claims: readonly FinancialClaim[];
|
|
27
|
+
readonly suggestedFix?: string;
|
|
28
|
+
}
|
|
29
|
+
declare function ruleFcr001(claims: readonly FinancialClaim[]): Violation[];
|
|
30
|
+
declare function ruleFcr002and003(claims: readonly FinancialClaim[]): Violation[];
|
|
31
|
+
declare function ruleFcr004(claims: readonly FinancialClaim[]): Violation[];
|
|
32
|
+
declare function ruleFcr005(claims: readonly FinancialClaim[]): Violation[];
|
|
33
|
+
declare function ruleFcr006(claims: readonly FinancialClaim[]): Violation[];
|
|
34
|
+
declare function ruleFcr007(claims: readonly FinancialClaim[], manifest: UnitEconomics | null): Violation[];
|
|
35
|
+
declare function ruleFcr008(claims: readonly FinancialClaim[], manifest: UnitEconomics | null): Violation[];
|
|
36
|
+
declare function ruleFcr009(claims: readonly FinancialClaim[]): Violation[];
|
|
37
|
+
declare function ruleFcr011(claims: readonly FinancialClaim[]): Violation[];
|
|
38
|
+
declare function ruleFcr012(claims: readonly FinancialClaim[]): Violation[];
|
|
39
|
+
export interface DocumentBody {
|
|
40
|
+
readonly document: FinancialClaimDocument;
|
|
41
|
+
readonly content: string;
|
|
42
|
+
}
|
|
43
|
+
declare function ruleFcr010(documents: readonly DocumentBody[], consensus: ConsensusSnapshot | null): Violation[];
|
|
44
|
+
export interface RunRulesInput {
|
|
45
|
+
readonly claims: readonly FinancialClaim[];
|
|
46
|
+
readonly manifest?: UnitEconomics | null;
|
|
47
|
+
readonly documents?: readonly DocumentBody[];
|
|
48
|
+
readonly consensus?: ConsensusSnapshot | null;
|
|
49
|
+
}
|
|
50
|
+
export declare function runConsistencyRules(input: RunRulesInput): Violation[];
|
|
51
|
+
export declare const __internal: {
|
|
52
|
+
ruleFcr001: typeof ruleFcr001;
|
|
53
|
+
ruleFcr002and003: typeof ruleFcr002and003;
|
|
54
|
+
ruleFcr004: typeof ruleFcr004;
|
|
55
|
+
ruleFcr005: typeof ruleFcr005;
|
|
56
|
+
ruleFcr006: typeof ruleFcr006;
|
|
57
|
+
ruleFcr007: typeof ruleFcr007;
|
|
58
|
+
ruleFcr008: typeof ruleFcr008;
|
|
59
|
+
ruleFcr009: typeof ruleFcr009;
|
|
60
|
+
ruleFcr010: typeof ruleFcr010;
|
|
61
|
+
ruleFcr011: typeof ruleFcr011;
|
|
62
|
+
ruleFcr012: typeof ruleFcr012;
|
|
63
|
+
};
|
|
64
|
+
export declare function countViolations(vs: readonly Violation[]): {
|
|
65
|
+
errors: number;
|
|
66
|
+
warnings: number;
|
|
67
|
+
};
|
|
68
|
+
export declare function violationsByDocument(vs: readonly Violation[]): Map<FinancialClaimDocument, Violation[]>;
|
|
69
|
+
export type { FinancialClaim, FinancialClaimDocument, FinancialClaimKind, FinancialClaimScope };
|
|
70
|
+
//# sourceMappingURL=financial-consistency-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"financial-consistency-rules.d.ts","sourceRoot":"","sources":["../../src/synthesis/financial-consistency-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAG9D,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAExC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAoDD,iBAAS,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAAE,CAmDlE;AAOD,iBAAS,gBAAgB,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAAE,CAwDxE;AAMD,iBAAS,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAAE,CAclE;AAgBD,iBAAS,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAAE,CAmClE;AAMD,iBAAS,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAAE,CAkClE;AAMD,iBAAS,UAAU,CACjB,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,QAAQ,EAAE,aAAa,GAAG,IAAI,GAC7B,SAAS,EAAE,CAkCb;AAMD,iBAAS,UAAU,CACjB,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,QAAQ,EAAE,aAAa,GAAG,IAAI,GAC7B,SAAS,EAAE,CAoCb;AAMD,iBAAS,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAAE,CA4BlE;AAMD,iBAAS,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAAE,CAkBlE;AAMD,iBAAS,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAAE,CAkBlE;AAMD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,iBAAS,UAAU,CACjB,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,SAAS,EAAE,iBAAiB,GAAG,IAAI,GAClC,SAAS,EAAE,CA+Bb;AAMD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC/C;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,EAAE,CAerE;AAGD,eAAO,MAAM,UAAU;;;;;;;;;;;;CAYtB,CAAC;AAGF,wBAAgB,eAAe,CAAC,EAAE,EAAE,SAAS,SAAS,EAAE,GAAG;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAQA;AAGD,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,SAAS,SAAS,EAAE,GACvB,GAAG,CAAC,sBAAsB,EAAE,SAAS,EAAE,CAAC,CAU1C;AAGD,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,CAAC"}
|