@llm-dev-ops/agentics-cli 2.7.12 → 2.7.14
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/synthesis/agent-claim-registry.d.ts +23 -0
- package/dist/synthesis/agent-claim-registry.d.ts.map +1 -1
- package/dist/synthesis/agent-claim-registry.js +71 -3
- package/dist/synthesis/agent-claim-registry.js.map +1 -1
- package/dist/synthesis/simulation-artifact-generator.d.ts.map +1 -1
- package/dist/synthesis/simulation-artifact-generator.js +6 -3
- package/dist/synthesis/simulation-artifact-generator.js.map +1 -1
- package/dist/synthesis/simulation-renderers.d.ts +3 -3
- package/dist/synthesis/simulation-renderers.d.ts.map +1 -1
- package/dist/synthesis/simulation-renderers.js +152 -17
- package/dist/synthesis/simulation-renderers.js.map +1 -1
- package/package.json +1 -1
|
@@ -380,7 +380,7 @@ function computeDomainAwareConfidence(query, originalProb) {
|
|
|
380
380
|
const rounded = Math.round(score * 100) / 100;
|
|
381
381
|
return Math.abs(rounded - originalProb) > 0.03 ? rounded : originalProb;
|
|
382
382
|
}
|
|
383
|
-
export function synthesizeFinancials(simData, platformResults, query) {
|
|
383
|
+
export function synthesizeFinancials(simData, platformResults, query, runDir) {
|
|
384
384
|
const fm = (safeGet(simData, 'financial_model') ?? safeGet(simData, 'cost_model') ?? safeGet(simData, 'financials'));
|
|
385
385
|
// Collect from all possible agent sources — not just costops
|
|
386
386
|
const financialFields = {};
|
|
@@ -405,6 +405,14 @@ export function synthesizeFinancials(simData, platformResults, query) {
|
|
|
405
405
|
// contribute to D3 part 2's triangulation surface.
|
|
406
406
|
const triangulationMap = {};
|
|
407
407
|
resolveCanonicalClaims(platformResults, financialFields, financialSources, triangulationMap);
|
|
408
|
+
// ── Source 0.5: ADR-096 D3+ (2.7.13) — narrative extraction ────────────
|
|
409
|
+
// When platform/decision-memo or platform/executive-summary return
|
|
410
|
+
// narrative text rather than structured JSON, scan that text for explicit
|
|
411
|
+
// financial figures ($X investment, Y% ROI, etc.) and use them with
|
|
412
|
+
// src=domain/agent:extracted. Conservative regex — only catches anchored
|
|
413
|
+
// mentions, never invents values. Cheaper than an LLM call but bridges
|
|
414
|
+
// the gap when the agent narrative happens to include real numbers.
|
|
415
|
+
resolveNarrativeClaims(platformResults, financialFields, financialSources);
|
|
408
416
|
// Source 1: simData direct fields
|
|
409
417
|
for (const [key, ...aliases] of financialKeys) {
|
|
410
418
|
if (!key)
|
|
@@ -463,6 +471,47 @@ export function synthesizeFinancials(simData, platformResults, query) {
|
|
|
463
471
|
}
|
|
464
472
|
}
|
|
465
473
|
}
|
|
474
|
+
// ── Source 0.7: ADR-PIPELINE-096 D3++ (2.7.14) — unit-economics-derived ─
|
|
475
|
+
// When a unit-economics.json manifest exists for this run AND any of the
|
|
476
|
+
// headline metrics are still empty, derive them from the bottom-up sector
|
|
477
|
+
// baseline (sqft × $/sqft for CRE, rooms × $/orn for hospitality, etc.)
|
|
478
|
+
// via buildFinancialModelFromUnitEconomics. This unifies the methodology:
|
|
479
|
+
// savings AND investment AND NPV AND payback all trace to one model
|
|
480
|
+
// instead of having savings from sqft baseline but investment from
|
|
481
|
+
// per-employee. McKinsey/Accenture engagements would flag the methodology
|
|
482
|
+
// mismatch — this fixes it.
|
|
483
|
+
if (runDir) {
|
|
484
|
+
const manifestResult = loadUnitEconomics(runDir);
|
|
485
|
+
if (manifestResult.manifest) {
|
|
486
|
+
const m = buildFinancialModelFromUnitEconomics(manifestResult.manifest);
|
|
487
|
+
const sector = manifestResult.manifest.sector;
|
|
488
|
+
const sourceTag = `unit-economics:${sector}`;
|
|
489
|
+
if (!financialFields['budget']) {
|
|
490
|
+
financialFields['budget'] = m.budget;
|
|
491
|
+
financialSources['budget'] = sourceTag;
|
|
492
|
+
}
|
|
493
|
+
if (!financialFields['roi']) {
|
|
494
|
+
financialFields['roi'] = m.roi;
|
|
495
|
+
financialSources['roi'] = sourceTag;
|
|
496
|
+
}
|
|
497
|
+
if (!financialFields['npv']) {
|
|
498
|
+
financialFields['npv'] = m.npv;
|
|
499
|
+
financialSources['npv'] = sourceTag;
|
|
500
|
+
}
|
|
501
|
+
if (!financialFields['payback']) {
|
|
502
|
+
financialFields['payback'] = m.payback;
|
|
503
|
+
financialSources['payback'] = sourceTag;
|
|
504
|
+
}
|
|
505
|
+
if (!financialFields['revenue']) {
|
|
506
|
+
financialFields['revenue'] = m.revenue;
|
|
507
|
+
financialSources['revenue'] = sourceTag;
|
|
508
|
+
}
|
|
509
|
+
if (!financialFields['costSavings']) {
|
|
510
|
+
financialFields['costSavings'] = m.costSavings;
|
|
511
|
+
financialSources['costSavings'] = sourceTag;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
466
515
|
const hasRealData = !!(financialFields['budget'] || financialFields['roi'] || financialFields['npv'] || financialFields['payback'] || financialFields['revenue'] || financialFields['costSavings']);
|
|
467
516
|
// Source 3: Estimate from query context when nothing else available
|
|
468
517
|
if (!hasRealData) {
|
|
@@ -594,6 +643,76 @@ function resolveCanonicalClaims(platformResults, financialFields, financialSourc
|
|
|
594
643
|
captureTriangulation('revenue', 'savings');
|
|
595
644
|
captureTriangulation('costSavings', 'savings');
|
|
596
645
|
}
|
|
646
|
+
/**
|
|
647
|
+
* ADR-PIPELINE-096 D3+ (2.7.13) — Source 0.5: extract financial figures
|
|
648
|
+
* from agent narrative responses (platform/decision-memo,
|
|
649
|
+
* platform/executive-summary). Used when no canonical agent supplied a
|
|
650
|
+
* structured value but a narrative mention exists.
|
|
651
|
+
*/
|
|
652
|
+
function resolveNarrativeClaims(platformResults, financialFields, financialSources) {
|
|
653
|
+
// Collect narrative agents — currently platform/decision-memo and
|
|
654
|
+
// platform/executive-summary are the only two that return structured
|
|
655
|
+
// narrative blocks per the 2.7.10 calibration diagnostic.
|
|
656
|
+
const narrativeAgents = [];
|
|
657
|
+
for (const r of platformResults) {
|
|
658
|
+
if (r.status < 200 || r.status >= 300)
|
|
659
|
+
continue;
|
|
660
|
+
const agent = r;
|
|
661
|
+
if (agent.domain !== 'platform')
|
|
662
|
+
continue;
|
|
663
|
+
if (agent.agent !== 'decision-memo' && agent.agent !== 'executive-summary')
|
|
664
|
+
continue;
|
|
665
|
+
const sp = extractSignalPayload(r.response);
|
|
666
|
+
const data = sp.data ?? {};
|
|
667
|
+
// Concatenate the narrative-bearing fields. decision-memo has
|
|
668
|
+
// background, analysis, recommendation, risks; executive-summary has
|
|
669
|
+
// executive_summary, key_findings, recommendation. Catch all relevant.
|
|
670
|
+
const parts = [];
|
|
671
|
+
for (const k of ['executive_summary', 'background', 'analysis', 'recommendation', 'risks', 'key_findings', 'next_steps', 'options']) {
|
|
672
|
+
const v = data[k];
|
|
673
|
+
if (typeof v === 'string')
|
|
674
|
+
parts.push(v);
|
|
675
|
+
else if (Array.isArray(v))
|
|
676
|
+
parts.push(v.filter(x => typeof x === 'string').join(' '));
|
|
677
|
+
}
|
|
678
|
+
const narrative = parts.join(' ');
|
|
679
|
+
if (narrative.length > 20) {
|
|
680
|
+
narrativeAgents.push({ domain: agent.domain, agent: agent.agent, narrative });
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if (narrativeAgents.length === 0)
|
|
684
|
+
return;
|
|
685
|
+
const extracted = agentClaimRegistry.extractFinancialClaimsFromNarrative(narrativeAgents);
|
|
686
|
+
// Map extracted claims onto financialFields keys based on the source suffix.
|
|
687
|
+
for (const claim of extracted) {
|
|
688
|
+
const value = typeof claim.value === 'string' ? claim.value : String(claim.value);
|
|
689
|
+
if (claim.source.endsWith(':extracted')) {
|
|
690
|
+
// Plain investment extraction
|
|
691
|
+
if (!financialFields['budget']) {
|
|
692
|
+
financialFields['budget'] = `${value} (${claim.methodology})`;
|
|
693
|
+
financialSources['budget'] = claim.source;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
else if (claim.source.endsWith(':extracted-roi')) {
|
|
697
|
+
if (!financialFields['roi']) {
|
|
698
|
+
financialFields['roi'] = `${value} projected (${claim.methodology})`;
|
|
699
|
+
financialSources['roi'] = claim.source;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
else if (claim.source.endsWith(':extracted-npv')) {
|
|
703
|
+
if (!financialFields['npv']) {
|
|
704
|
+
financialFields['npv'] = `${value} 5-year NPV (${claim.methodology})`;
|
|
705
|
+
financialSources['npv'] = claim.source;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
else if (claim.source.endsWith(':extracted-payback')) {
|
|
709
|
+
if (!financialFields['payback']) {
|
|
710
|
+
financialFields['payback'] = `${value} (${claim.methodology})`;
|
|
711
|
+
financialSources['payback'] = claim.source;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
597
716
|
/** Format a registry-resolved value into the renderer's expected string shape. */
|
|
598
717
|
function formatClaimValue(key, value, methodology) {
|
|
599
718
|
if (typeof value === 'string')
|
|
@@ -1663,7 +1782,7 @@ export async function synthesizeExecutiveDocument(skeleton, query, documentType,
|
|
|
1663
1782
|
// ============================================================================
|
|
1664
1783
|
// Executive Summary Renderer (ADR-PIPELINE-024: Pyramid Principle)
|
|
1665
1784
|
// ============================================================================
|
|
1666
|
-
export function renderExecutiveSummary(query, simulationResult, platformResults) {
|
|
1785
|
+
export function renderExecutiveSummary(query, simulationResult, platformResults, runDir) {
|
|
1667
1786
|
const now = new Date().toISOString();
|
|
1668
1787
|
const simPayload = extractSignalPayload(simulationResult);
|
|
1669
1788
|
const simData = simPayload.data ?? {};
|
|
@@ -1672,7 +1791,10 @@ export function renderExecutiveSummary(query, simulationResult, platformResults)
|
|
|
1672
1791
|
const timeline = safeString(simData, 'timeline_estimate') || safeString(simData, 'timeline') || '12-18 weeks';
|
|
1673
1792
|
const problemStatement = distillProblemStatement(query);
|
|
1674
1793
|
const extracted = extractScenarioFromQuery(query);
|
|
1675
|
-
|
|
1794
|
+
// ADR-PIPELINE-096 D3++ (2.7.14) — pass runDir so synthesizeFinancials
|
|
1795
|
+
// can apply the unit-economics-derived bottom-up methodology when
|
|
1796
|
+
// available. The same call now serves all three documents.
|
|
1797
|
+
const fin = synthesizeFinancials(simData, platformResults, query, runDir);
|
|
1676
1798
|
const risks = generateDomainRisks(query, extracted);
|
|
1677
1799
|
const primarySystem = extracted.systems[0] ?? extractSystemFromQuery(query) ?? 'the enterprise platform';
|
|
1678
1800
|
let recommendation = 'DEFER';
|
|
@@ -1786,21 +1908,33 @@ export function renderExecutiveSummary(query, simulationResult, platformResults)
|
|
|
1786
1908
|
// carry scope=full-program.
|
|
1787
1909
|
if (fin.hasData) {
|
|
1788
1910
|
lines.push('## Financial Impact', '');
|
|
1789
|
-
// ADR-PIPELINE-096 D3 calibration banner (2.7.11
|
|
1790
|
-
//
|
|
1791
|
-
//
|
|
1792
|
-
// src=
|
|
1793
|
-
//
|
|
1794
|
-
// agent
|
|
1795
|
-
//
|
|
1796
|
-
//
|
|
1911
|
+
// ADR-PIPELINE-096 D3 calibration banner (2.7.11→2.7.14): banner shape
|
|
1912
|
+
// depends on which source filled the cells:
|
|
1913
|
+
// • src=domain/agent → canonical agent (no banner; just the data)
|
|
1914
|
+
// • src=unit-economics:X → bottom-up sector model (no banner — this
|
|
1915
|
+
// IS the canonical methodology when no
|
|
1916
|
+
// project-level agent exists; tag this
|
|
1917
|
+
// explicitly as the engagement methodology)
|
|
1918
|
+
// • src=heuristic:X → per-employee fallback (banner with full
|
|
1919
|
+
// remediation guidance)
|
|
1797
1920
|
const allSources = [fin.sources?.budget, fin.sources?.roi, fin.sources?.npv, fin.sources?.payback, fin.sources?.revenue, fin.sources?.costSavings].filter(Boolean);
|
|
1798
|
-
const
|
|
1799
|
-
const
|
|
1800
|
-
|
|
1801
|
-
|
|
1921
|
+
const hasAnyAgentCanonical = allSources.some(s => !s.startsWith('heuristic:') && !s.startsWith('unit-economics:'));
|
|
1922
|
+
const allUnitEconomics = allSources.length > 0 && allSources.every(s => s.startsWith('unit-economics:'));
|
|
1923
|
+
const allHeuristic = allSources.length > 0 && allSources.every(s => s.startsWith('heuristic:'));
|
|
1924
|
+
if (allHeuristic) {
|
|
1925
|
+
lines.push('> **⚠️ Heuristic fallback in use.** No agent in the current fleet returned project-level financial figures, and unit-economics manifest was unavailable. The numbers below are derived from the sector-baseline per-employee benchmark (ADR-PIPELINE-095) and are tagged `src=heuristic:...` for transparency. For consultancy-grade attribution, either provision a project-financial agent that returns `{investment, roi, npv, payback}` at predictable paths, or add an LLM-extraction layer over `platform/decision-memo`\'s narrative output (ADR-PIPELINE-096 task #24).');
|
|
1926
|
+
lines.push('');
|
|
1927
|
+
}
|
|
1928
|
+
else if (allUnitEconomics) {
|
|
1929
|
+
lines.push('> **📊 Bottom-up sector methodology.** All headline figures derive from the unit-economics manifest (ADR-PIPELINE-066 §6 sector baseline) — savings AND investment AND NPV AND payback all trace to one model, McKinsey/Accenture-grade methodology consistency. Source attribution: `src=unit-economics:<sector>`.');
|
|
1930
|
+
lines.push('');
|
|
1931
|
+
}
|
|
1932
|
+
else if (!hasAnyAgentCanonical && allSources.length > 0) {
|
|
1933
|
+
// Mixed unit-econ + heuristic — partial bottom-up, partial fallback.
|
|
1934
|
+
lines.push('> **📊 Mixed methodology.** Some figures are unit-economics-derived (sector bottom-up); others are heuristic per-employee fallback. Source attribution carried in each cell\'s `src=` tag.');
|
|
1802
1935
|
lines.push('');
|
|
1803
1936
|
}
|
|
1937
|
+
// If hasAnyAgentCanonical: agents supplied at least one value — no banner needed (the data IS the deliverable).
|
|
1804
1938
|
lines.push('| Metric | Value |', '|--------|-------|');
|
|
1805
1939
|
// ADR-PIPELINE-096 D3 — pass `fin.sources?.X` to fcvTag so the rendered
|
|
1806
1940
|
// cell carries `src=domain/agent` (canonical) or omits the attribute
|
|
@@ -1919,7 +2053,7 @@ export function renderExecutiveSummary(query, simulationResult, platformResults)
|
|
|
1919
2053
|
// ============================================================================
|
|
1920
2054
|
// Decision Memo Renderer
|
|
1921
2055
|
// ============================================================================
|
|
1922
|
-
export function renderDecisionMemo(query, simulationResult, platformResults) {
|
|
2056
|
+
export function renderDecisionMemo(query, simulationResult, platformResults, runDir) {
|
|
1923
2057
|
const now = new Date().toISOString();
|
|
1924
2058
|
const lineage = extractSimulationLineage(simulationResult);
|
|
1925
2059
|
const simPayload = extractSignalPayload(simulationResult);
|
|
@@ -1927,7 +2061,8 @@ export function renderDecisionMemo(query, simulationResult, platformResults) {
|
|
|
1927
2061
|
const successProb = extractSuccessProbability(simData);
|
|
1928
2062
|
const extracted = extractScenarioFromQuery(query);
|
|
1929
2063
|
const problemStatement = distillProblemStatement(query);
|
|
1930
|
-
|
|
2064
|
+
// ADR-PIPELINE-096 D3++ (2.7.14) — runDir threaded for unit-economics-derived methodology.
|
|
2065
|
+
const fin = synthesizeFinancials(simData, platformResults, query, runDir);
|
|
1931
2066
|
const risks = generateDomainRisks(query, extracted);
|
|
1932
2067
|
const primarySystem = extracted.systems[0] ?? extractSystemFromQuery(query) ?? 'the enterprise platform';
|
|
1933
2068
|
const plannerData = extractAgentData(platformResults, 'copilot', 'planner');
|