fix(simulation): normalize commodityKey underscores and expand CHANNEL_KEYWORDS (#2410)

Two matching bugs causing adjustment=0 even after #2402+#2404:

1. commodityKey underscore: code checked text.includes('crude_oil') but
   LLM-generated text always uses natural language ('crude oil'). Fixed
   by .replace(/_/g, ' ') in both contradictsPremise and negatesDisruption.

2. CHANNEL_KEYWORDS too narrow: risk_off_rotation only matched 4 exact
   phrases ('risk off', 'risk aversion', 'flight to safety', 'sell off').
   Simulation paths use broader language ('capital flight', 'risk premium',
   'sell-off', 'retreat', etc.). Expanded to cover LLM output vocabulary.
   Also expanded security_escalation to include 'military', 'geopolit'.

Update test: negatesDisruption commodity test now uses natural language
('crude oil') matching what LLM actually generates, not the internal key.
This commit is contained in:
Elie Habib
2026-03-28 12:01:35 +04:00
committed by GitHub
parent 0be92c5949
commit e6a85f0a36
2 changed files with 8 additions and 5 deletions

View File

@@ -6540,7 +6540,10 @@ describe('phase 3 simulation re-ingestion — matching helpers', () => {
it('negatesDisruption detects commodity restoration', () => {
const candidatePacket = { routeFacilityKey: '', commodityKey: 'crude_oil' };
assert.ok(negatesDisruption('crude_oil supply chain restored to normal operations', candidatePacket));
// commodityKey is normalized to "crude oil" (space) before text matching — LLM text uses natural language
assert.ok(negatesDisruption('crude oil supply restored to normal operations', candidatePacket));
// underscore form in text would no longer match (correct — LLM never emits "crude_oil")
assert.ok(!negatesDisruption('crude_oil supply chain restored to normal operations', candidatePacket));
});
it('negatesDisruption returns false when no route/commodity and no stateKind/bucket on candidate', () => {