Files
worldmonitor/scripts/validate-resilience-sensitivity.mjs
Elie Habib 8eca33790e feat(resilience): sensitivity suite v2 + ceiling-effect detection (T2.6/T2.8) (#2991)
* feat(resilience): sensitivity suite v2 + ceiling-effect detection (Phase 2 T2.6/T2.8)

Extend weight-perturbation sensitivity analysis for the three-pillar structure:

- Pass 1: domain weight perturbation (+-20%, renormalized)
- Pass 2: pillar weight perturbation (+-20%, renormalized)
- Pass 3: goalpost perturbation (+-10% of indicator goalposts)
- Pass 4: alpha-sensitivity curve (sweep 0.0-1.0 in 0.1 steps)

Release gate: block if >20% of dimensions have top-10 rank swing >3
positions under perturbation.

Ceiling/floor detection: flags any country whose overall score clips
to 100 or 0 under standard perturbation passes.

24 unit tests covering perturbWeights, perturbGoalposts, normalizeToGoalposts,
computePenalizedPillarScore, spearmanCorrelation, computeReleaseGate,
ceiling detection, computePillarScoresFromDomains, and percentile.

* fix(resilience): sensitivity exit code + per-dimension goalpost perturbation (#2991 P1)

Two P1 findings:

1. The main catch block set process.exitCode = 0, masking fatal errors
   as success. Changed to exitCode = 1.

2. The goalpost perturbation pass fed the same country-level swings
   into every dimId, so computeReleaseGate() could only pass or fail
   ALL dimensions together. Restructured to perturb one dimension's
   goalposts at a time and record per-dimension rank swings, making
   the "fail >20% of dimensions" gate actually diagnostic.

* fix(resilience): named pillar scores + stable rank sort (#2991 review)

Return Array<{id, score}> from computePillarScoresFromDomains and
look up weight by pillarWeights[entry.id] instead of positional index.
Add localeCompare tiebreaker in rankCountries for deterministic sort.
2026-04-12 10:22:21 +04:00

19 KiB