Files
worldmonitor/tests/forecast-trace-export.test.mjs

4085 lines
168 KiB
JavaScript

import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
makePrediction,
buildForecastCase,
populateFallbackNarratives,
buildForecastTraceArtifacts,
buildForecastRunWorldState,
buildCrossSituationEffects,
buildSimulationMarketConsequences,
buildReportableInteractionLedger,
buildInteractionWatchlist,
isCrossTheaterPair,
getMacroRegion,
attachSituationContext,
projectSituationClusters,
refreshPublishedNarratives,
selectPublishedForecastPool,
deriveStateDrivenForecasts,
extractNewsClusterItems,
selectUrgentCriticalNewsCandidates,
validateCriticalSignalFrames,
mapCriticalSignalFrameToSignals,
extractCriticalNewsSignals,
buildImpactExpansionCandidateHash,
validateImpactHypotheses,
} from '../scripts/seed-forecasts.mjs';
import {
resolveR2StorageConfig,
} from '../scripts/_r2-storage.mjs';
describe('forecast trace storage config', () => {
it('resolves Cloudflare R2 trace env vars and derives the endpoint from account id', () => {
const config = resolveR2StorageConfig({
CLOUDFLARE_R2_ACCOUNT_ID: 'acct123',
CLOUDFLARE_R2_TRACE_BUCKET: 'trace-bucket',
CLOUDFLARE_R2_ACCESS_KEY_ID: 'abc',
CLOUDFLARE_R2_SECRET_ACCESS_KEY: 'def',
CLOUDFLARE_R2_REGION: 'auto',
CLOUDFLARE_R2_TRACE_PREFIX: 'custom-prefix',
CLOUDFLARE_R2_FORCE_PATH_STYLE: 'true',
});
assert.equal(config.bucket, 'trace-bucket');
assert.equal(config.endpoint, 'https://acct123.r2.cloudflarestorage.com');
assert.equal(config.region, 'auto');
assert.equal(config.basePrefix, 'custom-prefix');
assert.equal(config.forcePathStyle, true);
});
it('falls back to a shared Cloudflare R2 bucket env var', () => {
const config = resolveR2StorageConfig({
CLOUDFLARE_R2_ACCOUNT_ID: 'acct123',
CLOUDFLARE_R2_BUCKET: 'shared-bucket',
CLOUDFLARE_R2_ACCESS_KEY_ID: 'abc',
CLOUDFLARE_R2_SECRET_ACCESS_KEY: 'def',
});
assert.equal(config.bucket, 'shared-bucket');
assert.equal(config.endpoint, 'https://acct123.r2.cloudflarestorage.com');
});
});
describe('forecast trace artifact builder', () => {
it('builds manifest, summary, and per-forecast trace artifacts', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
{ type: 'ucdp', value: '3 UCDP conflict events', weight: 0.3 },
]);
a.newsContext = ['Regional officials warn of retaliation risk'];
a.calibration = { marketTitle: 'Will Iran conflict escalate before July?', marketPrice: 0.71, drift: 0.03, source: 'polymarket' };
a.trend = 'rising';
buildForecastCase(a);
const b = makePrediction('supply_chain', 'Red Sea', 'Shipping disruption: Red Sea', 0.68, 0.59, '7d', [
{ type: 'chokepoint', value: 'Red Sea disruption detected', weight: 0.5 },
{ type: 'gps_jamming', value: 'GPS interference near Red Sea', weight: 0.2 },
]);
b.newsContext = ['Freight rates react to Red Sea rerouting'];
b.trend = 'rising';
buildForecastCase(b);
const c = makePrediction('cyber', 'China', 'Cyber pressure: China', 0.59, 0.55, '7d', [
{ type: 'cyber', value: 'Malware-hosting concentration remains elevated', weight: 0.4 },
]);
c.trend = 'stable';
buildForecastCase(c);
populateFallbackNarratives([a, b, c]);
const artifacts = buildForecastTraceArtifacts(
{
generatedAt: Date.parse('2026-03-15T08:00:00Z'),
predictions: [a, b],
fullRunPredictions: [a, b, c],
publishTelemetry: {
suppressedFamilySelection: 2,
suppressedWeakFallback: 1,
suppressedSituationOverlap: 2,
suppressedSituationCap: 1,
suppressedSituationDomainCap: 1,
suppressedTotal: 5,
reasonCounts: { weak_fallback: 1, situation_overlap: 2, situation_cap: 1, situation_domain_cap: 1 },
situationClusterCount: 2,
maxForecastsPerSituation: 2,
multiForecastSituations: 1,
cappedSituations: 1,
},
triggerContext: {
triggerSource: 'military_chain',
triggerService: 'seed-forecasts',
deployRevision: 'abc123',
triggerRequest: {
requestedAt: Date.parse('2026-03-15T07:59:00Z'),
requestedAtIso: '2026-03-15T07:59:00.000Z',
requester: 'seed-military-flights',
requesterRunId: 'mil-run-1',
sourceVersion: 'wingbits',
},
},
},
{ runId: 'run-123' },
{ basePrefix: 'forecast-runs', maxForecasts: 1 },
);
assert.equal(artifacts.manifest.runId, 'run-123');
assert.equal(artifacts.manifest.forecastCount, 2);
assert.equal(artifacts.manifest.tracedForecastCount, 1);
assert.equal(artifacts.manifest.triggerContext.triggerSource, 'military_chain');
assert.match(artifacts.manifestKey, /forecast-runs\/2026\/03\/15\/run-123\/manifest\.json/);
assert.match(artifacts.summaryKey, /forecast-runs\/2026\/03\/15\/run-123\/summary\.json/);
assert.match(artifacts.worldStateKey, /forecast-runs\/2026\/03\/15\/run-123\/world-state\.json/);
assert.equal(artifacts.forecasts.length, 1);
assert.equal(artifacts.summary.topForecasts[0].id, a.id);
assert.deepEqual(artifacts.summary.quality.fullRun.domainCounts, {
conflict: 1,
market: 0,
supply_chain: 1,
political: 0,
military: 0,
cyber: 0,
infrastructure: 0,
});
assert.deepEqual(artifacts.summary.quality.fullRun.generationOriginCounts, {
legacy_detector: 2,
});
assert.equal(artifacts.summary.quality.fullRun.stateDerivedBackfillCount, 0);
assert.deepEqual(artifacts.summary.quality.fullRun.highlightedDomainCounts, {
conflict: 1,
market: 0,
supply_chain: 1,
political: 0,
military: 0,
cyber: 0,
infrastructure: 0,
});
assert.deepEqual(artifacts.summary.quality.traced.domainCounts, {
conflict: 1,
market: 0,
supply_chain: 0,
political: 0,
military: 0,
cyber: 0,
infrastructure: 0,
});
assert.equal(artifacts.summary.quality.traced.fallbackCount, 1);
assert.equal(artifacts.summary.quality.traced.enrichedCount, 0);
assert.equal(artifacts.summary.quality.traced.fallbackRate, 1);
assert.equal(artifacts.summary.quality.traced.enrichedRate, 0);
assert.equal(artifacts.summary.quality.publish.suppressedSituationOverlap, 2);
assert.equal(artifacts.summary.quality.publish.suppressedFamilySelection, 2);
assert.equal(artifacts.summary.quality.publish.suppressedSituationCap, 1);
assert.equal(artifacts.summary.quality.publish.suppressedSituationDomainCap, 1);
assert.equal(artifacts.summary.quality.publish.cappedSituations, 1);
assert.equal(artifacts.summary.quality.candidateRun.domainCounts.cyber, 1);
assert.deepEqual(artifacts.summary.quality.candidateRun.generationOriginCounts, {
legacy_detector: 3,
});
assert.ok(artifacts.summary.quality.fullRun.quietDomains.includes('military'));
assert.equal(artifacts.summary.quality.traced.topPromotionSignals[0].type, 'cii');
assert.equal(artifacts.summary.worldStateSummary.scope, 'published');
assert.ok(artifacts.summary.worldStateSummary.summary.includes('active forecasts'));
assert.ok(artifacts.summary.worldStateSummary.reportSummary.includes('leading domains'));
assert.ok(typeof artifacts.summary.worldStateSummary.reportContinuitySummary === 'string');
assert.equal(artifacts.summary.worldStateSummary.domainCount, 2);
assert.equal(artifacts.summary.worldStateSummary.regionCount, 2);
assert.ok(typeof artifacts.summary.worldStateSummary.situationCount === 'number');
assert.ok(artifacts.summary.worldStateSummary.situationCount >= 1);
assert.ok(typeof artifacts.summary.worldStateSummary.familyCount === 'number');
assert.ok(artifacts.summary.worldStateSummary.familyCount >= 1);
assert.ok(typeof artifacts.summary.worldStateSummary.simulationSituationCount === 'number');
assert.equal(artifacts.summary.worldStateSummary.simulationRoundCount, 3);
assert.ok(typeof artifacts.summary.worldStateSummary.simulationSummary === 'string');
assert.ok(typeof artifacts.summary.worldStateSummary.marketSummary === 'string');
assert.ok(typeof artifacts.summary.worldStateSummary.simulationInputSummary === 'string');
assert.ok(typeof artifacts.summary.worldStateSummary.worldSignalCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.marketBucketCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.transmissionEdgeCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.marketConsequenceCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.topMarketBucket === 'string');
assert.ok(typeof artifacts.summary.worldStateSummary.simulationEnvironmentSummary === 'string');
assert.ok(typeof artifacts.summary.worldStateSummary.memoryMutationSummary === 'string');
assert.ok(typeof artifacts.summary.worldStateSummary.causalReplaySummary === 'string');
assert.ok(typeof artifacts.summary.worldStateSummary.simulationActionCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.simulationInteractionCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.simulationEffectCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.simulationEnvironmentCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.memoryMutationCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.causalReplayCount === 'number');
assert.ok(typeof artifacts.summary.worldStateSummary.historyRuns === 'number');
assert.equal(artifacts.summary.worldStateSummary.candidateStateSummary.forecastCount, 3);
assert.ok(artifacts.summary.worldStateSummary.candidateStateSummary.situationCount >= artifacts.summary.worldStateSummary.situationCount);
assert.ok(Array.isArray(artifacts.worldState.actorRegistry));
assert.ok(artifacts.worldState.actorRegistry.every(actor => actor.name && actor.id));
assert.equal(artifacts.summary.worldStateSummary.persistentActorCount, 0);
assert.ok(typeof artifacts.summary.worldStateSummary.newlyActiveActors === 'number');
assert.equal(artifacts.summary.worldStateSummary.branchCount, 6);
assert.equal(artifacts.summary.worldStateSummary.newBranches, 6);
assert.equal(artifacts.summary.triggerContext.triggerRequest.requester, 'seed-military-flights');
assert.ok(Array.isArray(artifacts.worldState.situationClusters));
assert.ok(Array.isArray(artifacts.worldState.simulationState?.situationSimulations));
assert.equal(artifacts.worldState.simulationState?.roundTransitions?.length, 3);
assert.ok(Array.isArray(artifacts.worldState.simulationState?.actionLedger));
assert.ok(Array.isArray(artifacts.worldState.simulationState?.interactionLedger));
assert.ok(Array.isArray(artifacts.worldState.simulationState?.replayTimeline));
assert.ok(Array.isArray(artifacts.worldState.simulationState?.environmentSpec?.situations));
assert.ok(Array.isArray(artifacts.worldState.simulationState?.memoryMutations?.situations));
assert.ok(Array.isArray(artifacts.worldState.simulationState?.causalGraph?.edges));
assert.ok(Array.isArray(artifacts.worldState.simulationState?.causalReplay?.chains));
assert.ok(Array.isArray(artifacts.worldState.report.situationWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.actorWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.branchWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.marketWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.transmissionWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.marketConsequenceWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.simulationWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.interactionWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.replayWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.environmentWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.memoryWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.causalReplayWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.causalEdgeWatchlist));
assert.ok(Array.isArray(artifacts.worldState.report.simulationOutcomeSummaries));
assert.ok(Array.isArray(artifacts.worldState.report.crossSituationEffects));
assert.ok(Array.isArray(artifacts.worldState.report.causalReplayChains));
assert.ok(Array.isArray(artifacts.worldState.report.replayTimeline));
assert.ok(Array.isArray(artifacts.worldState.worldSignals?.signals));
assert.ok(Array.isArray(artifacts.worldState.marketState?.buckets));
assert.ok(Array.isArray(artifacts.worldState.marketTransmission?.edges));
assert.ok(Array.isArray(artifacts.worldState.simulationState?.marketConsequences?.items));
assert.ok(typeof artifacts.summary.worldStateSummary.marketInputCoverage?.loadedSourceCount === 'number');
assert.ok(artifacts.forecasts[0].payload.caseFile.worldState.summary.includes('Iran'));
assert.equal(artifacts.forecasts[0].payload.caseFile.branches.length, 3);
assert.equal(artifacts.forecasts[0].payload.traceMeta.narrativeSource, 'fallback');
// simulation linkage: per-forecast worldState must carry simulation fields from the global simulation state
const forecastWorldState = artifacts.forecasts[0].payload.caseFile.worldState;
const simulations = artifacts.worldState.simulationState?.situationSimulations || [];
if (simulations.length > 0) {
assert.ok(typeof forecastWorldState.situationId === 'string' && forecastWorldState.situationId.length > 0, 'worldState.situationId should be set from simulation');
assert.ok(typeof forecastWorldState.simulationSummary === 'string' && forecastWorldState.simulationSummary.length > 0, 'worldState.simulationSummary should be set from simulation');
assert.ok(['escalatory', 'contested', 'constrained'].includes(forecastWorldState.simulationPosture), 'worldState.simulationPosture should be a valid posture');
assert.ok(typeof forecastWorldState.simulationPostureScore === 'number', 'worldState.simulationPostureScore should be a number');
}
});
it('stores full canonical narrative fields alongside compact short fields in trace artifacts', () => {
const pred = makePrediction('market', 'Strait of Hormuz', 'Energy repricing risk: Strait of Hormuz', 0.71, 0.64, '30d', [
{ type: 'shipping_cost_shock', value: 'Strait of Hormuz rerouting is keeping freight costs elevated.', weight: 0.38 },
]);
buildForecastCase(pred);
pred.scenario = 'Strait of Hormuz shipping disruption keeps freight and energy repricing active across the Gulf over the next 30d while LNG routes, tanker insurance costs, and importer hedging behavior continue to amplify the base path across multiple downstream markets and policy-sensitive sectors.';
pred.feedSummary = 'Strait of Hormuz disruption is still anchoring the main market path through higher freight, wider energy premia, and persistent rerouting pressure across Gulf-linked trade flows, even as participants avoid assuming a full corridor closure.';
pred.traceMeta = { narrativeSource: 'llm_combined' };
const artifacts = buildForecastTraceArtifacts(
{
generatedAt: Date.parse('2026-03-23T09:00:00Z'),
predictions: [pred],
},
{ runId: 'trace-narrative-fields' },
{ maxForecasts: 1 },
);
const traced = artifacts.forecasts[0].payload;
assert.ok(traced.scenario.length > 220);
assert.ok(traced.feedSummary.length > 220);
assert.ok(traced.scenarioShort.length < traced.scenario.length);
assert.ok(traced.feedSummaryShort.length < traced.feedSummary.length);
assert.match(traced.scenarioShort, /\.\.\.$/);
assert.match(traced.feedSummaryShort, /\.\.\.$/);
});
it('stores all forecasts by default when no explicit max is configured', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', []);
const b = makePrediction('supply_chain', 'Red Sea', 'Shipping disruption: Red Sea', 0.68, 0.59, '7d', []);
buildForecastCase(a);
buildForecastCase(b);
populateFallbackNarratives([a, b]);
const artifacts = buildForecastTraceArtifacts(
{ generatedAt: Date.parse('2026-03-15T08:00:00Z'), predictions: [a, b] },
{ runId: 'run-all' },
{ basePrefix: 'forecast-runs' },
);
assert.equal(artifacts.manifest.forecastCount, 2);
assert.equal(artifacts.manifest.tracedForecastCount, 2);
assert.equal(artifacts.forecasts.length, 2);
});
it('summarizes fallback, enrichment, and domain quality across traced forecasts', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
]);
a.newsContext = ['Regional officials warn of retaliation risk'];
a.trend = 'rising';
buildForecastCase(a);
populateFallbackNarratives([a]);
a.traceMeta = { narrativeSource: 'llm_combined_cache', llmCached: true };
const b = makePrediction('cyber', 'China', 'Cyber threat concentration: China', 0.6, 0.52, '7d', [
{ type: 'cyber', value: 'Malware-hosting concentration remains elevated', weight: 0.4 },
{ type: 'news_corroboration', value: 'Security researchers warn of renewed activity', weight: 0.2 },
]);
b.trend = 'stable';
buildForecastCase(b);
populateFallbackNarratives([b]);
const artifacts = buildForecastTraceArtifacts(
{
generatedAt: Date.parse('2026-03-17T08:00:00Z'),
predictions: [a, b],
enrichmentMeta: {
selection: { candidateCount: 2, readinessEligibleCount: 2, selectedCombinedCount: 1, selectedScenarioCount: 1, reservedScenarioDomains: ['market'] },
combined: { requested: 1, source: 'live', provider: 'openrouter', model: 'google/gemini-2.5-flash', scenarios: 1, perspectives: 1, cases: 1, rawItemCount: 2, failureReason: '', succeeded: true },
scenario: { requested: 1, source: 'cache', provider: 'cache', model: 'cache', scenarios: 0, cases: 0, rawItemCount: 1, failureReason: '', succeeded: true },
},
},
{ runId: 'run-quality' },
{ basePrefix: 'forecast-runs' },
);
assert.equal(artifacts.summary.quality.traced.fallbackCount, 1);
assert.equal(artifacts.summary.quality.traced.enrichedCount, 1);
assert.equal(artifacts.summary.quality.traced.llmCombinedCount, 1);
assert.equal(artifacts.summary.quality.traced.llmScenarioCount, 0);
assert.equal(artifacts.summary.quality.fullRun.domainCounts.conflict, 1);
assert.equal(artifacts.summary.quality.fullRun.domainCounts.cyber, 1);
assert.ok(artifacts.summary.quality.traced.avgReadiness > 0);
assert.ok(artifacts.summary.quality.traced.topSuppressionSignals.length >= 1);
assert.equal(artifacts.summary.quality.enrichment.selection.selectedCombinedCount, 1);
assert.equal(artifacts.summary.quality.enrichment.combined.provider, 'openrouter');
assert.equal(artifacts.summary.quality.enrichment.combined.rawItemCount, 2);
assert.equal(artifacts.summary.quality.enrichment.scenario.rawItemCount, 1);
assert.equal(artifacts.summary.quality.enrichment.combined.failureReason, '');
});
it('projects published situations from the original full-run clusters without re-clustering ranked subsets', () => {
const a = makePrediction('market', 'Red Sea', 'Freight shock: Red Sea', 0.74, 0.61, '7d', [
{ type: 'chokepoint', value: 'Red Sea disruption detected', weight: 0.4 },
]);
const b = makePrediction('supply_chain', 'Hormuz', 'Shipping disruption: Hormuz', 0.71, 0.6, '7d', [
{ type: 'chokepoint', value: 'Hormuz disruption risk rising', weight: 0.4 },
]);
const c = makePrediction('market', 'Hormuz', 'Oil pricing pressure: Hormuz', 0.69, 0.58, '7d', [
{ type: 'commodity_price', value: 'Energy prices are moving higher', weight: 0.3 },
]);
const d = makePrediction('supply_chain', 'Red Sea', 'Container rerouting risk: Red Sea', 0.68, 0.57, '7d', [
{ type: 'shipping_delay', value: 'Freight rerouting remains elevated', weight: 0.3 },
]);
buildForecastCase(a);
buildForecastCase(b);
buildForecastCase(c);
buildForecastCase(d);
populateFallbackNarratives([a, b, c, d]);
const fullRunSituationClusters = attachSituationContext([a, b, c, d]);
const publishedPredictions = [a, c, d];
const projectedClusters = projectSituationClusters(fullRunSituationClusters, publishedPredictions);
attachSituationContext(publishedPredictions, projectedClusters);
refreshPublishedNarratives(publishedPredictions);
const projectedIds = new Set(projectedClusters.map((cluster) => cluster.id));
assert.equal(projectedClusters.reduce((sum, cluster) => sum + cluster.forecastCount, 0), publishedPredictions.length);
assert.ok(projectedIds.has(a.situationContext.id));
assert.ok(projectedIds.has(c.situationContext.id));
assert.ok(projectedIds.has(d.situationContext.id));
});
it('refreshes published narratives after shrinking a broader situation cluster', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
]);
const b = makePrediction('conflict', 'Iran', 'Retaliation risk: Iran', 0.7, 0.6, '7d', [
{ type: 'news_corroboration', value: 'Officials warn of retaliation risk', weight: 0.3 },
]);
buildForecastCase(a);
buildForecastCase(b);
const fullRunSituationClusters = attachSituationContext([a, b]);
populateFallbackNarratives([a, b]);
const publishedPredictions = [a];
const projectedClusters = projectSituationClusters(fullRunSituationClusters, publishedPredictions);
attachSituationContext(publishedPredictions, projectedClusters);
refreshPublishedNarratives(publishedPredictions);
assert.equal(a.caseFile.situationContext.forecastCount, 1);
assert.ok(!a.scenario.includes('broader cluster'));
assert.ok(!a.feedSummary.includes('broader'));
});
it('preserves llm narratives after projected situation context refresh', () => {
const a = makePrediction('market', 'Strait of Hormuz', 'Inflation and rates pressure from Strait of Hormuz maritime disruption state', 0.72, 0.66, '30d', [
{ type: 'shipping_cost_shock', value: 'Hormuz shipping costs are feeding inflation pressure', weight: 0.42 },
]);
const b = makePrediction('market', 'Strait of Hormuz', 'Oil price impact from Strait of Hormuz disruption', 0.67, 0.58, '30d', [
{ type: 'commodity_price', value: 'Oil pricing remains sensitive to Strait of Hormuz disruption', weight: 0.38 },
]);
buildForecastCase(a);
buildForecastCase(b);
populateFallbackNarratives([a, b]);
a.traceMeta = { narrativeSource: 'llm_combined', llmProvider: 'openrouter' };
a.caseFile.baseCase = 'LLM base case keeps Hormuz inflation pressure elevated while freight rerouting and insurance costs remain sticky.';
a.caseFile.escalatoryCase = 'LLM escalatory case sees a broader price shock if corridor access worsens again.';
a.caseFile.contrarianCase = 'LLM contrarian case assumes shipping normalization starts before downstream pass-through broadens.';
a.scenario = 'LLM scenario keeps Hormuz repricing elevated without a full break in corridor access.';
a.feedSummary = 'LLM base case keeps Hormuz inflation pressure elevated while freight rerouting and insurance costs remain sticky.';
const fullRunSituationClusters = attachSituationContext([a, b]);
const publishedPredictions = [a];
const projectedClusters = projectSituationClusters(fullRunSituationClusters, publishedPredictions);
attachSituationContext(publishedPredictions, projectedClusters);
refreshPublishedNarratives(publishedPredictions);
assert.equal(a.caseFile.situationContext.forecastCount, 1);
assert.equal(a.caseFile.baseCase, 'LLM base case keeps Hormuz inflation pressure elevated while freight rerouting and insurance costs remain sticky.');
assert.equal(a.scenario, 'LLM scenario keeps Hormuz repricing elevated without a full break in corridor access.');
assert.equal(a.feedSummary, 'LLM base case keeps Hormuz inflation pressure elevated while freight rerouting and insurance costs remain sticky.');
});
});
describe('market transmission macro state', () => {
it('uses live-shaped macro and market payloads to form energy-aware world signals and keep market consequences selective', () => {
const fredSeries = (seriesId, observations) => ({
seriesId,
title: seriesId,
observations: observations.map(([date, value]) => ({ date, value })),
});
const conflict = makePrediction('conflict', 'Middle East', 'Hormuz escalation risk', 0.73, 0.64, '7d', [
{ type: 'cii', value: 'Regional posture elevated', weight: 0.4 },
{ type: 'news', value: 'Hormuz pressure rising', weight: 0.25 },
]);
buildForecastCase(conflict);
const supply = makePrediction('supply_chain', 'Red Sea', 'Red Sea freight disruption', 0.69, 0.61, '7d', [
{ type: 'chokepoint', value: 'Red Sea disruption detected', weight: 0.45 },
{ type: 'shipping', value: 'Freight costs rising', weight: 0.25 },
]);
buildForecastCase(supply);
const political = makePrediction('political', 'United States', 'US sovereign risk repricing', 0.58, 0.56, '30d', [
{ type: 'macro', value: 'Rates and volatility remain elevated', weight: 0.3 },
]);
buildForecastCase(political);
populateFallbackNarratives([conflict, supply, political]);
const worldState = buildForecastRunWorldState({
predictions: [conflict, supply, political],
inputs: {
shippingRates: {
indices: [
{ indexId: 'wci-red-sea', name: 'Red Sea Freight Index', changePct: 11.4, spikeAlert: true },
],
},
commodityQuotes: {
quotes: [
{ symbol: 'CL=F', name: 'WTI Crude Oil', price: 87.4, change: 3.1 },
{ symbol: 'BZ=F', name: 'Brent Crude Oil', price: 92.8, change: 3.4 },
{ symbol: 'NG=F', name: 'Natural Gas', price: 3.9, change: 4.6 },
{ symbol: 'GC=F', name: 'Gold', price: 2450, change: 1.5 },
],
},
bisExchangeRates: {
exchange: {
rates: [
{ countryCode: 'TRY', countryName: 'Turkey', realChange: 3.2 },
],
},
},
bisPolicyRates: {
policy: {
rates: [
{ countryCode: 'BR', countryName: 'Brazil', rate: 11.25, previousRate: 10.75 },
],
},
exchange: {
rates: [
{ countryCode: 'MX', countryName: 'Mexico', realChange: 2.7 },
],
},
},
correlationCards: {
military: [
{ domain: 'military', title: 'Carrier posture and sanctions correlation' },
],
markets: [
{ domain: 'market', title: 'Economic sanctions and commodity correlation' },
],
},
fredSeries: {
VIXCLS: fredSeries('VIXCLS', [['2026-02-01', 18.2], ['2026-03-01', 23.4]]),
FEDFUNDS: fredSeries('FEDFUNDS', [['2026-02-01', 4.25], ['2026-03-01', 4.50]]),
T10Y2Y: fredSeries('T10Y2Y', [['2025-12-01', 0.55], ['2026-03-01', 0.08]]),
CPIAUCSL: fredSeries('CPIAUCSL', [
['2025-03-01', 312.0],
['2025-04-01', 312.6],
['2025-05-01', 313.1],
['2025-06-01', 313.8],
['2025-07-01', 314.4],
['2025-08-01', 315.1],
['2025-09-01', 315.8],
['2025-10-01', 316.2],
['2025-11-01', 317.0],
['2025-12-01', 318.2],
['2026-01-01', 319.3],
['2026-02-01', 320.6],
['2026-03-01', 321.8],
]),
UNRATE: fredSeries('UNRATE', [['2025-12-01', 3.9], ['2026-03-01', 4.2]]),
DGS10: fredSeries('DGS10', [['2026-02-01', 4.02], ['2026-03-01', 4.21]]),
WALCL: fredSeries('WALCL', [['2025-12-01', 6950], ['2026-03-01', 6760]]),
M2SL: fredSeries('M2SL', [['2025-09-01', 21400], ['2026-03-01', 21880]]),
GDP: fredSeries('GDP', [['2025-10-01', 28900], ['2026-01-01', 28940]]),
DCOILWTICO: fredSeries('DCOILWTICO', [['2026-01-20', 74.8], ['2026-03-01', 86.6]]),
},
},
});
const signalTypes = new Set((worldState.worldSignals?.signals || []).map((item) => item.type));
assert.ok(signalTypes.has('volatility_shock'));
assert.ok(signalTypes.has('yield_curve_stress'));
assert.ok(signalTypes.has('inflation_impulse'));
assert.ok(signalTypes.has('oil_macro_shock'));
assert.ok(signalTypes.has('global_crude_spread_stress'));
assert.ok(signalTypes.has('gas_supply_stress'));
assert.ok(signalTypes.has('safe_haven_bid'));
assert.ok(signalTypes.has('fx_stress'));
const buckets = new Map((worldState.marketState?.buckets || []).map((bucket) => [bucket.id, bucket]));
assert.ok((buckets.get('energy')?.pressureScore || 0) > 0.4);
assert.ok((buckets.get('freight')?.pressureScore || 0) > 0.35);
assert.ok((buckets.get('sovereign_risk')?.pressureScore || 0) > 0.25);
assert.ok((buckets.get('rates_inflation')?.macroConfirmation || 0) > 0);
assert.ok((buckets.get('fx_stress')?.macroConfirmation || 0) > 0);
assert.ok((buckets.get('energy')?.pressureScore || 0) >= (buckets.get('defense')?.pressureScore || 0));
const marketConsequences = worldState.simulationState?.marketConsequences;
assert.ok((marketConsequences?.internalCount || 0) >= (marketConsequences?.items?.length || 0));
assert.ok((marketConsequences?.items?.length || 0) <= 6);
assert.ok((marketConsequences?.blockedCount || 0) >= 1);
});
it('promotes direct core-bucket market consequences when critical signals are strong even if macro coverage is incomplete', () => {
const consequences = buildSimulationMarketConsequences({
situationSimulations: [
{
situationId: 'state-hormuz',
label: 'Hormuz closure pressure',
familyId: 'fam-hormuz',
familyLabel: 'Maritime supply shock',
dominantDomain: 'conflict',
dominantRegion: 'Middle East',
postureScore: 0.68,
avgConfidence: 0.58,
marketContext: {
linkedBucketIds: ['energy'],
confirmationScore: 0.57,
topTransmissionStrength: 0.62,
topTransmissionConfidence: 0.56,
topChannel: 'energy_supply_shock',
criticalSignalLift: 0.74,
criticalSignalTypes: ['energy_supply_shock', 'shipping_cost_shock', 'sovereign_stress'],
bucketContexts: {
energy: {
bucketId: 'energy',
bucketLabel: 'Energy',
edgeCount: 2,
topChannel: 'energy_supply_shock',
topTransmissionStrength: 0.66,
topTransmissionConfidence: 0.61,
supportingSignalIds: ['sig-energy', 'sig-route'],
supportingSignalTypes: ['energy_supply_shock', 'shipping_cost_shock'],
},
},
},
},
],
}, {
buckets: [
{
id: 'energy',
label: 'Energy',
pressureScore: 0.42,
confidence: 0.46,
macroConfirmation: 0.04,
},
],
}, {
marketInputCoverage: {
commodities: 14,
gulfQuotes: 12,
fredSeries: 0,
shippingRates: 0,
bisExchange: 0,
bisPolicy: 0,
correlationCards: 0,
},
});
assert.equal(consequences.items.length, 1);
assert.equal(consequences.items[0].targetBucketId, 'energy');
assert.ok((consequences.items[0].effectiveMacroConfirmation || 0) > 0.04);
assert.ok((consequences.items[0].criticalAlignment || 0) > 0.3);
assert.ok(!consequences.blocked.some((item) => item.reason === 'low_macro_confirmation'));
});
it('blocks direct energy consequences that only have sovereign-stress support', () => {
const consequences = buildSimulationMarketConsequences({
situationSimulations: [
{
situationId: 'state-brazil',
label: 'Brazil security escalation state',
familyId: 'fam-brazil',
familyLabel: 'Brazil security pressure family',
dominantDomain: 'conflict',
dominantRegion: 'Brazil',
postureScore: 0.71,
avgConfidence: 0.62,
marketContext: {
linkedBucketIds: ['energy'],
confirmationScore: 0.64,
topTransmissionStrength: 0.68,
topTransmissionConfidence: 0.59,
topChannel: 'sovereign_stress',
criticalSignalLift: 0.12,
criticalSignalTypes: ['sovereign_stress'],
bucketContexts: {
energy: {
bucketId: 'energy',
bucketLabel: 'Energy',
edgeCount: 2,
topChannel: 'sovereign_stress',
topTransmissionStrength: 0.68,
topTransmissionConfidence: 0.59,
supportingSignalIds: ['sig-sovereign'],
supportingSignalTypes: ['sovereign_stress'],
},
},
},
},
],
}, {
buckets: [
{
id: 'energy',
label: 'Energy',
pressureScore: 0.51,
confidence: 0.55,
macroConfirmation: 0.18,
},
],
}, {
marketInputCoverage: {
commodities: 12,
gulfQuotes: 8,
fredSeries: 10,
shippingRates: 0,
bisExchange: 0,
bisPolicy: 11,
correlationCards: 16,
},
});
assert.equal(consequences.items.length, 0);
assert.ok(consequences.blocked.some((item) => item.reason === 'inadmissible_bucket_channel'));
});
});
describe('publish selection', () => {
it('prefers unique state anchors before taking same-state follow-ons', () => {
const a = makePrediction('political', 'Middle East', 'State A political pressure', 0.71, 0.59, '7d', []);
const b = makePrediction('conflict', 'Middle East', 'State A conflict pressure', 0.69, 0.58, '7d', []);
const c = makePrediction('market', 'Red Sea', 'State B freight pressure', 0.63, 0.57, '7d', []);
for (const pred of [a, b, c]) {
pred.readiness = { overall: 0.74 };
pred.analysisPriority = 0.66;
pred.traceMeta = { narrativeSource: 'llm_combined' };
}
a.stateContext = { id: 'state-a', label: 'State A', dominantRegion: 'Middle East', dominantDomain: 'political', forecastCount: 3, topSignals: [{ type: 'sovereign_stress' }] };
b.stateContext = { id: 'state-a', label: 'State A', dominantRegion: 'Middle East', dominantDomain: 'conflict', forecastCount: 3, topSignals: [{ type: 'sovereign_stress' }] };
c.stateContext = { id: 'state-b', label: 'State B', dominantRegion: 'Red Sea', dominantDomain: 'market', forecastCount: 1, topSignals: [{ type: 'shipping_cost_shock' }] };
a.familyContext = { id: 'fam-a1', forecastCount: 1 };
b.familyContext = { id: 'fam-a2', forecastCount: 1 };
c.familyContext = { id: 'fam-b', forecastCount: 1 };
a.marketSelectionContext = { confirmationScore: 0.34, contradictionScore: 0, topBucketId: 'sovereign_risk', topBucketLabel: 'Sovereign Risk', topBucketPressure: 0.31, transmissionEdgeCount: 1, criticalSignalLift: 0.18, criticalSignalCount: 1, topChannel: 'political_pressure' };
b.marketSelectionContext = { confirmationScore: 0.36, contradictionScore: 0, topBucketId: 'sovereign_risk', topBucketLabel: 'Sovereign Risk', topBucketPressure: 0.34, transmissionEdgeCount: 1, criticalSignalLift: 0.2, criticalSignalCount: 1, topChannel: 'security_spillover' };
c.marketSelectionContext = { confirmationScore: 0.57, contradictionScore: 0, topBucketId: 'freight', topBucketLabel: 'Freight', topBucketPressure: 0.56, transmissionEdgeCount: 2, criticalSignalLift: 0.61, criticalSignalCount: 2, topChannel: 'shipping_cost_shock' };
const selected = selectPublishedForecastPool([a, b, c], { targetCount: 2 });
const selectedStateIds = selected.map((pred) => pred.stateContext?.id);
assert.deepEqual(selectedStateIds.sort(), ['state-a', 'state-b']);
assert.ok(selected.some((pred) => pred.id === c.id));
});
});
describe('state-driven domain derivation', () => {
it('derives market and supply-chain forecasts from strong state transmission when legacy detectors miss', () => {
const base = makePrediction('conflict', 'Red Sea', 'Escalation risk: Red Sea maritime pressure', 0.72, 0.61, '7d', [
{ type: 'shipping_cost_shock', value: 'Shipping costs are surging around the Red Sea corridor', weight: 0.4 },
{ type: 'energy_supply_shock', value: 'Energy flows remain exposed to Red Sea disruption', weight: 0.35 },
]);
base.stateContext = {
id: 'state-red-sea',
label: 'Red Sea maritime disruption state',
dominantRegion: 'Red Sea',
dominantDomain: 'conflict',
domains: ['conflict', 'infrastructure'],
topSignals: [{ type: 'shipping_cost_shock' }, { type: 'energy_supply_shock' }],
};
const derived = deriveStateDrivenForecasts({
existingPredictions: [base],
stateUnits: [
{
id: 'state-red-sea',
label: 'Red Sea maritime disruption state',
stateKind: 'transport_pressure',
dominantRegion: 'Red Sea',
dominantDomain: 'conflict',
regions: ['Red Sea'],
domains: ['conflict', 'infrastructure'],
actors: ['Regional shipping operators'],
branchKinds: ['base_case'],
signalTypes: ['shipping_cost_shock', 'energy_supply_shock', 'sovereign_stress'],
sourceSituationIds: ['sit-red-sea'],
situationIds: ['sit-red-sea'],
situationCount: 1,
forecastIds: [base.id],
forecastCount: 1,
avgProbability: 0.72,
avgConfidence: 0.61,
topSignals: [{ type: 'shipping_cost_shock', count: 3 }, { type: 'energy_supply_shock', count: 2 }],
sampleTitles: [base.title],
},
],
worldSignals: {
signals: [
{
id: 'sig-ship',
type: 'shipping_cost_shock',
sourceType: 'critical_news',
region: 'Red Sea',
macroRegion: 'EMEA',
strength: 0.74,
confidence: 0.68,
label: 'Red Sea shipping costs are surging',
},
{
id: 'sig-energy',
type: 'energy_supply_shock',
sourceType: 'critical_news',
region: 'Red Sea',
macroRegion: 'EMEA',
strength: 0.71,
confidence: 0.64,
label: 'Red Sea energy flows are at risk',
},
{
id: 'sig-sovereign',
type: 'sovereign_stress',
sourceType: 'critical_news',
region: 'Red Sea',
macroRegion: 'EMEA',
strength: 0.58,
confidence: 0.6,
label: 'Regional sovereign stress is rising',
},
],
},
marketTransmission: {
edges: [
{
sourceSituationId: 'state-red-sea',
sourceLabel: 'Red Sea maritime disruption state',
targetBucketId: 'freight',
targetLabel: 'Freight',
channel: 'shipping_cost_shock',
strength: 0.76,
confidence: 0.68,
supportingSignalIds: ['sig-ship', 'sig-energy'],
},
{
sourceSituationId: 'state-red-sea',
sourceLabel: 'Red Sea maritime disruption state',
targetBucketId: 'energy',
targetLabel: 'Energy',
channel: 'energy_supply_shock',
strength: 0.69,
confidence: 0.63,
supportingSignalIds: ['sig-energy', 'sig-ship'],
},
],
},
marketState: {
buckets: [
{
id: 'freight',
label: 'Freight',
pressureScore: 0.78,
confidence: 0.69,
macroConfirmation: 0.02,
},
{
id: 'energy',
label: 'Energy',
pressureScore: 0.74,
confidence: 0.66,
macroConfirmation: 0.03,
},
],
},
marketInputCoverage: {
commodities: 16,
gulfQuotes: 12,
shippingRates: 0,
fredSeries: 0,
bisExchange: 0,
bisPolicy: 0,
correlationCards: 0,
},
});
const derivedDomains = derived.map((pred) => pred.domain).sort();
assert.deepEqual(derivedDomains, ['market', 'supply_chain']);
assert.ok(derived.every((pred) => pred.generationOrigin === 'state_derived'));
assert.ok(derived.some((pred) => pred.title.includes('Energy repricing risk')));
assert.ok(derived.some((pred) => pred.title.includes('Supply chain disruption risk')));
assert.ok(derived.every((pred) => !pred.feedSummary.includes('pressure is')));
assert.ok(derived.every((pred) => !pred.feedSummary.endsWith('...')));
});
it('uses a state-derived backfill only when scores miss the main threshold but clear the fallback floor', () => {
const base = makePrediction('conflict', 'Red Sea', 'Escalation risk: constrained maritime pressure', 0.5, 0.45, '7d', [
{ type: 'energy_supply_shock', value: 'Energy flows remain exposed to Red Sea disruption', weight: 0.24 },
]);
base.stateContext = {
id: 'state-red-sea-fallback',
label: 'Red Sea constrained disruption state',
dominantRegion: 'Red Sea',
dominantDomain: 'conflict',
domains: ['conflict', 'infrastructure'],
topSignals: [{ type: 'energy_supply_shock' }],
};
const legacySupplyChain = makePrediction('supply_chain', 'Red Sea', 'Supply chain disruption: Red Sea corridor', 0.41, 0.39, '7d', [
{ type: 'shipping_cost_shock', value: 'Shipping costs remain elevated around the corridor', weight: 0.22 },
]);
legacySupplyChain.stateContext = {
id: 'state-red-sea-fallback',
label: 'Red Sea constrained disruption state',
dominantRegion: 'Red Sea',
dominantDomain: 'supply_chain',
domains: ['supply_chain'],
topSignals: [{ type: 'shipping_cost_shock' }],
};
const derived = deriveStateDrivenForecasts({
existingPredictions: [base, legacySupplyChain],
stateUnits: [
{
id: 'state-red-sea-fallback',
label: 'Red Sea constrained disruption state',
stateKind: 'transport_pressure',
dominantRegion: 'Red Sea',
dominantDomain: 'conflict',
regions: ['Red Sea'],
domains: ['conflict', 'infrastructure'],
actors: ['Regional shipping operators'],
branchKinds: ['base_case'],
signalTypes: ['energy_supply_shock', 'sovereign_stress'],
sourceSituationIds: ['sit-red-sea-fallback'],
situationIds: ['sit-red-sea-fallback'],
situationCount: 1,
forecastIds: [base.id, legacySupplyChain.id],
forecastCount: 2,
avgProbability: 0.42,
avgConfidence: 0.38,
topSignals: [{ type: 'energy_supply_shock', count: 2 }],
sampleTitles: [base.title, legacySupplyChain.title],
},
],
worldSignals: {
signals: [
{
id: 'sig-energy-soft',
type: 'energy_supply_shock',
sourceType: 'critical_news',
region: 'Red Sea',
macroRegion: 'EMEA',
strength: 0.24,
confidence: 0.28,
label: 'Red Sea energy flows remain exposed',
},
],
},
marketTransmission: {
edges: [
{
sourceSituationId: 'state-red-sea-fallback',
sourceLabel: 'Red Sea constrained disruption state',
targetBucketId: 'energy',
targetLabel: 'Energy',
channel: 'energy_supply_shock',
strength: 0.18,
confidence: 0.22,
supportingSignalIds: ['sig-energy-soft'],
},
],
},
marketState: {
buckets: [
{
id: 'energy',
label: 'Energy',
pressureScore: 0.35,
confidence: 0.36,
macroConfirmation: 0.02,
},
],
},
marketInputCoverage: {
commodities: 16,
gulfQuotes: 0,
shippingRates: 0,
fredSeries: 0,
bisExchange: 0,
bisPolicy: 0,
correlationCards: 0,
},
});
assert.equal(derived.length, 1);
assert.equal(derived[0].domain, 'market');
assert.equal(derived[0].generationOrigin, 'state_derived');
assert.equal(derived[0].stateDerivedBackfill, true);
});
it('does not derive a market forecast when the direct bucket only has an allowed but semantically mismatched channel', () => {
const base = makePrediction('conflict', 'Red Sea', 'Escalation risk: Red Sea maritime pressure', 0.69, 0.58, '7d', [
{ type: 'shipping_cost_shock', value: 'Shipping routes remain under pressure', weight: 0.35 },
]);
base.stateContext = {
id: 'state-red-sea-mismatch',
label: 'Red Sea maritime disruption state',
dominantRegion: 'Red Sea',
dominantDomain: 'conflict',
domains: ['conflict', 'supply_chain'],
topSignals: [{ type: 'shipping_cost_shock' }],
};
const derived = deriveStateDrivenForecasts({
existingPredictions: [base],
stateUnits: [
{
id: 'state-red-sea-mismatch',
label: 'Red Sea maritime disruption state',
stateKind: 'transport_pressure',
dominantRegion: 'Red Sea',
dominantDomain: 'conflict',
regions: ['Red Sea'],
domains: ['conflict', 'supply_chain'],
actors: ['Regional shipping operators'],
branchKinds: ['base_case'],
signalTypes: ['shipping_cost_shock'],
sourceSituationIds: ['sit-red-sea-mismatch'],
situationIds: ['sit-red-sea-mismatch'],
situationCount: 1,
forecastIds: [base.id],
forecastCount: 1,
avgProbability: 0.69,
avgConfidence: 0.58,
topSignals: [{ type: 'shipping_cost_shock', count: 3 }],
sampleTitles: [base.title],
},
],
worldSignals: {
signals: [
{
id: 'sig-ship-only',
type: 'shipping_cost_shock',
sourceType: 'critical_news',
region: 'Red Sea',
macroRegion: 'EMEA',
strength: 0.73,
confidence: 0.66,
label: 'Red Sea shipping costs are surging',
},
],
},
marketTransmission: {
edges: [
{
sourceSituationId: 'state-red-sea-mismatch',
sourceLabel: 'Red Sea maritime disruption state',
targetBucketId: 'energy',
targetLabel: 'Energy',
channel: 'shipping_cost_shock',
strength: 0.72,
confidence: 0.64,
supportingSignalIds: ['sig-ship-only'],
},
],
},
marketState: {
buckets: [
{
id: 'energy',
label: 'Energy',
pressureScore: 0.74,
confidence: 0.66,
macroConfirmation: 0.04,
},
],
},
marketInputCoverage: {
commodities: 14,
gulfQuotes: 10,
shippingRates: 0,
fredSeries: 0,
bisExchange: 0,
bisPolicy: 0,
correlationCards: 0,
},
});
assert.equal(derived.some((pred) => pred.domain === 'market'), false);
});
it('keeps state-derived market clustering coherent across source states and buckets', () => {
const indiaFx = makePrediction('market', 'India', 'FX stress from India cyber pressure state', 0.58, 0.56, '14d', [
{ type: 'risk_off_rotation', value: 'Risk-off pricing is pressuring India FX', weight: 0.36 },
]);
buildForecastCase(indiaFx);
indiaFx.stateDerivation = {
sourceStateId: 'state-india-fx',
sourceStateLabel: 'India cyber pressure state',
sourceStateKind: 'cyber_pressure',
bucketId: 'fx_stress',
bucketLabel: 'FX Stress',
channel: 'fx_stress',
macroRegion: 'SOUTH_ASIA',
};
const redSeaEnergy = makePrediction('market', 'Red Sea', 'Energy repricing risk from Red Sea maritime disruption state', 0.66, 0.59, '14d', [
{ type: 'energy_supply_shock', value: 'Red Sea disruption is pressuring energy flows', weight: 0.4 },
]);
buildForecastCase(redSeaEnergy);
redSeaEnergy.stateDerivation = {
sourceStateId: 'state-red-sea-maritime',
sourceStateLabel: 'Red Sea maritime disruption state',
sourceStateKind: 'transport_pressure',
bucketId: 'energy',
bucketLabel: 'Energy',
channel: 'energy_supply_shock',
macroRegion: 'MENA',
};
const redSeaFreight = makePrediction('supply_chain', 'Red Sea', 'Maritime energy flow disruption from Red Sea maritime disruption state', 0.64, 0.58, '14d', [
{ type: 'shipping_cost_shock', value: 'Freight routes are rerouting around the Red Sea corridor', weight: 0.39 },
]);
buildForecastCase(redSeaFreight);
redSeaFreight.stateDerivation = {
sourceStateId: 'state-red-sea-maritime',
sourceStateLabel: 'Red Sea maritime disruption state',
sourceStateKind: 'transport_pressure',
bucketId: 'freight',
bucketLabel: 'Freight',
channel: 'shipping_cost_shock',
macroRegion: 'MENA',
};
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-23T06:00:00Z'),
predictions: [indiaFx, redSeaEnergy, redSeaFreight],
});
const marketLikeClusters = (worldState.situationClusters || []).filter((cluster) => (
(cluster.domains || []).some((domain) => ['market', 'supply_chain'].includes(domain))
));
const indiaCluster = marketLikeClusters.find((cluster) => cluster.forecastIds.includes(indiaFx.id));
const redSeaCluster = marketLikeClusters.find((cluster) => cluster.forecastIds.includes(redSeaEnergy.id) || cluster.forecastIds.includes(redSeaFreight.id));
assert.equal(marketLikeClusters.length, 2);
assert.ok(indiaCluster);
assert.ok(redSeaCluster);
assert.equal(indiaCluster.forecastIds.includes(redSeaEnergy.id), false);
assert.equal(indiaCluster.forecastIds.includes(redSeaFreight.id), false);
assert.equal(redSeaCluster.forecastIds.includes(indiaFx.id), false);
assert.deepEqual(indiaCluster.sourceStateIds, ['state-india-fx']);
assert.deepEqual(redSeaCluster.sourceStateIds, ['state-red-sea-maritime']);
});
});
describe('forecast run world state', () => {
it('builds a canonical run-level world state artifact', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
{ type: 'news_corroboration', value: 'Regional officials warn of retaliation risk', weight: 0.3 },
]);
a.newsContext = ['Regional officials warn of retaliation risk'];
a.trend = 'rising';
a.priorProbability = 0.61;
buildForecastCase(a);
const b = makePrediction('market', 'Middle East', 'Oil price impact from Strait of Hormuz disruption', 0.52, 0.55, '30d', [
{ type: 'chokepoint', value: 'Strait of Hormuz remains disrupted', weight: 0.5 },
]);
b.trend = 'stable';
buildForecastCase(b);
populateFallbackNarratives([a, b]);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T12:00:00Z'),
predictions: [a, b],
priorWorldState: {
actorRegistry: [
{
id: 'Regional command authority:state',
name: 'Regional command authority',
category: 'state',
influenceScore: 0.3,
domains: ['conflict'],
regions: ['Iran'],
},
{
id: 'legacy:state',
name: 'Legacy Actor',
category: 'state',
influenceScore: 0.2,
domains: ['market'],
regions: ['Middle East'],
},
],
branchStates: [
{
id: `${a.id}:base`,
forecastId: a.id,
kind: 'base',
title: 'Base Branch',
projectedProbability: 0.62,
actorIds: ['Regional command authority:state'],
triggerSample: ['Old trigger'],
},
{
id: `${a.id}:contrarian`,
forecastId: a.id,
kind: 'contrarian',
title: 'Contrarian Branch',
projectedProbability: 0.55,
actorIds: ['Regional command authority:state'],
triggerSample: [],
},
],
},
});
assert.equal(worldState.version, 1);
assert.equal(worldState.domainStates.length, 2);
assert.ok(worldState.actorRegistry.length > 0);
assert.equal(worldState.branchStates.length, 6);
assert.equal(worldState.continuity.risingForecasts, 1);
assert.ok(worldState.summary.includes('2 active forecasts'));
assert.ok(worldState.evidenceLedger.supporting.length > 0);
assert.ok(worldState.actorContinuity.persistentCount >= 1);
assert.ok(worldState.actorContinuity.newlyActiveCount >= 1);
assert.ok(worldState.actorContinuity.newlyActivePreview.length >= 1);
assert.ok(worldState.actorContinuity.noLongerActivePreview.some(actor => actor.id === 'legacy:state'));
assert.ok(worldState.branchContinuity.persistentBranchCount >= 2);
assert.ok(worldState.branchContinuity.newBranchCount >= 1);
assert.ok(worldState.branchContinuity.strengthenedBranchCount >= 1);
assert.ok(worldState.branchContinuity.resolvedBranchCount >= 0);
assert.ok(worldState.situationClusters.length >= 1);
assert.ok(worldState.situationSummary.summary.includes('clustered situations'));
assert.ok(typeof worldState.situationContinuity.newSituationCount === 'number');
assert.ok(worldState.simulationState.summary.includes('deterministic rounds'));
assert.equal(worldState.simulationState.roundTransitions.length, 3);
assert.ok(worldState.simulationState.situationSimulations.length >= 1);
assert.ok(worldState.simulationState.situationSimulations.every((unit) => unit.rounds.length === 3));
assert.ok(worldState.report.summary.includes('leading domains'));
assert.ok(worldState.report.continuitySummary.includes('Actors:'));
assert.ok(worldState.report.simulationSummary.includes('deterministic rounds'));
assert.ok(worldState.report.simulationInputSummary.includes('simulation report inputs'));
assert.ok(worldState.report.regionalHotspots.length >= 1);
assert.ok(worldState.report.branchWatchlist.length >= 1);
assert.ok(Array.isArray(worldState.report.situationWatchlist));
assert.ok(Array.isArray(worldState.report.simulationWatchlist));
assert.ok(Array.isArray(worldState.report.simulationOutcomeSummaries));
assert.ok(Array.isArray(worldState.report.crossSituationEffects));
});
it('keeps broad non-maritime pressure states from merging across regions without a real spine', () => {
const germanyCyber = makePrediction('cyber', 'Germany', 'Cyber pressure: Germany telecom networks', 0.58, 0.56, '14d', [
{ type: 'cyber', value: 'Germany telecom intrusion pressure remains elevated.', weight: 0.38 },
]);
const usCyber = makePrediction('cyber', 'United States', 'Cyber pressure: United States grid networks', 0.57, 0.55, '14d', [
{ type: 'cyber', value: 'United States grid intrusion pressure remains elevated.', weight: 0.37 },
]);
buildForecastCase(germanyCyber);
buildForecastCase(usCyber);
populateFallbackNarratives([germanyCyber, usCyber]);
germanyCyber.caseFile.actors = [{ id: 'actor-germany-cert', name: 'German CERT', role: 'defender' }];
usCyber.caseFile.actors = [{ id: 'actor-us-grid', name: 'US Grid Operators', role: 'defender' }];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-23T10:30:00Z'),
predictions: [germanyCyber, usCyber],
});
assert.equal(
worldState.situationClusters.some((cluster) => cluster.regions.includes('Germany') && cluster.regions.includes('United States')),
false,
);
assert.equal(
worldState.stateUnits.some((unit) => unit.regions.includes('Germany') && unit.regions.includes('United States')),
false,
);
});
it('reports full actor continuity counts even when previews are capped', () => {
const predictions = [
makePrediction('conflict', 'Region A', 'Escalation risk: Region A', 0.6, 0.6, '7d', [
{ type: 'cii', value: 'Conflict signal', weight: 0.4 },
]),
makePrediction('market', 'Region B', 'Oil price impact: Region B', 0.6, 0.6, '7d', [
{ type: 'prediction_market', value: 'Market stress', weight: 0.4 },
]),
makePrediction('cyber', 'Region C', 'Cyber threat concentration: Region C', 0.6, 0.6, '7d', [
{ type: 'cyber', value: 'Cyber signal', weight: 0.4 },
]),
];
for (const pred of predictions) buildForecastCase(pred);
const priorWorldState = {
actorRegistry: [],
};
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T12:00:00Z'),
predictions,
priorWorldState,
});
assert.ok(worldState.actorContinuity.newlyActiveCount > 8);
assert.equal(worldState.actorContinuity.newlyActivePreview.length, 8);
});
it('tracks situation continuity across runs', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.72, 0.63, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
{ type: 'ucdp', value: '3 UCDP conflict events', weight: 0.3 },
]);
a.newsContext = ['Regional officials warn of retaliation risk'];
a.trend = 'rising';
buildForecastCase(a);
const b = makePrediction('market', 'Middle East', 'Oil price impact from Strait of Hormuz disruption', 0.55, 0.57, '30d', [
{ type: 'prediction_market', value: 'Oil contracts reprice on Strait of Hormuz risk', weight: 0.4 },
{ type: 'chokepoint', value: 'Strait of Hormuz remains disrupted', weight: 0.3 },
]);
b.trend = 'rising';
buildForecastCase(b);
const currentWorldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T14:00:00Z'),
predictions: [a, b],
priorWorldState: {
situationClusters: [
{
id: 'sit-legacy',
label: 'Legacy: resolved pressure',
forecastCount: 1,
avgProbability: 0.22,
regions: ['Elsewhere'],
domains: ['political'],
actors: ['legacy:actor'],
},
],
},
});
const priorWorldState = {
situationClusters: currentWorldState.situationClusters.map((cluster) => ({
...cluster,
avgProbability: +(cluster.avgProbability - 0.12).toFixed(3),
forecastCount: Math.max(1, cluster.forecastCount - 1),
})),
};
const nextWorldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T15:00:00Z'),
predictions: [a, b],
priorWorldState,
priorWorldStates: [priorWorldState],
});
assert.ok(nextWorldState.situationContinuity.persistentSituationCount >= 1);
assert.ok(nextWorldState.situationContinuity.strengthenedSituationCount >= 1);
assert.ok(nextWorldState.report.continuitySummary.includes('Situations:'));
assert.ok(nextWorldState.report.situationWatchlist.length >= 1);
assert.ok(nextWorldState.reportContinuity.summary.includes('last'));
});
it('keeps situation continuity stable when a cluster expands with a new earlier-sorting actor', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.72, 0.63, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
]);
a.newsContext = ['Regional officials warn of retaliation risk'];
a.trend = 'rising';
buildForecastCase(a);
const priorWorldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T14:00:00Z'),
predictions: [a],
});
const currentPrediction = structuredClone(a);
currentPrediction.caseFile = structuredClone(a.caseFile);
currentPrediction.caseFile.actors = [
{
id: 'aaa-new-actor:state',
name: 'AAA New Actor',
category: 'state',
influenceScore: 0.7,
domains: ['conflict'],
regions: ['Iran'],
role: 'AAA New Actor is a primary state actor.',
objectives: ['Shape the conflict path.'],
constraints: ['Public escalation is costly.'],
likelyActions: ['Increase visible coordination.'],
},
...(currentPrediction.caseFile.actors || []),
];
const nextWorldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T15:00:00Z'),
predictions: [currentPrediction],
priorWorldState,
priorWorldStates: [priorWorldState],
});
assert.equal(nextWorldState.situationContinuity.newSituationCount, 0);
assert.ok(nextWorldState.situationContinuity.persistentSituationCount >= 1);
});
it('summarizes report continuity across recent world-state history', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
]);
a.newsContext = ['Regional officials warn of retaliation risk'];
buildForecastCase(a);
const baseState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T10:00:00Z'),
predictions: [a],
});
const strongerState = {
...baseState,
generatedAt: Date.parse('2026-03-17T11:00:00Z'),
generatedAtIso: '2026-03-17T11:00:00.000Z',
situationClusters: baseState.situationClusters.map((cluster) => ({
...cluster,
avgProbability: +(cluster.avgProbability - 0.08).toFixed(3),
forecastCount: Math.max(1, cluster.forecastCount - 1),
})),
};
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T12:00:00Z'),
predictions: [a],
priorWorldState: strongerState,
priorWorldStates: [strongerState, baseState],
});
assert.ok(worldState.reportContinuity.history.length >= 2);
assert.ok(worldState.reportContinuity.persistentPressureCount >= 1);
assert.equal(worldState.reportContinuity.repeatedStrengtheningCount, 0);
assert.ok(Array.isArray(worldState.report.continuityWatchlist));
});
it('matches report continuity when historical situation ids drift from cluster expansion', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
]);
a.newsContext = ['Regional officials warn of retaliation risk'];
buildForecastCase(a);
const priorState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T10:00:00Z'),
predictions: [a],
});
const expandedPrediction = structuredClone(a);
expandedPrediction.caseFile = structuredClone(a.caseFile);
expandedPrediction.caseFile.actors = [
{
id: 'aaa-new-actor:state',
name: 'AAA New Actor',
category: 'state',
influenceScore: 0.7,
domains: ['conflict'],
regions: ['Iran'],
role: 'AAA New Actor is a primary state actor.',
objectives: ['Shape the conflict path.'],
constraints: ['Public escalation is costly.'],
likelyActions: ['Increase visible coordination.'],
},
...(expandedPrediction.caseFile.actors || []),
];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T11:00:00Z'),
predictions: [expandedPrediction],
priorWorldState: priorState,
priorWorldStates: [priorState],
});
assert.equal(worldState.reportContinuity.emergingPressureCount, 0);
assert.equal(worldState.reportContinuity.fadingPressureCount, 0);
assert.ok(worldState.reportContinuity.persistentPressureCount >= 1);
});
it('marks fading pressures for situations present in prior state but absent from current run', () => {
const a = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
]);
buildForecastCase(a);
const baseState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T10:00:00Z'),
predictions: [a],
});
// Inject a synthetic cluster into the prior state that will not be present in the current run
const priorState = {
...baseState,
generatedAt: Date.parse('2026-03-17T10:00:00Z'),
situationClusters: [
...baseState.situationClusters,
{
id: 'sit-redseafade-test',
label: 'Red Sea: Shipping disruption fading',
domain: 'supply_chain',
regionIds: ['red_sea'],
actorIds: [],
forecastIds: ['fc-supply_chain-redseafade'],
avgProbability: 0.55,
forecastCount: 1,
},
],
};
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-17T11:00:00Z'),
predictions: [a],
priorWorldState: priorState,
priorWorldStates: [priorState],
});
assert.ok(worldState.reportContinuity.fadingPressureCount >= 1);
assert.ok(worldState.reportContinuity.fadingPressurePreview.length >= 1);
assert.ok(worldState.reportContinuity.fadingPressurePreview.every(
(s) => typeof s.avgProbability === 'number' && typeof s.forecastCount === 'number',
));
assert.ok(worldState.reportContinuity.persistentPressureCount >= 1);
});
it('does not collapse unrelated cross-country conflict and political forecasts into one giant situation', () => {
const conflictIran = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'ucdp', value: '27 conflict events in Iran', weight: 0.4 },
]);
conflictIran.newsContext = ['Regional officials warn of retaliation risk'];
buildForecastCase(conflictIran);
const conflictBrazil = makePrediction('conflict', 'Brazil', 'Active armed conflict: Brazil', 0.68, 0.44, '7d', [
{ type: 'ucdp', value: '18 conflict events in Brazil', weight: 0.35 },
]);
conflictBrazil.newsContext = ['Security operations intensify in Brazil'];
buildForecastCase(conflictBrazil);
const politicalTurkey = makePrediction('political', 'Turkey', 'Political instability: Turkey', 0.43, 0.52, '14d', [
{ type: 'news_corroboration', value: 'Cabinet tensions intensify in Turkey', weight: 0.3 },
]);
politicalTurkey.newsContext = ['Opposition parties escalate criticism in Turkey'];
buildForecastCase(politicalTurkey);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-18T22:00:00Z'),
predictions: [conflictIran, conflictBrazil, politicalTurkey],
});
assert.ok(worldState.situationClusters.length >= 2);
assert.ok(worldState.situationClusters.every((cluster) => cluster.forecastCount <= 2));
assert.ok(worldState.situationClusters.every((cluster) => cluster.label.endsWith('situation')));
});
it('does not describe a lower-probability situation as strengthened just because it expanded', () => {
const prediction = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'cii', value: 'Iran CII 79 (high)', weight: 0.4 },
]);
prediction.newsContext = ['Regional officials warn of retaliation risk'];
buildForecastCase(prediction);
const priorWorldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-18T10:00:00Z'),
predictions: [prediction],
});
const currentPrediction = structuredClone(prediction);
currentPrediction.caseFile = structuredClone(prediction.caseFile);
currentPrediction.probability = 0.62;
currentPrediction.caseFile.actors = [
{
id: 'new-actor:state',
name: 'New Actor',
category: 'state',
influenceScore: 0.7,
role: 'New Actor is newly engaged.',
objectives: ['Shape the path.'],
constraints: ['Public escalation is costly.'],
likelyActions: ['Increase visible coordination.'],
},
...(currentPrediction.caseFile.actors || []),
];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-18T11:00:00Z'),
predictions: [currentPrediction],
priorWorldState,
priorWorldStates: [priorWorldState],
});
assert.equal(worldState.situationContinuity.strengthenedSituationCount, 0);
assert.ok(worldState.report.situationWatchlist.every((item) => item.type !== 'strengthened_situation'));
});
it('builds deterministic simulation units and round transitions from clustered situations', () => {
const conflict = makePrediction('conflict', 'Israel', 'Active armed conflict: Israel', 0.76, 0.66, '7d', [
{ type: 'ucdp', value: 'Israeli theater remains active', weight: 0.4 },
{ type: 'news_corroboration', value: 'Regional actors prepare responses', weight: 0.2 },
]);
conflict.newsContext = ['Regional actors prepare responses'];
buildForecastCase(conflict);
const supply = makePrediction('supply_chain', 'Eastern Mediterranean', 'Shipping disruption: Eastern Mediterranean', 0.59, 0.55, '14d', [
{ type: 'chokepoint', value: 'Shipping reroutes through the Eastern Mediterranean', weight: 0.4 },
]);
buildForecastCase(supply);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T08:00:00Z'),
predictions: [conflict, supply],
});
assert.ok(worldState.simulationState.totalSituationSimulations >= 2);
assert.equal(worldState.simulationState.totalRounds, 3);
assert.ok(worldState.simulationState.roundTransitions.every((round) => round.situationCount >= 1));
assert.ok(Array.isArray(worldState.simulationState.actionLedger));
assert.ok(worldState.simulationState.actionLedger.length >= 2);
assert.ok(Array.isArray(worldState.simulationState.replayTimeline));
assert.equal(worldState.simulationState.replayTimeline.length, 3);
assert.ok(worldState.simulationState.situationSimulations.every((unit) => ['escalatory', 'contested', 'constrained'].includes(unit.posture)));
assert.ok(worldState.simulationState.situationSimulations.every((unit) => unit.rounds.every((round) => typeof round.netPressure === 'number')));
assert.ok(worldState.simulationState.situationSimulations.every((unit) => Array.isArray(unit.actionPlan) && unit.actionPlan.length === 3));
assert.ok(worldState.simulationState.situationSimulations.every((unit) => unit.actionPlan.every((round) => Array.isArray(round.actions))));
});
it('derives differentiated simulation postures from actor actions, branches, and counter-evidence', () => {
const escalatory = makePrediction('conflict', 'Israel', 'Active armed conflict: Israel', 0.88, 0.71, '7d', [
{ type: 'ucdp', value: 'Israeli theater remains highly active', weight: 0.45 },
{ type: 'news_corroboration', value: 'Regional actors prepare responses', weight: 0.3 },
]);
buildForecastCase(escalatory);
const constrained = makePrediction('infrastructure', 'Cuba', 'Infrastructure cascade risk: Cuba', 0.28, 0.44, '14d', [
{ type: 'outage', value: 'Localized outages remain contained', weight: 0.2 },
]);
buildForecastCase(constrained);
constrained.caseFile.counterEvidence = [
{ type: 'confidence', summary: 'Confidence remains limited and the pattern is not yet broad.', weight: 0.3 },
{ type: 'coverage_gap', summary: 'Cross-system corroboration is still thin.', weight: 0.25 },
{ type: 'trend', summary: 'Momentum is already easing.', weight: 0.25 },
];
constrained.caseFile.actors = (constrained.caseFile.actors || []).map((actor) => ({
...actor,
likelyActions: ['Maintain continuity around exposed nodes.'],
constraints: ['Containment remains the priority and escalation is costly.'],
}));
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T13:00:00Z'),
predictions: [escalatory, constrained],
});
const escalatoryUnit = worldState.simulationState.situationSimulations.find((unit) => unit.label.includes('Israel'));
const constrainedUnit = worldState.simulationState.situationSimulations.find((unit) => unit.label.includes('Cuba'));
assert.equal(escalatoryUnit?.posture, 'escalatory');
assert.equal(constrainedUnit?.posture, 'constrained');
assert.ok(escalatoryUnit?.rounds.some((round) => (round.actionMix?.pressure || 0) > (round.actionMix?.stabilizing || 0)));
assert.ok(constrainedUnit?.rounds.some((round) => (round.actionMix?.stabilizing || 0) >= (round.actionMix?.pressure || 0)));
});
it('keeps moderate market and supply-chain situations contested unless pressure compounds strongly', () => {
const market = makePrediction('market', 'Japan', 'Oil price impact: Japan', 0.58, 0.56, '30d', [
{ type: 'prediction_market', value: 'Oil contracts reprice on Japan energy risk', weight: 0.3 },
{ type: 'commodity_price', value: 'Energy prices are drifting higher', weight: 0.2 },
]);
buildForecastCase(market);
const supply = makePrediction('supply_chain', 'Red Sea', 'Shipping disruption: Red Sea', 0.55, 0.54, '14d', [
{ type: 'chokepoint', value: 'Shipping reroutes remain elevated', weight: 0.3 },
]);
buildForecastCase(supply);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T13:30:00Z'),
predictions: [market, supply],
});
const marketUnit = worldState.simulationState.situationSimulations.find((unit) => unit.label.includes('Japan'));
const supplyUnit = worldState.simulationState.situationSimulations.find((unit) => unit.label.includes('Red Sea'));
assert.equal(marketUnit?.posture, 'contested');
assert.equal(supplyUnit?.posture, 'contested');
assert.ok((marketUnit?.postureScore || 0) < 0.77);
assert.ok((supplyUnit?.postureScore || 0) < 0.77);
assert.ok((marketUnit?.marketContext?.confirmationScore || 0) > 0);
assert.ok((supplyUnit?.marketContext?.linkedBucketIds || []).length >= 1);
assert.equal(worldState.simulationState.marketConsequences?.reportableCount || 0, 0);
assert.ok((worldState.simulationState.marketConsequences?.blockedCount || 0) >= 1);
});
it('builds report outputs from simulation outcomes and cross-situation effects', () => {
const conflict = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.79, 0.67, '7d', [
{ type: 'ucdp', value: 'Conflict intensity remains elevated in Iran', weight: 0.4 },
{ type: 'news_corroboration', value: 'Regional actors prepare for reprisals', weight: 0.3 },
]);
conflict.newsContext = ['Regional actors prepare for reprisals'];
buildForecastCase(conflict);
conflict.caseFile.actors = [
{
id: 'shared-energy-actor',
name: 'Shared Energy Actor',
category: 'market_participant',
influenceScore: 0.7,
domains: ['conflict', 'market'],
regions: ['Iran', 'Japan'],
objectives: ['Preserve energy flows'],
constraints: ['Cannot absorb prolonged disruption'],
likelyActions: ['Reprice energy exposure'],
},
...(conflict.caseFile.actors || []),
];
const market = makePrediction('market', 'Japan', 'Oil price impact: Japan', 0.61, 0.57, '30d', [
{ type: 'prediction_market', value: 'Oil contracts reprice on Japan energy risk', weight: 0.4 },
{ type: 'chokepoint', value: 'Strait of Hormuz remains exposed', weight: 0.2 },
]);
market.newsContext = ['Oil traders price escalation risk across Japan'];
buildForecastCase(market);
market.caseFile.actors = [
{
id: 'shared-energy-actor',
name: 'Shared Energy Actor',
category: 'market_participant',
influenceScore: 0.7,
domains: ['conflict', 'market'],
regions: ['Iran', 'Japan'],
objectives: ['Preserve energy flows'],
constraints: ['Cannot absorb prolonged disruption'],
likelyActions: ['Reprice energy exposure'],
},
...(market.caseFile.actors || []),
];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T10:00:00Z'),
predictions: [conflict, market],
});
assert.ok(worldState.report.simulationOutcomeSummaries.length >= 2);
assert.ok(worldState.report.simulationOutcomeSummaries.every((item) => item.rounds.length === 3));
assert.ok(worldState.report.simulationOutcomeSummaries.every((item) => ['escalatory', 'contested', 'constrained'].includes(item.posture)));
assert.ok(worldState.simulationState.interactionLedger.length >= 1);
assert.ok(worldState.simulationState.replayTimeline.some((item) => item.interactionCount >= 1));
assert.ok(worldState.report.crossSituationEffects.length >= 1);
assert.ok(worldState.report.crossSituationEffects.some((item) => item.summary.includes('Japan')));
assert.ok(worldState.report.crossSituationEffects.every((item) => item.channel));
assert.ok(worldState.report.interactionWatchlist.length >= 1);
assert.ok(worldState.report.replayWatchlist.length === 3);
assert.ok(worldState.simulationState.situationSimulations.every((item) => item.familyId));
});
it('does not synthesize cross-situation effects for unrelated theaters with no overlap', () => {
const brazilConflict = makePrediction('conflict', 'Brazil', 'Active armed conflict: Brazil', 0.77, 0.65, '7d', [
{ type: 'ucdp', value: 'Brazil conflict intensity remains elevated', weight: 0.4 },
]);
buildForecastCase(brazilConflict);
const japanMarket = makePrediction('market', 'Japan', 'Market repricing: Japan', 0.58, 0.54, '30d', [
{ type: 'prediction_market', value: 'Japanese markets price regional risk', weight: 0.4 },
]);
buildForecastCase(japanMarket);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T11:00:00Z'),
predictions: [brazilConflict, japanMarket],
});
assert.equal(worldState.report.crossSituationEffects.length, 0);
});
it('uses the true dominant domain when deriving simulation report inputs and effects', () => {
const supplyA = makePrediction('supply_chain', 'Middle East', 'Shipping disruption: Middle East', 0.66, 0.57, '14d', [
{ type: 'chokepoint', value: 'Regional shipping remains disrupted', weight: 0.4 },
]);
supplyA.newsContext = ['Middle East shipping disruption expands'];
buildForecastCase(supplyA);
const supplyB = makePrediction('supply_chain', 'Middle East', 'Logistics delay: Middle East', 0.62, 0.55, '14d', [
{ type: 'chokepoint', value: 'Logistics routes remain congested', weight: 0.35 },
]);
supplyB.newsContext = ['Middle East shipping disruption expands'];
buildForecastCase(supplyB);
const market = makePrediction('market', 'Middle East', 'Oil price impact: Middle East', 0.57, 0.53, '30d', [
{ type: 'prediction_market', value: 'Oil contracts reprice on logistics risk', weight: 0.3 },
]);
market.newsContext = ['Middle East shipping disruption expands'];
buildForecastCase(market);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T12:00:00Z'),
predictions: [supplyA, supplyB, market],
});
const dominantInput = worldState.report.simulationOutcomeSummaries.find((item) => item.label.includes('Middle East'));
const dominantSimulation = worldState.simulationState.situationSimulations.find((item) => item.label.includes('Middle East'));
assert.equal(dominantSimulation?.dominantDomain, 'supply_chain');
assert.ok(dominantInput);
});
it('builds broader situation families above individual situations', () => {
const conflict = makePrediction('conflict', 'Israel', 'Active armed conflict: Israel', 0.76, 0.66, '7d', [
{ type: 'ucdp', value: 'Israeli theater remains active', weight: 0.4 },
]);
conflict.newsContext = ['Regional actors prepare responses'];
buildForecastCase(conflict);
const market = makePrediction('market', 'Middle East', 'Oil price impact: Middle East', 0.59, 0.56, '30d', [
{ type: 'prediction_market', value: 'Energy traders reprice risk', weight: 0.35 },
]);
market.newsContext = ['Regional actors prepare responses'];
buildForecastCase(market);
const supply = makePrediction('supply_chain', 'Eastern Mediterranean', 'Shipping disruption: Eastern Mediterranean', 0.57, 0.54, '14d', [
{ type: 'chokepoint', value: 'Shipping reroutes continue', weight: 0.35 },
]);
supply.newsContext = ['Regional actors prepare responses'];
buildForecastCase(supply);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T12:30:00Z'),
predictions: [conflict, market, supply],
});
assert.ok(worldState.situationClusters.length >= 2);
assert.ok(worldState.situationFamilies.length >= 1);
assert.ok(worldState.situationFamilies.length <= worldState.situationClusters.length);
assert.ok(worldState.report.familyWatchlist.length >= 1);
});
it('does not synthesize cross-situation effects from family membership alone', () => {
const source = makePrediction('conflict', 'Iran', 'Escalation risk: Iran', 0.74, 0.64, '7d', [
{ type: 'ucdp', value: 'Iran theater remains active', weight: 0.4 },
]);
source.newsContext = ['Regional actors prepare responses'];
buildForecastCase(source);
const target = makePrediction('market', 'Japan', 'Market repricing: Japan', 0.58, 0.55, '30d', [
{ type: 'prediction_market', value: 'Japan markets price energy risk', weight: 0.35 },
]);
target.newsContext = ['Regional actors prepare responses'];
buildForecastCase(target);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T12:45:00Z'),
predictions: [source, target],
});
const patchedSimulationState = structuredClone(worldState.simulationState);
for (const unit of patchedSimulationState.situationSimulations || []) {
unit.familyId = 'fam-shared-test';
unit.familyLabel = 'Shared test family';
}
const effects = buildCrossSituationEffects(patchedSimulationState);
assert.equal(effects.length, 0);
});
it('does not emit cross-situation effects from constrained low-energy infrastructure situations', () => {
const cuba = makePrediction('infrastructure', 'Cuba', 'Infrastructure degradation: Cuba', 0.29, 0.45, '14d', [
{ type: 'outage', value: 'Localized infrastructure outages remain contained in Cuba', weight: 0.25 },
]);
buildForecastCase(cuba);
cuba.caseFile.actors = [
{
id: 'shared-grid-operator',
name: 'Shared Grid Operator',
category: 'infrastructure_operator',
influenceScore: 0.45,
domains: ['infrastructure'],
regions: ['Cuba', 'Iran'],
objectives: ['Maintain continuity'],
constraints: ['Containment remains the priority.'],
likelyActions: ['Maintain service continuity around exposed nodes.'],
},
];
const iran = makePrediction('infrastructure', 'Iran', 'Infrastructure degradation: Iran', 0.31, 0.46, '14d', [
{ type: 'outage', value: 'Localized infrastructure outages remain contained in Iran', weight: 0.25 },
]);
buildForecastCase(iran);
iran.caseFile.actors = [
{
id: 'shared-grid-operator',
name: 'Shared Grid Operator',
category: 'infrastructure_operator',
influenceScore: 0.45,
domains: ['infrastructure'],
regions: ['Cuba', 'Iran'],
objectives: ['Maintain continuity'],
constraints: ['Containment remains the priority.'],
likelyActions: ['Maintain service continuity around exposed nodes.'],
},
];
iran.caseFile.counterEvidence = [
{ type: 'containment', summary: 'Containment actions are limiting broader spread.', weight: 0.35 },
];
cuba.caseFile.counterEvidence = [
{ type: 'containment', summary: 'Containment actions are limiting broader spread.', weight: 0.35 },
];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T13:20:00Z'),
predictions: [cuba, iran],
});
assert.ok((worldState.simulationState.situationSimulations || []).every((item) => item.posture === 'constrained'));
assert.equal(worldState.report.crossSituationEffects.length, 0);
});
it('allows cyber sources above the domain constrained threshold to emit direct effects', () => {
const cyber = makePrediction('cyber', 'Poland', 'Cyber disruption risk: Poland', 0.46, 0.54, '14d', [
{ type: 'cyber', value: 'Cyber disruption pressure remains elevated across Poland', weight: 0.35 },
]);
buildForecastCase(cyber);
cyber.caseFile.actors = [
{
id: 'shared-cyber-actor',
name: 'Shared Cyber Actor',
category: 'state_actor',
influenceScore: 0.6,
domains: ['cyber', 'infrastructure'],
regions: ['Poland', 'Baltic States'],
objectives: ['Sustain pressure against exposed systems'],
constraints: ['Avoid overt escalation'],
likelyActions: ['Coordinate cyber pressure against exposed infrastructure.'],
},
];
const infrastructure = makePrediction('infrastructure', 'Baltic States', 'Infrastructure disruption risk: Baltic States', 0.41, 0.52, '14d', [
{ type: 'outage', value: 'Infrastructure resilience is under pressure in the Baltic States', weight: 0.3 },
]);
buildForecastCase(infrastructure);
infrastructure.caseFile.actors = [
{
id: 'shared-cyber-actor',
name: 'Shared Cyber Actor',
category: 'state_actor',
influenceScore: 0.6,
domains: ['cyber', 'infrastructure'],
regions: ['Poland', 'Baltic States'],
objectives: ['Sustain pressure against exposed systems'],
constraints: ['Avoid overt escalation'],
likelyActions: ['Coordinate cyber pressure against exposed infrastructure.'],
},
];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T13:25:00Z'),
predictions: [cyber, infrastructure],
});
const patchedSimulationState = structuredClone(worldState.simulationState);
const cyberUnit = patchedSimulationState.situationSimulations.find((item) => item.label.includes('Poland'));
assert.ok(cyberUnit);
cyberUnit.posture = 'contested';
cyberUnit.postureScore = 0.394;
cyberUnit.totalPressure = 0.62;
cyberUnit.totalStabilization = 0.31;
cyberUnit.effectChannels = [{ type: 'cyber_disruption', count: 2 }];
const effects = buildCrossSituationEffects(patchedSimulationState);
assert.ok(effects.some((item) => item.channel === 'cyber_disruption'));
});
it('keeps direct regional spillovers when a source only contributes one matching channel but has direct overlap', () => {
const cyber = makePrediction('cyber', 'Estonia', 'Cyber pressure: Estonia', 0.47, 0.53, '14d', [
{ type: 'cyber', value: 'Regional cyber pressure remains elevated around Estonia', weight: 0.32 },
]);
buildForecastCase(cyber);
cyber.caseFile.actors = [
{
id: 'shared-regional-actor',
name: 'Shared Regional Actor',
category: 'state_actor',
influenceScore: 0.58,
domains: ['cyber', 'political'],
regions: ['Estonia', 'Latvia'],
objectives: ['Shape regional posture'],
constraints: ['Avoid direct confrontation'],
likelyActions: ['Manage broader regional effects from Estonia.'],
},
];
const political = makePrediction('political', 'Latvia', 'Political pressure: Latvia', 0.44, 0.52, '14d', [
{ type: 'policy_change', value: 'Political pressure is building in Latvia', weight: 0.3 },
]);
buildForecastCase(political);
political.caseFile.actors = [
{
id: 'shared-regional-actor',
name: 'Shared Regional Actor',
category: 'state_actor',
influenceScore: 0.58,
domains: ['cyber', 'political'],
regions: ['Estonia', 'Latvia'],
objectives: ['Shape regional posture'],
constraints: ['Avoid direct confrontation'],
likelyActions: ['Manage broader regional effects from Estonia.'],
},
];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T13:30:00Z'),
predictions: [cyber, political],
});
const patchedSimulationState = structuredClone(worldState.simulationState);
const cyberUnit = patchedSimulationState.situationSimulations.find((item) => item.label.includes('Estonia'));
assert.ok(cyberUnit);
cyberUnit.posture = 'contested';
cyberUnit.postureScore = 0.422;
cyberUnit.totalPressure = 0.59;
cyberUnit.totalStabilization = 0.28;
cyberUnit.effectChannels = [{ type: 'regional_spillover', count: 2 }];
patchedSimulationState.interactionLedger = (patchedSimulationState.interactionLedger || []).map((item) => ({
...item,
confidence: 0.94,
actorSpecificity: 0.95,
sharedActor: true,
}));
const effects = buildCrossSituationEffects(patchedSimulationState, { mode: 'internal' });
assert.ok(effects.some((item) => item.channel === 'regional_spillover' && item.relation === 'regional pressure transfer'));
});
it('emits reverse-direction effects when only the later-listed situation can drive the target', () => {
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T14:05:00Z'),
predictions: [
makePrediction('infrastructure', 'Romania', 'Infrastructure pressure: Romania', 0.34, 0.48, '14d', [
{ type: 'outage', value: 'Romania infrastructure remains contained', weight: 0.24 },
]),
makePrediction('market', 'Black Sea', 'Market repricing: Black Sea', 0.57, 0.56, '14d', [
{ type: 'prediction_market', value: 'Black Sea pricing reacts to service disruption risk', weight: 0.36 },
]),
],
});
const patchedSimulationState = structuredClone(worldState.simulationState);
const infraUnit = patchedSimulationState.situationSimulations.find((item) => item.dominantDomain === 'infrastructure');
const marketUnit = patchedSimulationState.situationSimulations.find((item) => item.dominantDomain === 'market');
assert.ok(infraUnit);
assert.ok(marketUnit);
infraUnit.posture = 'constrained';
infraUnit.postureScore = 0.19;
infraUnit.effectChannels = [{ type: 'service_disruption', count: 1 }];
marketUnit.posture = 'contested';
marketUnit.postureScore = 0.49;
marketUnit.totalPressure = 0.67;
marketUnit.totalStabilization = 0.24;
marketUnit.effectChannels = [{ type: 'service_disruption', count: 2 }];
patchedSimulationState.interactionLedger = [
{
id: 'reverse-only',
stage: 'round_2',
sourceSituationId: infraUnit.situationId,
targetSituationId: marketUnit.situationId,
strongestChannel: 'service_disruption',
score: 5,
sourceActorName: 'Port Operator',
targetActorName: 'Market Desk',
interactionType: 'spillover',
},
{
id: 'reverse-emitter',
stage: 'round_2',
sourceSituationId: marketUnit.situationId,
targetSituationId: infraUnit.situationId,
strongestChannel: 'service_disruption',
score: 5,
sourceActorName: 'Market Desk',
targetActorName: 'Port Operator',
interactionType: 'spillover',
},
];
patchedSimulationState.reportableInteractionLedger = [...patchedSimulationState.interactionLedger];
const effects = buildCrossSituationEffects(patchedSimulationState);
assert.ok(effects.some((item) => item.sourceSituationId === marketUnit.situationId && item.targetSituationId === infraUnit.situationId));
});
it('prefers a usable shared channel over the alphabetically first shared channel', () => {
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T14:10:00Z'),
predictions: [
makePrediction('market', 'Black Sea', 'Market repricing: Black Sea', 0.56, 0.55, '14d', [
{ type: 'prediction_market', value: 'Black Sea pricing reflects service disruption risk', weight: 0.36 },
]),
makePrediction('infrastructure', 'Romania', 'Infrastructure pressure: Romania', 0.45, 0.52, '14d', [
{ type: 'outage', value: 'Romania infrastructure remains exposed to service disruption', weight: 0.3 },
]),
],
});
const patchedSimulationState = structuredClone(worldState.simulationState);
const marketUnit = patchedSimulationState.situationSimulations.find((item) => item.dominantDomain === 'market');
const infraUnit = patchedSimulationState.situationSimulations.find((item) => item.dominantDomain === 'infrastructure');
assert.ok(marketUnit);
assert.ok(infraUnit);
marketUnit.posture = 'contested';
marketUnit.postureScore = 0.5;
marketUnit.totalPressure = 0.65;
marketUnit.totalStabilization = 0.25;
marketUnit.effectChannels = [
{ type: 'containment', count: 3 },
{ type: 'service_disruption', count: 2 },
];
patchedSimulationState.interactionLedger = [
{
id: 'shared-channel-choice',
stage: 'round_2',
sourceSituationId: marketUnit.situationId,
targetSituationId: infraUnit.situationId,
strongestChannel: 'service_disruption',
score: 5.5,
sourceActorName: 'Shipping Desk',
targetActorName: 'Port Operator',
interactionType: 'spillover',
},
];
patchedSimulationState.reportableInteractionLedger = [...patchedSimulationState.interactionLedger];
const effects = buildCrossSituationEffects(patchedSimulationState);
assert.ok(effects.some((item) => item.channel === 'service_disruption'));
});
it('uses a cross-regional family label when no single region clearly dominates a family', () => {
const iranPolitical = makePrediction('political', 'Iran', 'Political pressure: Iran', 0.62, 0.56, '14d', [
{ type: 'policy_change', value: 'Political posture hardens in Iran', weight: 0.35 },
]);
buildForecastCase(iranPolitical);
iranPolitical.caseFile.actors = [
{
id: 'shared-diplomatic-actor',
name: 'Shared Diplomatic Actor',
category: 'state_actor',
influenceScore: 0.6,
domains: ['political'],
regions: ['Iran', 'Germany'],
objectives: ['Shape political messaging'],
constraints: ['Avoid direct confrontation'],
likelyActions: ['Shift political posture across both theaters.'],
},
];
const germanyPolitical = makePrediction('political', 'Germany', 'Political pressure: Germany', 0.6, 0.55, '14d', [
{ type: 'policy_change', value: 'Political posture hardens in Germany', weight: 0.35 },
]);
buildForecastCase(germanyPolitical);
germanyPolitical.caseFile.actors = [
{
id: 'shared-diplomatic-actor',
name: 'Shared Diplomatic Actor',
category: 'state_actor',
influenceScore: 0.6,
domains: ['political'],
regions: ['Iran', 'Germany'],
objectives: ['Shape political messaging'],
constraints: ['Avoid direct confrontation'],
likelyActions: ['Shift political posture across both theaters.'],
},
];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T13:40:00Z'),
predictions: [iranPolitical, germanyPolitical],
});
assert.ok(worldState.situationFamilies.length >= 1);
assert.ok(worldState.situationFamilies.some((family) => family.label.startsWith('Cross-regional ')));
});
it('assigns archetype-aware family labels for maritime supply situations', () => {
const supplyA = makePrediction('supply_chain', 'Red Sea', 'Shipping disruption: Red Sea', 0.68, 0.58, '14d', [
{ type: 'chokepoint', value: 'Shipping disruption persists in the Red Sea corridor', weight: 0.4 },
]);
buildForecastCase(supplyA);
const supplyB = makePrediction('supply_chain', 'Bab el-Mandeb', 'Freight rerouting: Bab el-Mandeb', 0.64, 0.56, '14d', [
{ type: 'gps_jamming', value: 'Maritime routing disruption persists near Bab el-Mandeb', weight: 0.32 },
]);
buildForecastCase(supplyB);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T15:00:00Z'),
predictions: [supplyA, supplyB],
});
assert.ok(worldState.situationFamilies.some((family) => family.archetype === 'maritime_supply'));
assert.ok(worldState.situationFamilies.some((family) => family.label.includes('maritime supply')));
});
it('does not infer maritime families from generic port labor talk tokens', () => {
const portTalks = makePrediction('political', 'Spain', 'Port labor talks: Spain', 0.58, 0.55, '14d', [
{ type: 'policy_change', value: 'Port labor talks continue in Spain', weight: 0.28 },
]);
buildForecastCase(portTalks);
const dockStrikePolitics = makePrediction('political', 'Portugal', 'Port labor pressure: Portugal', 0.56, 0.53, '14d', [
{ type: 'policy_change', value: 'Dockworker negotiations are shaping coalition pressure in Portugal', weight: 0.26 },
]);
buildForecastCase(dockStrikePolitics);
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T15:30:00Z'),
predictions: [portTalks, dockStrikePolitics],
});
assert.ok(worldState.situationFamilies.length >= 1);
assert.ok(worldState.situationFamilies.every((family) => family.archetype !== 'maritime_supply'));
assert.ok(worldState.situationFamilies.every((family) => !family.label.includes('maritime supply')));
});
it('keeps weak generic interactions out of the reportable interaction surface', () => {
const source = makePrediction('political', 'Brazil', 'Political pressure: Brazil', 0.56, 0.53, '14d', [
{ type: 'policy_change', value: 'Political pressure is building in Brazil', weight: 0.32 },
]);
buildForecastCase(source);
source.caseFile.actors = [
{
id: 'regional-command-generic',
name: 'Regional command authority',
category: 'state',
influenceScore: 0.58,
domains: ['political'],
regions: ['Brazil', 'Israel'],
objectives: ['Shape regional posture'],
constraints: ['Avoid direct confrontation'],
likelyActions: ['Shift messaging and posture as new evidence arrives.'],
},
];
const target = makePrediction('political', 'Israel', 'Political pressure: Israel', 0.58, 0.54, '14d', [
{ type: 'policy_change', value: 'Political pressure is building in Israel', weight: 0.33 },
]);
buildForecastCase(target);
target.caseFile.actors = [
{
id: 'regional-command-generic',
name: 'Regional command authority',
category: 'state',
influenceScore: 0.58,
domains: ['political'],
regions: ['Brazil', 'Israel'],
objectives: ['Shape regional posture'],
constraints: ['Avoid direct confrontation'],
likelyActions: ['Shift messaging and posture as new evidence arrives.'],
},
];
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T15:10:00Z'),
predictions: [source, target],
});
assert.ok(Array.isArray(worldState.simulationState.reportableInteractionLedger));
assert.equal(worldState.simulationState.reportableInteractionLedger.length, 0);
assert.equal(worldState.simulationState.blockedInteractionSummary.totalBlocked, 0);
assert.equal(worldState.report.interactionWatchlist.length, 0);
});
it('does not emit reportable effects when no interactions promote into the reportable ledger', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
{
situationId: 'sit-source',
label: 'Red Sea supply chain situation',
dominantDomain: 'supply_chain',
familyId: 'fam-red-sea',
familyLabel: 'Red Sea maritime supply family',
regions: ['Red Sea'],
actorIds: ['actor-shipping'],
effectChannels: [{ type: 'logistics_disruption', count: 3 }],
posture: 'escalatory',
postureScore: 0.71,
totalPressure: 0.82,
totalStabilization: 0.22,
},
{
situationId: 'sit-target',
label: 'Middle East market situation',
dominantDomain: 'market',
familyId: 'fam-middle-east',
familyLabel: 'Middle East market repricing family',
regions: ['Middle East'],
actorIds: ['actor-market'],
effectChannels: [],
posture: 'contested',
postureScore: 0.53,
totalPressure: 0.61,
totalStabilization: 0.29,
},
],
interactionLedger: [
{
sourceSituationId: 'sit-source',
targetSituationId: 'sit-target',
sourceLabel: 'Red Sea supply chain situation',
targetLabel: 'Middle East market situation',
sourceActorName: 'Shipping operator',
targetActorName: 'Commodity desk',
interactionType: 'regional_spillover',
strongestChannel: 'logistics_disruption',
score: 4.9,
confidence: 0.76,
actorSpecificity: 0.86,
stage: 'round_2',
},
],
reportableInteractionLedger: [],
}, { mode: 'reportable' });
assert.equal(effects.length, 0);
assert.ok(Array.isArray(effects.blocked));
assert.equal(effects.blocked.length, 0);
});
it('returns reportable effects and blocked metadata when the reportable interaction ledger is populated', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
{
situationId: 'sit-source',
label: 'Baltic Sea supply chain situation',
dominantDomain: 'supply_chain',
familyId: 'fam-baltic',
familyLabel: 'Baltic maritime supply family',
regions: ['Baltic Sea'],
actorIds: ['actor-shipping'],
effectChannels: [{ type: 'logistics_disruption', count: 3 }],
posture: 'escalatory',
postureScore: 0.74,
totalPressure: 0.84,
totalStabilization: 0.21,
},
{
situationId: 'sit-target',
label: 'Black Sea market situation',
dominantDomain: 'market',
familyId: 'fam-black-sea',
familyLabel: 'Black Sea market repricing family',
regions: ['Black Sea'],
actorIds: ['actor-market'],
effectChannels: [],
posture: 'contested',
postureScore: 0.49,
totalPressure: 0.58,
totalStabilization: 0.31,
},
],
reportableInteractionLedger: [
{
sourceSituationId: 'sit-source',
targetSituationId: 'sit-target',
sourceLabel: 'Baltic Sea supply chain situation',
targetLabel: 'Black Sea market situation',
sourceActorName: 'Shipping operator',
targetActorName: 'Commodity desk',
interactionType: 'regional_spillover',
strongestChannel: 'logistics_disruption',
score: 5.2,
confidence: 0.79,
actorSpecificity: 0.91,
sharedActor: false,
regionLink: false,
stage: 'round_2',
},
{
sourceSituationId: 'sit-source',
targetSituationId: 'sit-target',
sourceLabel: 'Baltic Sea supply chain situation',
targetLabel: 'Black Sea market situation',
sourceActorName: 'Shipping operator',
targetActorName: 'Commodity desk',
interactionType: 'regional_spillover',
strongestChannel: 'logistics_disruption',
score: 5.1,
confidence: 0.78,
actorSpecificity: 0.91,
sharedActor: false,
regionLink: false,
stage: 'round_3',
},
],
}, { mode: 'reportable' });
assert.ok(effects.length >= 1);
assert.ok(effects.some((item) => item.channel === 'logistics_disruption'));
assert.ok(Array.isArray(effects.blocked));
});
it('aggregates cross-situation effects across reportable interaction ledgers larger than 32 rows', () => {
const source = {
situationId: 'sit-source',
label: 'Baltic Sea supply chain situation',
dominantDomain: 'supply_chain',
familyId: 'fam-a',
familyLabel: 'Baltic maritime supply pressure family',
regions: ['Baltic Sea'],
actorIds: ['actor-shipping'],
effectChannels: [{ type: 'logistics_disruption', count: 3 }],
posture: 'escalatory',
postureScore: 0.63,
totalPressure: 0.68,
totalStabilization: 0.24,
};
const target = {
situationId: 'sit-target',
label: 'Black Sea market situation',
dominantDomain: 'market',
familyId: 'fam-b',
familyLabel: 'Black Sea market repricing family',
regions: ['Black Sea'],
actorIds: ['actor-markets'],
effectChannels: [],
posture: 'contested',
postureScore: 0.44,
totalPressure: 0.42,
totalStabilization: 0.36,
};
const filler = Array.from({ length: 32 }, (_, index) => ({
sourceSituationId: `noise-source-${index}`,
targetSituationId: `noise-target-${index}`,
sourceLabel: `Noise source ${index}`,
targetLabel: `Noise target ${index}`,
sourceActorName: `Actor ${index}`,
targetActorName: `Counterparty ${index}`,
interactionType: 'direct_overlap',
strongestChannel: 'political_pressure',
score: 6,
confidence: 0.9,
actorSpecificity: 0.85,
stage: 'round_1',
}));
const paired = [
{
sourceSituationId: source.situationId,
targetSituationId: target.situationId,
sourceLabel: source.label,
targetLabel: target.label,
sourceActorName: 'Shipping operator',
targetActorName: 'Commodity desk',
interactionType: 'regional_spillover',
strongestChannel: 'logistics_disruption',
score: 2.4,
confidence: 0.74,
actorSpecificity: 0.82,
stage: 'round_2',
},
{
sourceSituationId: source.situationId,
targetSituationId: target.situationId,
sourceLabel: source.label,
targetLabel: target.label,
sourceActorName: 'Shipping operator',
targetActorName: 'Commodity desk',
interactionType: 'regional_spillover',
strongestChannel: 'logistics_disruption',
score: 2.3,
confidence: 0.72,
actorSpecificity: 0.82,
stage: 'round_3',
},
];
const effects = buildCrossSituationEffects({
situationSimulations: [
source,
target,
...filler.flatMap((item) => ([
{
situationId: item.sourceSituationId,
label: item.sourceLabel,
dominantDomain: 'political',
familyId: `family-${item.sourceSituationId}`,
familyLabel: 'Noise family',
regions: [`Region ${item.sourceSituationId}`],
actorIds: [`actor-${item.sourceSituationId}`],
effectChannels: [{ type: 'political_pressure', count: 3 }],
posture: 'escalatory',
postureScore: 0.7,
totalPressure: 0.75,
totalStabilization: 0.2,
},
{
situationId: item.targetSituationId,
label: item.targetLabel,
dominantDomain: 'political',
familyId: `family-${item.targetSituationId}`,
familyLabel: 'Noise family',
regions: [`Region ${item.targetSituationId}`],
actorIds: [`actor-${item.targetSituationId}`],
effectChannels: [],
posture: 'contested',
postureScore: 0.45,
totalPressure: 0.4,
totalStabilization: 0.35,
},
])),
],
reportableInteractionLedger: [...filler, ...paired],
});
assert.ok(effects.some((item) => (
item.sourceSituationId === source.situationId
&& item.targetSituationId === target.situationId
&& item.channel === 'logistics_disruption'
)));
});
it('dedupes the interaction watchlist by source target and channel before report surfacing', () => {
const watchlist = buildInteractionWatchlist([
{
sourceSituationId: 'sit-a',
targetSituationId: 'sit-b',
sourceLabel: 'Brazil cyber situation',
targetLabel: 'United States cyber and political situation',
strongestChannel: 'cyber_disruption',
interactionType: 'spillover',
stage: 'round_1',
score: 4.2,
confidence: 0.71,
sourceActorName: 'Cyber unit',
targetActorName: 'Agency',
},
{
sourceSituationId: 'sit-a',
targetSituationId: 'sit-b',
sourceLabel: 'Brazil cyber situation',
targetLabel: 'United States cyber and political situation',
strongestChannel: 'cyber_disruption',
interactionType: 'spillover',
stage: 'round_2',
score: 4.4,
confidence: 0.74,
sourceActorName: 'Cyber unit',
targetActorName: 'Agency',
},
]);
assert.equal(watchlist.length, 1);
assert.equal(watchlist[0].label, 'Brazil cyber situation -> United States cyber and political situation');
assert.ok(watchlist[0].summary.includes('2 round(s)'));
});
it('blocks weak cross-theater political effects without strong actor continuity', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
{
situationId: 'sit-politics-eu',
label: 'Germany political situation',
dominantDomain: 'political',
familyId: 'fam-politics',
familyLabel: 'Cross-regional political instability family',
regions: ['Germany'],
actorIds: ['actor-germany'],
effectChannels: [{ type: 'political_pressure', count: 3 }],
posture: 'contested',
postureScore: 0.54,
totalPressure: 0.62,
totalStabilization: 0.39,
},
{
situationId: 'sit-conflict-me',
label: 'Israel conflict and political situation',
dominantDomain: 'conflict',
familyId: 'fam-conflict',
familyLabel: 'Cross-regional war theater family',
regions: ['Israel'],
actorIds: ['actor-israel'],
effectChannels: [],
posture: 'escalatory',
postureScore: 0.91,
totalPressure: 0.95,
totalStabilization: 0.18,
},
],
reportableInteractionLedger: [
{
sourceSituationId: 'sit-politics-eu',
targetSituationId: 'sit-conflict-me',
sourceLabel: 'Germany political situation',
targetLabel: 'Israel conflict and political situation',
strongestChannel: 'political_pressure',
interactionType: 'spillover',
stage: 'round_1',
score: 4.9,
confidence: 0.73,
actorSpecificity: 0.78,
directLinkCount: 1,
sharedActor: true,
regionLink: false,
sourceActorName: 'Coalition bloc',
targetActorName: 'Cabinet office',
},
],
});
assert.equal(effects.length, 0);
});
it('keeps structural situation-level actor overlap in political reportable filtering', () => {
const source = {
situationId: 'sit-politics-a',
label: 'Germany political situation',
dominantDomain: 'political',
regions: ['Germany'],
actorIds: ['shared-actor', 'actor-germany'],
};
const target = {
situationId: 'sit-politics-b',
label: 'Israel political situation',
dominantDomain: 'political',
regions: ['Israel'],
actorIds: ['shared-actor', 'actor-israel'],
};
const reportable = buildReportableInteractionLedger([
{
sourceSituationId: source.situationId,
targetSituationId: target.situationId,
sourceLabel: source.label,
targetLabel: target.label,
strongestChannel: 'political_pressure',
interactionType: 'spillover',
score: 5.5,
confidence: 0.72,
actorSpecificity: 0.84,
sharedActor: false,
regionLink: false,
},
], [source, target]);
assert.equal(reportable.length, 1);
});
it('blocks cross-theater political reportable interactions without market or regional support', () => {
const source = {
situationId: 'sit-politics-a',
label: 'India political situation',
dominantDomain: 'political',
regions: ['India'],
actorIds: ['shared-actor', 'actor-india'],
marketContext: {
confirmationScore: 0.34,
linkedBucketIds: ['sovereign_risk'],
},
};
const target = {
situationId: 'sit-politics-b',
label: 'Israel conflict and political situation',
dominantDomain: 'conflict',
regions: ['Israel'],
actorIds: ['shared-actor', 'actor-israel'],
marketContext: {
confirmationScore: 0.31,
linkedBucketIds: ['energy'],
},
};
const reportable = buildReportableInteractionLedger([
{
sourceSituationId: source.situationId,
targetSituationId: target.situationId,
sourceLabel: source.label,
targetLabel: target.label,
strongestChannel: 'political_pressure',
interactionType: 'spillover',
score: 5.8,
confidence: 0.75,
actorSpecificity: 0.91,
sharedActor: false,
regionLink: false,
},
], [source, target]);
assert.equal(reportable.length, 0);
});
it('blocks non-political reportable interactions when they have neither structural nor market linkage', () => {
const source = {
situationId: 'sit-source',
label: 'Germany cyber situation',
dominantDomain: 'cyber',
regions: ['Germany'],
actorIds: ['actor-germany'],
marketContext: {
confirmationScore: 0.24,
linkedBucketIds: ['fx_stress'],
},
};
const target = {
situationId: 'sit-target',
label: 'Japan infrastructure situation',
dominantDomain: 'infrastructure',
regions: ['Japan'],
actorIds: ['actor-japan'],
marketContext: {
confirmationScore: 0.22,
linkedBucketIds: ['freight'],
},
};
const reportable = buildReportableInteractionLedger([
{
sourceSituationId: source.situationId,
targetSituationId: target.situationId,
sourceLabel: source.label,
targetLabel: target.label,
strongestChannel: 'service_disruption',
interactionType: 'regional_spillover',
score: 5.9,
confidence: 0.81,
actorSpecificity: 0.9,
sharedActor: false,
regionLink: false,
},
], [source, target]);
assert.equal(reportable.length, 0);
assert.equal(reportable.blocked[0]?.reason, 'no_structural_or_market_link');
});
it('blocks cross-theater political effects even with shared-actor when actorSpec below 0.90', () => {
// US (AMERICAS) → Japan (EAST_ASIA) via political_pressure with actorSpec 0.87 is cross-theater.
// The gate requires actorSpec >= 0.90 for non-exempt channels across theater boundaries.
const effects = buildCrossSituationEffects({
situationSimulations: [
{
situationId: 'sit-cyber',
label: 'United States cyber and political situation',
dominantDomain: 'cyber',
familyId: 'fam-cyber',
familyLabel: 'United States cyber pressure family',
regions: ['United States'],
actorIds: ['shared-actor', 'actor-us'],
effectChannels: [{ type: 'political_pressure', count: 3 }],
posture: 'contested',
postureScore: 0.58,
totalPressure: 0.67,
totalStabilization: 0.29,
},
{
situationId: 'sit-market',
label: 'Japan market situation',
dominantDomain: 'market',
familyId: 'fam-market',
familyLabel: 'Japan market repricing family',
regions: ['Japan'],
actorIds: ['shared-actor', 'actor-japan'],
effectChannels: [],
posture: 'contested',
postureScore: 0.43,
totalPressure: 0.48,
totalStabilization: 0.31,
},
],
reportableInteractionLedger: [
{
sourceSituationId: 'sit-cyber',
targetSituationId: 'sit-market',
sourceLabel: 'United States cyber and political situation',
targetLabel: 'Japan market situation',
strongestChannel: 'political_pressure',
interactionType: 'actor_carryover',
stage: 'round_1',
score: 5.6,
confidence: 0.76,
actorSpecificity: 0.87,
directLinkCount: 1,
sharedActor: false,
regionLink: false,
sourceActorName: 'Shared policy actor',
targetActorName: 'Shared policy actor',
},
{
sourceSituationId: 'sit-cyber',
targetSituationId: 'sit-market',
sourceLabel: 'United States cyber and political situation',
targetLabel: 'Japan market situation',
strongestChannel: 'political_pressure',
interactionType: 'actor_carryover',
stage: 'round_2',
score: 5.5,
confidence: 0.75,
actorSpecificity: 0.87,
directLinkCount: 1,
sharedActor: false,
regionLink: false,
sourceActorName: 'Shared policy actor',
targetActorName: 'Shared policy actor',
},
],
});
assert.equal(effects.length, 0, 'US → Japan cross-theater political_pressure at actorSpec 0.87 should be blocked');
});
it('allows logistics effects with strong confidence while filtering weaker political ones', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
{
situationId: 'sit-baltic',
label: 'Baltic Sea supply chain situation',
dominantDomain: 'supply_chain',
familyId: 'fam-supply',
familyLabel: 'Baltic maritime supply pressure family',
regions: ['Baltic Sea', 'Black Sea'],
actorIds: ['actor-shipping'],
effectChannels: [{ type: 'logistics_disruption', count: 3 }],
posture: 'contested',
postureScore: 0.47,
totalPressure: 0.58,
totalStabilization: 0.33,
},
{
situationId: 'sit-blacksea-market',
label: 'Black Sea market situation',
dominantDomain: 'market',
familyId: 'fam-market',
familyLabel: 'Black Sea market repricing family',
regions: ['Black Sea'],
actorIds: ['actor-market'],
effectChannels: [],
posture: 'contested',
postureScore: 0.42,
totalPressure: 0.45,
totalStabilization: 0.32,
},
{
situationId: 'sit-brazil-politics',
label: 'Brazil political situation',
dominantDomain: 'political',
familyId: 'fam-politics-a',
familyLabel: 'Cross-regional political instability family',
regions: ['Brazil'],
actorIds: ['actor-brazil'],
effectChannels: [{ type: 'political_pressure', count: 3 }],
posture: 'contested',
postureScore: 0.55,
totalPressure: 0.61,
totalStabilization: 0.35,
},
{
situationId: 'sit-uk-politics',
label: 'United Kingdom political situation',
dominantDomain: 'political',
familyId: 'fam-politics-b',
familyLabel: 'Cross-regional political instability family',
regions: ['United Kingdom'],
actorIds: ['actor-uk'],
effectChannels: [],
posture: 'contested',
postureScore: 0.48,
totalPressure: 0.5,
totalStabilization: 0.33,
},
],
reportableInteractionLedger: [
{
sourceSituationId: 'sit-baltic',
targetSituationId: 'sit-blacksea-market',
sourceLabel: 'Baltic Sea supply chain situation',
targetLabel: 'Black Sea market situation',
strongestChannel: 'logistics_disruption',
interactionType: 'regional_spillover',
stage: 'round_1',
score: 2.5,
confidence: 0.76,
actorSpecificity: 0.84,
directLinkCount: 2,
sharedActor: false,
regionLink: true,
sourceActorName: 'Shipping operator',
targetActorName: 'Commodity desk',
},
{
sourceSituationId: 'sit-baltic',
targetSituationId: 'sit-blacksea-market',
sourceLabel: 'Baltic Sea supply chain situation',
targetLabel: 'Black Sea market situation',
strongestChannel: 'logistics_disruption',
interactionType: 'regional_spillover',
stage: 'round_2',
score: 2.4,
confidence: 0.78,
actorSpecificity: 0.84,
directLinkCount: 2,
sharedActor: false,
regionLink: true,
sourceActorName: 'Shipping operator',
targetActorName: 'Commodity desk',
},
{
sourceSituationId: 'sit-brazil-politics',
targetSituationId: 'sit-uk-politics',
sourceLabel: 'Brazil political situation',
targetLabel: 'United Kingdom political situation',
strongestChannel: 'political_pressure',
interactionType: 'spillover',
stage: 'round_1',
score: 5.2,
confidence: 0.75,
actorSpecificity: 0.79,
directLinkCount: 1,
sharedActor: true,
regionLink: false,
sourceActorName: 'Coalition bloc',
targetActorName: 'Policy team',
},
{
sourceSituationId: 'sit-brazil-politics',
targetSituationId: 'sit-uk-politics',
sourceLabel: 'Brazil political situation',
targetLabel: 'United Kingdom political situation',
strongestChannel: 'political_pressure',
interactionType: 'spillover',
stage: 'round_2',
score: 5.1,
confidence: 0.74,
actorSpecificity: 0.79,
directLinkCount: 1,
sharedActor: true,
regionLink: false,
sourceActorName: 'Coalition bloc',
targetActorName: 'Policy team',
},
],
});
assert.equal(effects.length, 1);
assert.equal(effects[0].channel, 'logistics_disruption');
assert.ok(effects[0].confidence >= 0.5);
});
it('ignores incompatible prior simulation momentum when the simulation version changes', () => {
const conflict = makePrediction('conflict', 'Israel', 'Active armed conflict: Israel', 0.76, 0.66, '7d', [
{ type: 'ucdp', value: 'Israeli theater remains active', weight: 0.4 },
]);
buildForecastCase(conflict);
const priorWorldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T08:00:00Z'),
predictions: [conflict],
});
priorWorldState.simulationState = {
...priorWorldState.simulationState,
version: 1,
situationSimulations: (priorWorldState.simulationState?.situationSimulations || []).map((item) => ({
...item,
postureScore: 0.99,
rounds: (item.rounds || []).map((round) => ({
...round,
pressureDelta: 0.99,
stabilizationDelta: 0,
})),
})),
};
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-19T09:00:00Z'),
predictions: [conflict],
priorWorldState,
priorWorldStates: [priorWorldState],
});
assert.equal(worldState.simulationState.version, 5);
assert.ok((worldState.simulationState.situationSimulations || []).every((item) => item.postureScore < 0.99));
});
it('promotes same-macro repeated security spillover into the reportable layer', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
{
situationId: 'sit-brazil',
label: 'Brazil conflict situation',
dominantDomain: 'conflict',
familyId: 'fam-americas-war',
familyLabel: 'Americas war theater family',
regions: ['Brazil'],
actorIds: ['actor-brazil', 'actor-shared'],
effectChannels: [{ type: 'security_escalation', count: 3 }],
posture: 'escalatory',
postureScore: 0.88,
totalPressure: 0.92,
totalStabilization: 0.18,
},
{
situationId: 'sit-mexico',
label: 'Mexico conflict situation',
dominantDomain: 'conflict',
familyId: 'fam-americas-war',
familyLabel: 'Americas war theater family',
regions: ['Mexico'],
actorIds: ['actor-mexico', 'actor-shared'],
effectChannels: [],
posture: 'contested',
postureScore: 0.46,
totalPressure: 0.57,
totalStabilization: 0.31,
},
],
reportableInteractionLedger: [
{
sourceSituationId: 'sit-brazil',
targetSituationId: 'sit-mexico',
sourceLabel: 'Brazil conflict situation',
targetLabel: 'Mexico conflict situation',
strongestChannel: 'security_escalation',
interactionType: 'actor_carryover',
stage: 'round_1',
score: 4.3,
confidence: 0.67,
actorSpecificity: 0.91,
directLinkCount: 1,
sharedActor: true,
regionLink: false,
sourceActorName: 'Named brigade command',
targetActorName: 'Named brigade command',
},
{
sourceSituationId: 'sit-brazil',
targetSituationId: 'sit-mexico',
sourceLabel: 'Brazil conflict situation',
targetLabel: 'Mexico conflict situation',
strongestChannel: 'security_escalation',
interactionType: 'actor_carryover',
stage: 'round_2',
score: 4.3,
confidence: 0.68,
actorSpecificity: 0.91,
directLinkCount: 1,
sharedActor: true,
regionLink: false,
sourceActorName: 'Named brigade command',
targetActorName: 'Named brigade command',
},
],
});
assert.equal(effects.length, 1);
assert.equal(effects[0].effectClass, 'security_spillover');
assert.equal(effects[0].channel, 'security_escalation');
});
it('records blocked effect telemetry on the world state', () => {
const worldState = buildForecastRunWorldState({
predictions: [
makePrediction('political', 'Israel', 'Political instability: Israel', 0.61, 0.5, '30d', []),
makePrediction('political', 'Taiwan', 'Political instability: Taiwan', 0.53, 0.45, '30d', []),
],
situationClusters: [
{
id: 'sit-israel',
label: 'Israel political situation',
forecastIds: ['fc-political-a'],
domains: ['political'],
regions: ['Israel'],
actors: ['Incumbent leadership'],
topSignals: [{ type: 'unrest', count: 2 }],
forecastCount: 1,
avgProbability: 0.61,
avgConfidence: 0.5,
dominantDomain: 'political',
dominantRegion: 'Israel',
branchKinds: ['base'],
sampleTitles: ['Political instability: Israel'],
},
{
id: 'sit-taiwan',
label: 'Taiwan political situation',
forecastIds: ['fc-political-b'],
domains: ['political'],
regions: ['Taiwan'],
actors: ['Incumbent leadership'],
topSignals: [{ type: 'unrest', count: 2 }],
forecastCount: 1,
avgProbability: 0.53,
avgConfidence: 0.45,
dominantDomain: 'political',
dominantRegion: 'Taiwan',
branchKinds: ['base'],
sampleTitles: ['Political instability: Taiwan'],
},
],
situationFamilies: [
{
id: 'fam-israel',
label: 'Israel political instability family',
archetype: 'political_instability',
situationIds: ['sit-israel'],
dominantDomain: 'political',
dominantRegion: 'Israel',
forecastCount: 1,
situationCount: 1,
},
{
id: 'fam-taiwan',
label: 'Taiwan political instability family',
archetype: 'political_instability',
situationIds: ['sit-taiwan'],
dominantDomain: 'political',
dominantRegion: 'Taiwan',
forecastCount: 1,
situationCount: 1,
},
],
});
assert.ok(typeof worldState.simulationState.blockedEffectSummary.totalBlocked === 'number');
assert.ok(Array.isArray(worldState.report.blockedEffectWatchlist));
});
});
describe('cross-theater gate', () => {
it('identifies cross-theater pairs correctly', () => {
assert.equal(isCrossTheaterPair(['Israel'], ['Taiwan']), true);
assert.equal(isCrossTheaterPair(['Israel'], ['Iran']), false);
assert.equal(isCrossTheaterPair(['Brazil'], ['Mexico']), false);
assert.equal(isCrossTheaterPair(['Cuba'], ['Iran']), true);
assert.equal(isCrossTheaterPair(['China'], ['United States']), true);
assert.equal(isCrossTheaterPair(['Baltic Sea'], ['Black Sea']), false);
assert.equal(isCrossTheaterPair(['Israel'], ['unknown-region']), false);
assert.equal(isCrossTheaterPair(['unknown-a'], ['unknown-b']), false);
});
it('maps regions to macro-regions', () => {
assert.equal(getMacroRegion(['Israel', 'Gaza']), 'MENA');
assert.equal(getMacroRegion(['Taiwan', 'Western Pacific']), 'EAST_ASIA');
assert.equal(getMacroRegion(['Brazil']), 'AMERICAS');
assert.equal(getMacroRegion(['Baltic Sea', 'Black Sea']), 'EUROPE');
assert.equal(getMacroRegion(['unknown-region']), null);
assert.equal(getMacroRegion([]), null);
});
function makeSimulation(situationId, label, domain, regions, posture, postureScore, effectChannels = []) {
return {
situationId,
label,
dominantDomain: domain,
familyId: `fam-${situationId}`,
familyLabel: `${label} family`,
regions,
actorIds: [`actor-${situationId}`],
effectChannels,
posture,
postureScore,
totalPressure: posture === 'escalatory' ? 0.88 : 0.55,
totalStabilization: posture === 'escalatory' ? 0.22 : 0.38,
};
}
function makeInteraction(srcId, srcLabel, tgtId, tgtLabel, channel, stage, score, conf, spec, sharedActor, regionLink) {
return {
sourceSituationId: srcId,
targetSituationId: tgtId,
sourceLabel: srcLabel,
targetLabel: tgtLabel,
strongestChannel: channel,
interactionType: sharedActor ? 'actor_carryover' : 'spillover',
stage,
score,
confidence: conf,
actorSpecificity: spec,
directLinkCount: (sharedActor ? 1 : 0) + (regionLink ? 1 : 0) + 1,
sharedActor,
regionLink,
sourceActorName: 'Test actor',
targetActorName: 'Test actor',
};
}
it('blocks Israel → Taiwan via generic Incumbent Leadership (regional_spillover, spec 0.68)', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
makeSimulation('sit-israel', 'Israel conflict situation', 'conflict', ['Israel'], 'escalatory', 0.88,
[{ type: 'regional_spillover', count: 3 }]),
makeSimulation('sit-taiwan', 'Taiwan political situation', 'political', ['Taiwan'], 'contested', 0.54),
],
reportableInteractionLedger: [
makeInteraction('sit-israel', 'Israel conflict situation', 'sit-taiwan', 'Taiwan political situation',
'regional_spillover', 'round_1', 5.2, 0.77, 0.68, true, false),
makeInteraction('sit-israel', 'Israel conflict situation', 'sit-taiwan', 'Taiwan political situation',
'regional_spillover', 'round_2', 5.1, 0.77, 0.68, true, false),
],
});
assert.equal(effects.length, 0, 'Israel → Taiwan via generic actor should be blocked by cross-theater gate');
});
it('allows China → US via Threat Actors (cyber_disruption, exempt channel)', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
makeSimulation('sit-china', 'China cyber situation', 'cyber', ['China'], 'escalatory', 0.88,
[{ type: 'cyber_disruption', count: 3 }]),
// target must be infrastructure for cyber_disruption:infrastructure relation to exist
makeSimulation('sit-us', 'United States infrastructure situation', 'infrastructure', ['United States'], 'contested', 0.62),
],
reportableInteractionLedger: [
makeInteraction('sit-china', 'China cyber situation', 'sit-us', 'United States infrastructure situation',
'cyber_disruption', 'round_1', 6.5, 0.91, 0.95, true, false),
makeInteraction('sit-china', 'China cyber situation', 'sit-us', 'United States infrastructure situation',
'cyber_disruption', 'round_2', 6.3, 0.90, 0.95, true, false),
],
});
assert.equal(effects.length, 1, 'China (EAST_ASIA) → US (AMERICAS) via cyber_disruption should pass (exempt channel)');
assert.equal(effects[0].channel, 'cyber_disruption');
});
it('blocks Brazil → Israel conflict via External Power Broker (security_escalation, spec 0.85 < 0.90)', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
makeSimulation('sit-brazil', 'Brazil conflict situation', 'conflict', ['Brazil'], 'escalatory', 0.84,
[{ type: 'security_escalation', count: 3 }]),
makeSimulation('sit-israel', 'Israel conflict situation', 'conflict', ['Israel'], 'escalatory', 0.88),
],
reportableInteractionLedger: [
makeInteraction('sit-brazil', 'Brazil conflict situation', 'sit-israel', 'Israel conflict situation',
'security_escalation', 'round_1', 5.8, 0.87, 0.85, true, false),
makeInteraction('sit-brazil', 'Brazil conflict situation', 'sit-israel', 'Israel conflict situation',
'security_escalation', 'round_2', 5.7, 0.86, 0.85, true, false),
],
});
assert.equal(effects.length, 0, 'Brazil → Israel via generic external actor should be blocked (actorSpec 0.85 < 0.90)');
});
it('allows Brazil → Mexico (same macro-region, security_escalation → infrastructure)', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
makeSimulation('sit-brazil', 'Brazil conflict situation', 'conflict', ['Brazil'], 'escalatory', 0.84,
[{ type: 'security_escalation', count: 3 }]),
// target must be infrastructure for security_escalation:infrastructure relation to exist
makeSimulation('sit-mexico', 'Mexico infrastructure situation', 'infrastructure', ['Mexico'], 'escalatory', 0.72),
],
reportableInteractionLedger: [
makeInteraction('sit-brazil', 'Brazil conflict situation', 'sit-mexico', 'Mexico infrastructure situation',
'security_escalation', 'round_1', 5.8, 0.87, 0.85, true, false),
makeInteraction('sit-brazil', 'Brazil conflict situation', 'sit-mexico', 'Mexico infrastructure situation',
'security_escalation', 'round_2', 5.7, 0.86, 0.85, true, false),
],
});
assert.equal(effects.length, 1, 'Brazil → Mexico should pass (both AMERICAS, cross-theater gate does not apply)');
assert.equal(effects[0].channel, 'security_escalation');
});
it('blocks Cuba → Iran infrastructure (cross-theater, service_disruption, spec 0.73 < 0.90)', () => {
const effects = buildCrossSituationEffects({
situationSimulations: [
makeSimulation('sit-cuba', 'Cuba infrastructure situation', 'infrastructure', ['Cuba'], 'contested', 0.62,
[{ type: 'service_disruption', count: 3 }]),
makeSimulation('sit-iran', 'Iran infrastructure situation', 'infrastructure', ['Iran'], 'contested', 0.58),
],
reportableInteractionLedger: [
makeInteraction('sit-cuba', 'Cuba infrastructure situation', 'sit-iran', 'Iran infrastructure situation',
'service_disruption', 'round_1', 5.5, 0.84, 0.73, true, false),
makeInteraction('sit-cuba', 'Cuba infrastructure situation', 'sit-iran', 'Iran infrastructure situation',
'service_disruption', 'round_2', 5.4, 0.83, 0.73, true, false),
],
});
assert.equal(effects.length, 0, 'Cuba → Iran via generic civil-protection actor should be blocked');
});
});
describe('impact expansion layer', () => {
function makeImpactCandidatePacket(stateId = 'state-1', label = 'Strait of Hormuz maritime disruption state', overrides = {}) {
return {
candidateIndex: 0,
candidateStateId: stateId,
candidateStateLabel: label,
stateKind: 'maritime_disruption',
dominantRegion: 'Middle East',
macroRegions: ['EMEA'],
countries: ['Middle East', 'Qatar'],
marketBucketIds: ['energy', 'freight', 'rates_inflation'],
transmissionChannels: ['shipping_cost_shock', 'gas_supply_stress'],
topSignalTypes: ['shipping_cost_shock', 'energy_supply_shock'],
criticalSignalTypes: ['shipping_cost_shock', 'gas_supply_stress'],
routeFacilityKey: 'Strait of Hormuz',
commodityKey: 'lng',
specificityScore: 0.8,
continuityMode: 'persistent_strengthened',
continuityScore: 1,
rankingScore: 0.92,
evidenceTable: [
{ key: 'E1', kind: 'state_summary', text: 'Strait of Hormuz shipping pressure is active.' },
{ key: 'E2', kind: 'headline', text: 'Qatar LNG export risk is rising as route security deteriorates.' },
],
marketContext: {
topBucketId: 'energy',
topBucketLabel: 'Energy',
topBucketPressure: 0.83,
confirmationScore: 0.72,
contradictionScore: 0.08,
topChannel: 'gas_supply_stress',
topTransmissionStrength: 0.76,
topTransmissionConfidence: 0.69,
transmissionEdgeCount: 3,
criticalSignalLift: 0.64,
criticalSignalTypes: ['shipping_cost_shock', 'gas_supply_stress'],
linkedBucketIds: ['energy', 'freight', 'rates_inflation'],
consequenceSummary: 'Strait of Hormuz is transmitting into Energy through gas supply stress.',
},
stateSummary: {
avgProbability: 0.71,
avgConfidence: 0.63,
situationCount: 1,
forecastCount: 1,
sampleTitles: ['Shipping disruption: Strait of Hormuz'],
actors: ['Regional command authority'],
signalTypes: ['shipping_cost_shock'],
},
...overrides,
};
}
function makeImpactExpansionBundle(stateId = 'state-1', label = 'Strait of Hormuz maritime disruption state', packetOverrides = {}) {
const candidatePacket = makeImpactCandidatePacket(stateId, label, packetOverrides);
return {
source: 'live',
provider: 'test',
model: 'test-model',
parseStage: 'object_candidates',
rawPreview: '',
failureReason: '',
candidateCount: 1,
extractedCandidateCount: 1,
extractedHypothesisCount: 3,
candidates: [{
candidateIndex: 0,
candidateStateId: candidatePacket.candidateStateId,
label: candidatePacket.candidateStateLabel,
stateKind: candidatePacket.stateKind,
dominantRegion: candidatePacket.dominantRegion,
rankingScore: candidatePacket.rankingScore,
topBucketId: candidatePacket.marketContext.topBucketId,
topBucketLabel: candidatePacket.marketContext.topBucketLabel,
topChannel: candidatePacket.marketContext.topChannel,
transmissionEdgeCount: candidatePacket.marketContext.transmissionEdgeCount,
routeFacilityKey: candidatePacket.routeFacilityKey,
commodityKey: candidatePacket.commodityKey,
}],
candidatePackets: [candidatePacket],
extractedCandidates: [{
candidateIndex: 0,
candidateStateId: candidatePacket.candidateStateId,
directHypotheses: [
{
variableKey: 'lng_export_stress',
channel: 'gas_supply_stress',
targetBucket: 'energy',
region: 'Middle East',
macroRegion: 'EMEA',
countries: ['Qatar'],
assetsOrSectors: ['LNG exports'],
commodity: 'lng',
dependsOnKey: '',
strength: 0.95,
confidence: 0.92,
analogTag: 'lng_export_disruption',
summary: 'LNG export stress is rising through the Strait of Hormuz route.',
evidenceRefs: ['E1', 'E2'],
},
],
secondOrderHypotheses: [
{
variableKey: 'inflation_pass_through',
channel: 'inflation_impulse',
targetBucket: 'rates_inflation',
region: 'Middle East',
macroRegion: 'EMEA',
countries: ['Qatar'],
assetsOrSectors: ['Importers'],
commodity: 'lng',
dependsOnKey: 'lng_export_stress',
strength: 0.92,
confidence: 0.9,
analogTag: 'inflation_pass_through',
summary: 'Import costs are feeding inflation pass-through from LNG stress.',
evidenceRefs: ['E1', 'E2'],
},
],
thirdOrderHypotheses: [
{
variableKey: 'sovereign_funding_stress',
channel: 'sovereign_stress',
targetBucket: 'sovereign_risk',
region: 'Middle East',
macroRegion: 'EMEA',
countries: ['Qatar'],
assetsOrSectors: ['Sovereign issuers'],
commodity: 'lng',
dependsOnKey: 'inflation_pass_through',
strength: 0.92,
confidence: 0.9,
analogTag: 'sovereign_funding_stress',
summary: 'Funding stress follows if the inflation shock broadens into sovereign repricing.',
evidenceRefs: ['E2'],
},
],
}],
};
}
it('keeps impact-expansion cache hashes stable when source situation ids churn', () => {
const left = makeImpactCandidatePacket('state-1', 'Strait of Hormuz maritime disruption state', {
sourceSituationIds: ['sit-a'],
});
const right = makeImpactCandidatePacket('state-1', 'Strait of Hormuz maritime disruption state', {
sourceSituationIds: ['sit-b', 'sit-c'],
});
assert.equal(
buildImpactExpansionCandidateHash([left]),
buildImpactExpansionCandidateHash([right]),
);
});
it('validates exact evidence refs and maps only strong hypotheses', () => {
const bundle = makeImpactExpansionBundle();
bundle.extractedCandidates[0].directHypotheses.push({
variableKey: 'route_disruption',
channel: 'shipping_cost_shock',
targetBucket: 'freight',
region: 'Middle East',
macroRegion: 'EMEA',
countries: ['Qatar'],
assetsOrSectors: ['Shipping'],
commodity: 'lng',
dependsOnKey: '',
strength: 0.88,
confidence: 0.84,
analogTag: 'energy_corridor_blockage',
summary: 'This should fail because the evidence key is invalid.',
evidenceRefs: ['E9'],
});
const validation = validateImpactHypotheses(bundle);
const direct = validation.hypotheses.find((item) => item.order === 'direct' && item.variableKey === 'lng_export_stress');
const secondOrder = validation.hypotheses.find((item) => item.order === 'second_order' && item.variableKey === 'inflation_pass_through');
const thirdOrder = validation.hypotheses.find((item) => item.order === 'third_order' && item.variableKey === 'sovereign_funding_stress');
assert.equal(validation.mapped.length, 2);
assert.equal(validation.rejectionReasonCounts.no_valid_evidence_refs, 1);
assert.equal(direct.validationStatus, 'mapped');
assert.equal(secondOrder.validationStatus, 'mapped');
assert.equal(thirdOrder.validationStatus, 'rejected');
assert.equal(thirdOrder.rejectionReason, '');
});
it('accepts valid risk-off channels for sovereign-risk impact hypotheses', () => {
const bundle = makeImpactExpansionBundle('state-risk', 'Global risk-off repricing state', {
marketBucketIds: ['sovereign_risk', 'fx_stress'],
transmissionChannels: ['risk_off_rotation', 'volatility_shock'],
topSignalTypes: ['risk_off_rotation'],
criticalSignalTypes: ['risk_off_rotation'],
commodityKey: '',
routeFacilityKey: '',
marketContext: {
topBucketId: 'sovereign_risk',
topBucketLabel: 'Sovereign Risk',
topBucketPressure: 0.8,
confirmationScore: 0.74,
contradictionScore: 0.06,
topChannel: 'risk_off_rotation',
topTransmissionStrength: 0.72,
topTransmissionConfidence: 0.68,
transmissionEdgeCount: 3,
criticalSignalLift: 0.55,
criticalSignalTypes: ['risk_off_rotation'],
linkedBucketIds: ['sovereign_risk', 'fx_stress'],
consequenceSummary: 'Risk-off rotation is transmitting into sovereign repricing.',
},
});
bundle.extractedCandidateCount = 1;
bundle.extractedHypothesisCount = 2;
bundle.extractedCandidates = [{
candidateIndex: 0,
candidateStateId: 'state-risk',
directHypotheses: [
{
variableKey: 'route_disruption',
channel: 'shipping_cost_shock',
targetBucket: 'freight',
region: 'Global',
macroRegion: 'GLOBAL',
countries: ['United States'],
assetsOrSectors: ['Shipping'],
commodity: '',
dependsOnKey: '',
strength: 0.93,
confidence: 0.9,
analogTag: 'shipping_insurance_spike',
summary: 'Shipping stress is spilling out of the primary route network.',
evidenceRefs: ['E1', 'E2'],
},
],
secondOrderHypotheses: [
{
variableKey: 'risk_off_rotation',
channel: 'risk_off_rotation',
targetBucket: 'sovereign_risk',
region: 'Global',
macroRegion: 'GLOBAL',
countries: ['United States'],
assetsOrSectors: ['Sovereign bonds'],
commodity: '',
dependsOnKey: 'route_disruption',
strength: 0.93,
confidence: 0.9,
analogTag: 'risk_off_flight_to_safety',
summary: 'Risk-off rotation is spilling into sovereign repricing.',
evidenceRefs: ['E1', 'E2'],
},
],
thirdOrderHypotheses: [],
}];
const validation = validateImpactHypotheses(bundle);
const riskOff = validation.hypotheses.find((item) => item.variableKey === 'risk_off_rotation');
assert.equal(validation.mapped.length, 2);
assert.equal(riskOff.validationStatus, 'mapped');
assert.equal(riskOff.rejectionReason, '');
});
it('requires higher-order hypotheses to depend on lower-order items that survived validation', () => {
const bundle = makeImpactExpansionBundle();
bundle.extractedCandidates = [{
candidateIndex: 0,
candidateStateId: bundle.candidatePackets[0].candidateStateId,
directHypotheses: [
{
variableKey: 'lng_export_stress',
channel: 'gas_supply_stress',
targetBucket: 'energy',
region: 'Middle East',
macroRegion: 'EMEA',
countries: ['Qatar'],
assetsOrSectors: ['LNG exports'],
commodity: 'lng',
dependsOnKey: '',
strength: 0.95,
confidence: 0.92,
analogTag: 'lng_export_disruption',
summary: 'This direct hypothesis should fail evidence validation.',
evidenceRefs: ['E9'],
},
],
secondOrderHypotheses: [
{
variableKey: 'inflation_pass_through',
channel: 'inflation_impulse',
targetBucket: 'rates_inflation',
region: 'Middle East',
macroRegion: 'EMEA',
countries: ['Qatar'],
assetsOrSectors: ['Importers'],
commodity: 'lng',
dependsOnKey: 'lng_export_stress',
strength: 0.92,
confidence: 0.9,
analogTag: 'inflation_pass_through',
summary: 'This should fail because its parent did not survive validation.',
evidenceRefs: ['E1', 'E2'],
},
],
thirdOrderHypotheses: [],
}];
bundle.extractedHypothesisCount = 2;
const validation = validateImpactHypotheses(bundle);
const direct = validation.hypotheses.find((item) => item.order === 'direct');
const secondOrder = validation.hypotheses.find((item) => item.order === 'second_order');
assert.equal(direct.rejectionReason, 'no_valid_evidence_refs');
assert.equal(secondOrder.rejectionReason, 'missing_dependency');
assert.equal(secondOrder.validationStatus, 'rejected');
});
it('threads mapped expansion signals into simulation rounds without mutating observed world signals', () => {
const prediction = makePrediction('supply_chain', 'Red Sea', 'Shipping disruption: Strait of Hormuz', 0.68, 0.6, '7d', [
{ type: 'shipping_cost_shock', value: 'Shipping costs are rising around Strait of Hormuz rerouting.', weight: 0.5 },
{ type: 'energy_supply_shock', value: 'Energy transit pressure is building around Qatar LNG flows.', weight: 0.32 },
]);
prediction.newsContext = ['Tanker rerouting is amplifying LNG and freight pressure around the Gulf.'];
buildForecastCase(prediction);
populateFallbackNarratives([prediction]);
const baseState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-23T10:00:00Z'),
predictions: [prediction],
});
const stateUnit = baseState.stateUnits[0];
const bundle = makeImpactExpansionBundle(stateUnit.id, stateUnit.label, {
dominantRegion: stateUnit.dominantRegion || stateUnit.regions?.[0] || 'Red Sea',
macroRegions: stateUnit.macroRegions || ['EMEA'],
countries: stateUnit.regions || ['Red Sea'],
marketBucketIds: stateUnit.marketBucketIds || ['energy', 'freight', 'rates_inflation'],
transmissionChannels: stateUnit.transmissionChannels || ['shipping_cost_shock', 'gas_supply_stress'],
topSignalTypes: stateUnit.signalTypes || ['shipping_cost_shock'],
});
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-23T10:05:00Z'),
predictions: [prediction],
inputs: { impactExpansionBundle: bundle },
situationClusters: baseState.situationClusters,
situationFamilies: baseState.situationFamilies,
stateUnits: baseState.stateUnits,
});
assert.equal(worldState.worldSignals.signals.length, baseState.worldSignals.signals.length);
assert.equal(worldState.impactExpansion.mappedSignalCount, 2);
assert.ok(worldState.impactExpansion.expandedWorldSignalCount > worldState.impactExpansion.observedWorldSignalCount);
assert.equal(worldState.simulationState.expandedSignalUsageByRound.round_1.mappedCount, 1);
assert.equal(worldState.simulationState.expandedSignalUsageByRound.round_2.mappedCount, 2);
assert.equal(worldState.simulationState.expandedSignalUsageByRound.round_3.mappedCount, 2);
});
});
describe('critical news signal extraction', () => {
it('extracts urgent route, LNG, sanctions, and thermal signals from structured news and intelligence', () => {
const clusterItems = extractNewsClusterItems(
{
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'Iran threatens closure of the Strait of Hormuz after tanker strike',
primaryLink: 'https://example.com/hormuz',
threatLevel: 'critical',
sourceCount: 5,
isAlert: true,
pubDate: '2026-03-22T11:45:00.000Z',
},
{
primaryTitle: 'Attack reported near Ras Laffan LNG export terminal in Qatar',
primaryLink: 'https://example.com/ras-laffan',
threatLevel: 'critical',
sourceCount: 4,
isAlert: true,
pubDate: '2026-03-22T11:40:00.000Z',
},
],
},
{
categories: {
geopolitics: {
items: [
{ title: 'US issues fresh sanctions on Iran shipping network', isAlert: true, link: 'https://example.com/sanctions', pubDate: '2026-03-22T11:35:00.000Z' },
],
},
},
},
);
assert.equal(clusterItems.length, 3);
const signals = extractCriticalNewsSignals({
newsInsights: {
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'Iran threatens closure of the Strait of Hormuz after tanker strike',
primaryLink: 'https://example.com/hormuz',
threatLevel: 'critical',
sourceCount: 5,
isAlert: true,
pubDate: '2026-03-22T11:45:00.000Z',
},
{
primaryTitle: 'Attack reported near Ras Laffan LNG export terminal in Qatar',
primaryLink: 'https://example.com/ras-laffan',
threatLevel: 'critical',
sourceCount: 4,
isAlert: true,
pubDate: '2026-03-22T11:40:00.000Z',
},
],
},
newsDigest: {
categories: {
geopolitics: {
items: [
{ title: 'US issues fresh sanctions on Iran shipping network', isAlert: true, link: 'https://example.com/sanctions', pubDate: '2026-03-22T11:35:00.000Z' },
],
},
},
},
iranEvents: {
events: [
{
id: 'ie-1',
title: 'Missile strike reported near Ras Laffan LNG terminal',
category: 'airstrike',
severity: 'critical',
locationName: 'qatar',
},
],
},
sanctionsPressure: {
countries: [
{ countryCode: 'IR', countryName: 'Iran', entryCount: 12, newEntryCount: 3, vesselCount: 4, aircraftCount: 0 },
],
entries: [
{ id: 'sp-1', name: 'Iran tanker network', countryCodes: ['IR'], countryNames: ['Iran'], programs: ['IRAN'], isNew: true, note: 'New sanctions target oil tanker exports' },
],
},
thermalEscalation: {
clusters: [
{
id: 'th-1',
countryCode: 'QA',
countryName: 'Qatar',
regionLabel: 'Qatar',
observationCount: 9,
totalFrp: 180,
persistenceHours: 14,
status: 'THERMAL_STATUS_SPIKE',
context: 'THERMAL_CONTEXT_CONFLICT_ADJACENT',
confidence: 'THERMAL_CONFIDENCE_HIGH',
strategicRelevance: 'THERMAL_RELEVANCE_HIGH',
},
],
},
});
const types = new Set(signals.map((signal) => signal.type));
const sourceTypes = new Set(signals.map((signal) => signal.sourceType));
assert.ok(types.has('shipping_cost_shock'));
assert.ok(types.has('energy_supply_shock'));
assert.ok(types.has('gas_supply_stress'));
assert.ok(types.has('sovereign_stress'));
assert.ok(types.has('infrastructure_capacity_loss'));
assert.ok(sourceTypes.has('critical_news'));
assert.ok(sourceTypes.has('iran_events'));
assert.ok(sourceTypes.has('sanctions_pressure'));
assert.ok(sourceTypes.has('thermal_escalation'));
});
it('recognizes plural sanctions, airstrike, and blocks phrasing in critical headlines', () => {
const signals = extractCriticalNewsSignals({
newsInsights: {
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'US issues fresh sanctions on Iran shipping network',
primaryLink: 'https://example.com/sanctions',
threatLevel: 'high',
sourceCount: 3,
isAlert: true,
pubDate: '2026-03-22T11:55:00.000Z',
},
{
primaryTitle: 'Airstrike on oil terminal in Qatar disrupts exports',
primaryLink: 'https://example.com/airstrike',
threatLevel: 'critical',
sourceCount: 4,
isAlert: true,
pubDate: '2026-03-22T11:50:00.000Z',
},
{
primaryTitle: 'Iran blocks access to canal after ultimatum',
primaryLink: 'https://example.com/blocks',
threatLevel: 'high',
sourceCount: 3,
isAlert: true,
pubDate: '2026-03-22T11:45:00.000Z',
},
],
},
});
assert.ok(signals.some((signal) => signal.sourceType === 'critical_news' && signal.type === 'sovereign_stress'));
assert.ok(signals.some((signal) => signal.sourceType === 'critical_news' && signal.type === 'energy_supply_shock'));
assert.ok(signals.some((signal) => signal.sourceType === 'critical_news' && signal.type === 'shipping_cost_shock'));
});
it('extends thermal energy sensitivity to Oman and does not force unknown thermal regions into MENA', () => {
const signals = extractCriticalNewsSignals({
thermalEscalation: {
clusters: [
{
id: 'th-oman',
countryCode: 'OM',
countryName: 'Oman',
regionLabel: 'Oman',
observationCount: 10,
totalFrp: 190,
persistenceHours: 16,
status: 'THERMAL_STATUS_PERSISTENT',
context: 'THERMAL_CONTEXT_CONFLICT_ADJACENT',
confidence: 'THERMAL_CONFIDENCE_HIGH',
strategicRelevance: 'THERMAL_RELEVANCE_HIGH',
},
{
id: 'th-unknown',
countryCode: 'XX',
countryName: 'Unknown Energy Province',
regionLabel: 'Unknown Energy Province',
observationCount: 8,
totalFrp: 170,
persistenceHours: 13,
status: 'THERMAL_STATUS_SPIKE',
context: 'THERMAL_CONTEXT_CONFLICT_ADJACENT',
confidence: 'THERMAL_CONFIDENCE_HIGH',
strategicRelevance: 'THERMAL_RELEVANCE_HIGH',
},
],
},
});
const omanEnergy = signals.find((signal) => signal.sourceType === 'thermal_escalation' && signal.type === 'energy_supply_shock' && signal.region === 'Oman');
const unknownInfra = signals.find((signal) => signal.sourceType === 'thermal_escalation' && signal.type === 'infrastructure_capacity_loss' && signal.region === 'Unknown Energy Province');
assert.ok(omanEnergy, 'Oman thermal escalation should now be treated as energy-sensitive');
assert.equal(unknownInfra?.macroRegion || '', '', 'unknown thermal regions should not be forced into MENA');
});
it('dedupes corroborated critical events across news and iran event sources in world signals', () => {
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-22T12:00:00Z'),
predictions: [],
inputs: {
newsInsights: {
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'Attack reported near Ras Laffan LNG export terminal in Qatar',
primaryLink: 'https://example.com/ras-laffan-story',
threatLevel: 'critical',
sourceCount: 4,
isAlert: true,
pubDate: '2026-03-22T11:45:00.000Z',
},
],
},
iranEvents: {
events: [
{
id: 'ie-ras-laffan',
title: 'Missile strike reported near Ras Laffan LNG terminal',
category: 'airstrike',
severity: 'critical',
locationName: 'qatar',
},
],
},
},
});
const criticalSignals = worldState.worldSignals?.criticalSignals || [];
const lngSignals = criticalSignals.filter((signal) => signal.type === 'gas_supply_stress' && signal.label === 'Middle East LNG and gas export stress');
const energySignals = criticalSignals.filter((signal) => signal.type === 'energy_supply_shock' && signal.label === 'Middle East energy infrastructure stress');
assert.equal(lngSignals.length, 1);
assert.equal(energySignals.length, 1);
});
it('triages only urgent free-form critical-news candidates for structured extraction', () => {
const candidates = selectUrgentCriticalNewsCandidates({
newsInsights: {
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'Cabinet coalition talks continue ahead of reform vote',
primaryLink: 'https://example.com/politics',
threatLevel: 'moderate',
sourceCount: 3,
isAlert: false,
},
{
primaryTitle: 'Iran threatens closure of the Strait of Hormuz after tanker strike',
primaryLink: 'https://example.com/hormuz',
threatLevel: 'critical',
sourceCount: 5,
isAlert: true,
},
{
primaryTitle: 'Attack reported near Ras Laffan LNG export terminal in Qatar',
primaryLink: 'https://example.com/ras-laffan',
threatLevel: 'critical',
sourceCount: 4,
isAlert: true,
},
],
},
});
assert.equal(candidates.length, 2);
assert.equal(candidates[0].title, 'Iran threatens closure of the Strait of Hormuz after tanker strike');
assert.ok(candidates.every((item) => item.isUrgent));
assert.ok(candidates.every((item) => item.urgentScore >= 0.58));
assert.ok(candidates.every((item) => item.triageTags.length > 0));
});
it('excludes generic tragedy stories from urgent critical-news extraction when they lack transmission relevance', () => {
const candidates = selectUrgentCriticalNewsCandidates({
newsInsights: {
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'Airstrike hits hospital in Sudan as casualties rise',
primaryLink: 'https://example.com/hospital-strike',
threatLevel: 'critical',
sourceCount: 5,
isAlert: true,
},
{
primaryTitle: 'Massive house fire spreads through Minnesota neighborhood overnight',
primaryLink: 'https://example.com/house-fire',
threatLevel: 'critical',
sourceCount: 4,
isAlert: true,
},
{
primaryTitle: 'Iran threatens closure of the Strait of Hormuz after tanker strike',
primaryLink: 'https://example.com/hormuz',
threatLevel: 'critical',
sourceCount: 6,
isAlert: true,
},
],
},
});
assert.equal(candidates.length, 1);
assert.equal(candidates[0].title, 'Iran threatens closure of the Strait of Hormuz after tanker strike');
assert.ok(candidates[0].triageTags.includes('route'));
});
it('maps validated structured critical-event frames into deterministic world signals', () => {
const candidates = selectUrgentCriticalNewsCandidates({
newsInsights: {
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'Attack reported near Ras Laffan LNG export terminal in Qatar',
primaryLink: 'https://example.com/ras-laffan',
threatLevel: 'critical',
sourceCount: 4,
isAlert: true,
},
],
},
});
const validFrames = validateCriticalSignalFrames([
{
index: candidates[0].candidateIndex,
primaryKind: 'facility_attack',
impactHints: ['energy', 'gas_lng'],
region: 'Middle East',
macroRegion: 'MENA',
facility: 'Ras Laffan LNG terminal',
commodity: 'LNG exports',
actor: 'Iran-linked strike',
strength: 0.88,
confidence: 0.83,
evidence: ['Attack reported near Ras Laffan LNG export terminal in Qatar'],
summary: 'A direct strike on LNG export infrastructure is threatening gas exports.',
},
], candidates);
assert.equal(validFrames.length, 1);
const signals = mapCriticalSignalFrameToSignals(validFrames[0], candidates[0]);
const types = new Set(signals.map((signal) => signal.type));
const sourceTypes = new Set(signals.map((signal) => signal.sourceType));
assert.ok(types.has('energy_supply_shock'));
assert.ok(types.has('gas_supply_stress'));
assert.ok(sourceTypes.has('critical_news_llm'));
});
it('prefers a precomputed critical-signal bundle in world-state and trace summaries', () => {
const candidates = selectUrgentCriticalNewsCandidates({
newsInsights: {
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'Iran threatens closure of the Strait of Hormuz after tanker strike',
primaryLink: 'https://example.com/hormuz',
threatLevel: 'critical',
sourceCount: 5,
isAlert: true,
},
],
},
});
const frames = validateCriticalSignalFrames([
{
index: candidates[0].candidateIndex,
primaryKind: 'route_blockage',
impactHints: ['shipping', 'energy'],
region: 'Middle East',
macroRegion: 'MENA',
route: 'Strait of Hormuz',
commodity: 'crude oil transit',
strength: 0.9,
confidence: 0.86,
evidence: ['Iran threatens closure of the Strait of Hormuz after tanker strike'],
summary: 'Blockage risk at Hormuz is threatening shipping and oil transit.',
},
], candidates);
const llmSignals = mapCriticalSignalFrameToSignals(frames[0], candidates[0]);
const bundle = {
source: 'live',
provider: 'openrouter',
model: 'google/gemini-2.5-flash',
parseStage: 'direct_array',
failureReason: '',
candidateCount: 1,
extractedFrameCount: 1,
mappedSignalCount: llmSignals.length,
fallbackNewsSignalCount: 0,
structuredSignalCount: 0,
rawPreview: '[{"index":0}]',
candidates: candidates.map((item) => ({
index: item.candidateIndex,
title: item.title,
urgentScore: item.urgentScore,
threatLevel: item.threatLevel,
})),
signals: llmSignals,
};
const worldState = buildForecastRunWorldState({
generatedAt: Date.parse('2026-03-22T12:00:00Z'),
predictions: [],
inputs: { criticalSignalBundle: bundle },
});
assert.equal(worldState.worldSignals?.criticalExtraction?.source, 'live');
assert.equal(worldState.worldSignals?.criticalExtraction?.candidateCount, 1);
assert.equal(worldState.worldSignals?.criticalExtraction?.extractedFrameCount, 1);
const artifacts = buildForecastTraceArtifacts({
generatedAt: Date.parse('2026-03-22T12:00:00Z'),
predictions: [],
inputs: { criticalSignalBundle: bundle },
}, { runId: 'critical-bundle' });
assert.equal(artifacts.summary.worldStateSummary.criticalSignalSource, 'live');
assert.equal(artifacts.summary.worldStateSummary.criticalSignalCandidateCount, 1);
assert.equal(artifacts.summary.worldStateSummary.criticalSignalFrameCount, 1);
});
it('does not promote generic political headlines into critical world signals', () => {
const signals = extractCriticalNewsSignals({
newsInsights: {
generatedAt: '2026-03-22T12:00:00.000Z',
topStories: [
{
primaryTitle: 'Cabinet coalition talks continue ahead of reform vote',
primaryLink: 'https://example.com/politics',
threatLevel: 'moderate',
sourceCount: 3,
isAlert: false,
pubDate: '2026-03-22T11:45:00.000Z',
},
],
},
});
assert.equal(signals.length, 0);
});
});
describe('military domain guarantee in publish selection', () => {
function makeMinimalPred(id, domain, prob, confidence = 0.5) {
const pred = makePrediction(domain, 'Test Region', `Test ${domain} forecast ${id}`, prob, confidence, '30d', []);
pred.id = id;
return pred;
}
it('injects military forecast when buried below high-scoring non-military forecasts', () => {
// 14 well-scored conflict forecasts would fill the pool, leaving military out
const nonMilitary = Array.from({ length: 14 }, (_, i) =>
makeMinimalPred(`conflict-${i}`, 'conflict', 0.7 + (i * 0.001), 0.75),
);
const military = makeMinimalPred('mil-baltic', 'military', 0.41, 0.30);
const pool = selectPublishedForecastPool([...nonMilitary, military]);
const hasMilitary = pool.some((p) => p.domain === 'military');
assert.equal(hasMilitary, true, 'military forecast should be included via domain guarantee');
});
it('does not inject military when none are eligible (prob = 0)', () => {
const nonMilitary = Array.from({ length: 5 }, (_, i) =>
makeMinimalPred(`conflict-${i}`, 'conflict', 0.6, 0.6),
);
const pool = selectPublishedForecastPool(nonMilitary);
const hasMilitary = pool.some((p) => p.domain === 'military');
assert.equal(hasMilitary, false, 'no military forecast should appear when none were input');
});
it('does not double-inject military when it already ranks into selection naturally', () => {
const forecasts = [
makeMinimalPred('mil-1', 'military', 0.80, 0.75),
makeMinimalPred('conflict-1', 'conflict', 0.60, 0.60),
makeMinimalPred('conflict-2', 'conflict', 0.55, 0.55),
];
const pool = selectPublishedForecastPool(forecasts);
const militaryCount = pool.filter((p) => p.domain === 'military').length;
assert.equal(militaryCount, 1, 'only one military forecast should appear, no duplication');
});
});