feat(deep-forecast): Phase 1 simulation package export contract#2204
Merged
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
koala73
added a commit
that referenced
this pull request
Mar 24, 2026
P1 fixes: - inferEntityClassFromName: use word-boundary regex to prevent "force" substring false positives (e.g. "workforce", "Salesforce") - buildSimulationPackageEntities: key Map entries by candidateStateId instead of dominantRegion to prevent collision across theaters sharing the same region - writeSimulationPackage call site: pass priorWorldState so actorRegistry is available to buildSimulationPackageFromDeepSnapshot P2 fixes: - buildSimulationRequirementText: apply sanitizeForPrompt to theater.label, stateKind, topChannel, and critTypes before string interpolation (stored prompt injection risk) - buildSimulationPackageEventSeeds: apply sanitizeForPrompt to entry.text before .slice(0, 200) - isMaritimeChokeEnergyCandidate: replace new Set() allocation per call with Array.includes for 2-element arrays - buildSimulationPackageEntities: convert allForecastIds to Set before actor registry loop (O(n²) → O(n)) - buildSimulationPackageEvaluationTargets: add missing candidate guard with console.warn when candidate is undefined for theater - selectedTheaters map: add label fallback to dominantRegion / 'unknown theater' to prevent "undefined" in simulationRequirement Tests: 6 new unit tests covering the word-boundary fix, entity key collision, injection stripping, and undefined label guard
Add buildSimulationPackageFromDeepSnapshot and writeSimulationPackage to produce simulation-package.json alongside deep-snapshot.json on every eligible fast run, completing Phase 1 of the WorldMonitor → MiroFish bridge defined in docs/internal/wm-mirofish-gap.md. Phase 1 scope: maritime chokepoint + energy/logistics theaters only. A candidate qualifies if its routeFacilityKey is a known chokepoint in CHOKEPOINT_MARKET_REGIONS and the top bucket is energy or freight, or the commodityKey is an energy commodity. Package shape (schemaVersion: v1): - selectedTheaters: top 1–3 qualifying candidates with theater ID, route, commodity, bucket, channel, and rankingScore - simulationRequirement: deterministic template per theater (no LLM, fully cacheable), built from label, stateKind, route, commodity, channel, and criticalSignalTypes - structuralWorld: filtered stateUnits, worldSignals, transmission edges, market buckets, situationClusters, situationFamilies touching the theater - entities: extracted from actorRegistry (forecastId overlap), stateUnit actors, and evidence table actor entries; classified into 7 entity classes (state_actor, military_or_security_actor, regulator_or_central_bank, exporter_or_importer, logistics_operator, market_participant, media_or_public_bloc); falls back to anchor set if extraction finds nothing - eventSeeds: headline evidence → live_news, disruption-keyword signal evidence → observed_disruption; T+0h timing; relative timing format - constraints: route_chokepoint_status (hard if criticalSignalLift ≥ 0.25), commodity_exposure (always hard), market_admissibility (soft, channel routing), known_invalidators (soft, when contradictionScore ≥ 0.10) - evaluationTargets: deterministic escalation/containment/spillover path questions + T+24h/T+48h/T+72h timing markers per theater Also adds 6 missing chokepoints to CHOKEPOINT_MARKET_REGIONS: Baltic Sea, Danish Straits, Strait of Gibraltar, Panama Canal, Lombok Strait, Cape of Good Hope. writeSimulationPackage fires-and-forgets after writeDeepForecastSnapshot so it does not add latency to the critical seed path. 17 new unit tests covering: theater filter, package shape, simulationRequirement content, eventSeeds, constraints (hard/soft), evaluationTargets structure, entity extraction, key format, and 3-theater cap. 🤖 Generated with Claude Sonnet 4.6 via Claude Code (https://claude.ai/claude-code) + Compound Engineering v2.49.0 Co-Authored-By: Claude Sonnet 4.6 (200K context) <[email protected]>
P1 fixes: - inferEntityClassFromName: use word-boundary regex to prevent "force" substring false positives (e.g. "workforce", "Salesforce") - buildSimulationPackageEntities: key Map entries by candidateStateId instead of dominantRegion to prevent collision across theaters sharing the same region - writeSimulationPackage call site: pass priorWorldState so actorRegistry is available to buildSimulationPackageFromDeepSnapshot P2 fixes: - buildSimulationRequirementText: apply sanitizeForPrompt to theater.label, stateKind, topChannel, and critTypes before string interpolation (stored prompt injection risk) - buildSimulationPackageEventSeeds: apply sanitizeForPrompt to entry.text before .slice(0, 200) - isMaritimeChokeEnergyCandidate: replace new Set() allocation per call with Array.includes for 2-element arrays - buildSimulationPackageEntities: convert allForecastIds to Set before actor registry loop (O(n²) → O(n)) - buildSimulationPackageEvaluationTargets: add missing candidate guard with console.warn when candidate is undefined for theater - selectedTheaters map: add label fallback to dominantRegion / 'unknown theater' to prevent "undefined" in simulationRequirement Tests: 6 new unit tests covering the word-boundary fix, entity key collision, injection stripping, and undefined label guard
koala73
force-pushed
the
feat/simulation-package-export
branch
from
March 24, 2026 16:35
b055bc9 to
eef5038
Compare
This was referenced Mar 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
buildSimulationPackageFromDeepSnapshot(snapshot, priorWorldState)toscripts/seed-forecasts.mjs— the bridge adapter from WorldMonitor's deep forecast pipeline to a MiroFish-compatible simulation packagesimulation-package.jsonbesidedeep-snapshot.jsonin R2 via fire-and-forget (zero latency impact on the seed critical path)What's in
simulation-package.jsonTop-level fields per the gap spec (
docs/internal/wm-mirofish-gap.md):schemaVersion: "v1"— explicit export contract versionselectedTheaters— up to 3 top maritime/energy candidates withrouteFacilityKey,commodityKey,topBucketId,rankingScoresimulationRequirement— deterministic template paragraph per theater (route + commodity + horizon + reaction type)structuralWorld— frozen WorldMonitor truth layer: touching stateUnits, worldSignals, marketState buckets, situationClustersentities— 7 entity classes derived fromactorRegistry,stateUnit.actors, evidence table, with fallback anchor seteventSeeds—live_news+observed_disruptionseeds with relative timing (T+0h,T+12h±6h)constraints— hard route/commodity constraints, soft market admissibility + known invalidatorsevaluationTargets— deterministic per theater: escalation/containment/spillover paths + T+24h/T+48h/T+72h timing markersTheater filter
A candidate qualifies for Phase 1 if:
routeFacilityKeyis a key inCHOKEPOINT_MARKET_REGIONS(the known maritime chokepoints already expanded in PR feat(deep-forecast): Phase 2+3 scoring recalibration + autoresearch prompt self-improvement #2178)topBucketId∈ {energy,freight} ORcommodityKey∈ energy commodity set (crude_oil, lng, natural_gas, refined_products, petrochemicals)Integration point
Tests
17 new tests in
tests/forecast-trace-export.test.mjs('simulation package export'suite):selectedTheatersshape (all fields, cap at 3)simulationRequirementdeterministic content (route name, commodity, horizon)eventSeedswithlive_newstype andT+0htimingbuildSimulationPackageKeyformat (/simulation-package.jsonsuffix)Post-Deploy Monitoring & Validation
*/simulation-package.jsonkeys appearing beside deep snapshot writes on Hormuz/Red Sea eligible runsnode -e "import('./scripts/seed-forecasts.mjs').then(m => console.log(Object.keys(m)))"— confirmbuildSimulationPackageFromDeepSnapshot,writeSimulationPackage,isMaritimeChokeEnergyCandidateare exportedsimulation-package.jsonwithselectedTheaters.length >= 1,schemaVersion: "v1", andconstraintswith at least onehard: trueentry[SimulationPackage] Write failed:— non-critical, fire-and-forget write does not affect the main seed pathContext
This is Phase 1 of the WorldMonitor→MiroFish bridge defined in
docs/internal/wm-mirofish-gap.md. The standalone package is consumable by MiroFish, any later simulator, or a structured LLM scenario-analysis workflow without human reformatting.Phases 2 (theater-limited simulation) and 3 (outcome re-ingestion) are separate follow-up PRs.