Skip to content

chore(resilience): T1.9 cache-key health sync + Phase 1 scorecard close-out#2965

Merged
koala73 merged 2 commits into
mainfrom
chore/t1-9-phase-1-close-out
Apr 11, 2026
Merged

chore(resilience): T1.9 cache-key health sync + Phase 1 scorecard close-out#2965
koala73 merged 2 commits into
mainfrom
chore/t1-9-phase-1-close-out

Conversation

@koala73

@koala73 koala73 commented Apr 11, 2026

Copy link
Copy Markdown
Owner

Summary

Final PR of the Phase 1 reference-grade upgrade. Closes out the Phase 1 acceptance gate defined in docs/internal/country-resilience-upgrade-plan.md.

Does not depend on other Phase 1 PRs at the code level

This PR references PRs #2959 (T1.7 schema), #2961 (T1.5 propagation), #2962 (T1.6 full grid), #2964 (T1.7 source-failure wiring) in the changelog but does not edit any code they touch. All five Phase 1 PRs can merge in any order.

What this PR commits

1. T1.9 cache-key / health-registry sync regression test

New tests/resilience-cache-keys-health-sync.test.mts asserts that the resilience cache-key constants from _shared.ts literally appear in api/health.js and match the expected version shape. This guards against future silent drift where a cache-key bump could leave the health registry watching the old key indefinitely. No cache keys were bumped in Phase 1 because every schema addition was additive with default fallbacks on the existing keys.

2. Methodology changelog v1.1 + Phase 1 self-assessment scorecard

docs/methodology/country-resilience-index.mdx:

3. Plan doc acceptance checklist

docs/internal/country-resilience-upgrade-plan.md: 7 of 7 Phase 1 acceptance items flipped to [x] with PR references. T1.9 task bullet closed.

Phase 1 acceptance gate status: MET

What is NOT in this PR

  • No code changes to the scorer, response builder, or widget. Docs + a single regression test.
  • No new proto fields or schema changes.
  • No cache-key bumps.
  • No external expert review (Phase 3 T3.8b, parallel workstream).
  • No Phase 2 work. Phase 2 kicks off once all five Phase 1 PRs merge.

Test plan

  • tests/resilience-cache-keys-health-sync.test.mts passes (drift guard)
  • npm run test:data still passes (no regression)
  • Methodology doc linter (T1.8 test(resilience): methodology doc linter enforces dimension parity (T1.8) #2946) still passes on the updated mdx
  • npm run lint:md clean
  • npm run typecheck clean
  • After merge, verify the changelog renders correctly on the published docs site and the scorecard table displays the six-row breakdown

Phase 2 kickoff (not this PR)

Phase 2 begins once all five Phase 1 PRs merge:

  • T2.1 three-pillar schema (proto + OpenAPI) behind schemaVersion: "2.0" feature flag
  • T2.2 recovery-capacity pillar with new Core-tier signals
  • T2.3 regroup 5 domains to 3 pillars preserving domain-weighted ranks
  • T2.4-T2.8 cross-index benchmark, outcome backtest, sensitivity suite, Railway cron wiring, ceiling-effect fixes, language-normalized information signal

Post-Deploy Monitoring & Validation

No additional operational monitoring required: this PR is docs + one regression test. No runtime behavior change, no response schema change, no new Redis keys. The cache-key drift test is CI-gated and will fail loudly on any future silent drift.

…se-out

Final PR of the Phase 1 reference-grade upgrade. Closes out the Phase 1
acceptance gate with two deliverables:

1. T1.9 cache-key / health-registry sync regression test

   New tests/resilience-cache-keys-health-sync.test.mts asserts that
   the RESILIENCE_RANKING_CACHE_KEY string from _shared.ts literally
   appears in api/health.js, and that the score/history prefixes match
   the expected resilience:<kind>:v<n>: shape. This guards against
   future silent version drift where a cache-key bump in _shared.ts
   could leave the health registry watching the old key indefinitely.

   No cache keys were bumped in Phase 1 because every schema addition
   (imputationClass, freshness) was additive with default fallbacks on
   the existing resilience:score:v7 / ranking:v8 / history:v4 keys.

2. Methodology changelog v1.1 + Phase 1 self-assessment scorecard

   docs/methodology/country-resilience-index.mdx:
   - v1.0 entry trimmed to only reference the actual v1.0 baseline PRs
     (#2821, #2847, #2858). Moved from "Current published version" to
     "Baseline".
   - New v1.1 entry inserted between v1.0 and v2.0, marked as "Current
     published version". Lists all Phase 1 tasks T1.1-T1.9 with the
     specific PRs that shipped each slice.
   - New "Scorecard (v1.1 self-assessment)" section at the end of the
     changelog with ratings on six standard composite-indicator review
     axes: Methodology 7.5, Explainability 7.5, Reproducibility 8.0,
     Source quality 7.0, Timeliness 6.5, Sensitivity 7.0. Every axis has
     a named rationale and a named gap tied to a Phase 2 or Phase 3
     task. Both Phase 1 required thresholds (Methodology >=7.5,
     Explainability >=7.5) are met.

   docs/internal/country-resilience-upgrade-plan.md:
   - Phase 1 acceptance checklist: 7 of 7 items flipped to [x] with
     PR references.
   - T1.9 task bullet closed out with a reference to this PR.

What is deliberately NOT in this PR

- No code changes to the scorer, response builder, or widget.
- No new proto fields or schema changes.
- No cache-key bumps.
- No external expert review (Phase 3 T3.8b, runs in parallel).
- No Phase 2 work.

Depends on nothing at code level; references PRs 2959/2961/2962/2964
which are still in the review queue. This PR can land independently.

Verified

- tests/resilience-cache-keys-health-sync.test.mts 3/3 passing
- methodology doc linter (T1.8) still passes on the updated mdx
- lint:md clean
- test:data clean (4355/4355)
- typecheck clean
- typecheck:api clean
@mintlify

mintlify Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
WorldMonitor 🟢 Ready View Preview Apr 11, 2026, 5:33 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@vercel

vercel Bot commented Apr 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldmonitor Ready Ready Preview, Comment Apr 11, 2026 8:43pm

Request Review

@greptile-apps

greptile-apps Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This is the Phase 1 close-out PR: it adds a cache-key / health-registry drift guard test (tests/resilience-cache-keys-health-sync.test.mts), publishes the v1.1 methodology changelog with a self-assessment scorecard, and marks all seven Phase 1 acceptance items complete in the upgrade plan. No runtime code is changed.

  • The new test is correct and consistent with the established readFileSync-at-describe-scope pattern used throughout this test suite; all three assertions are satisfied by the current constants in _shared.ts.
  • The Timeliness scorecard row contains a factual inaccuracy: it states "no real-time signals in v1.1" and describes conflict events and power outages as Phase 2 additions, but ucdpConflict, internetOutages, infraOutages, unrestEvents, and socialVelocity are all already live at Realtime or daily cadence in the current indicator registry.

Confidence Score: 5/5

Safe to merge; only remaining finding is a P2 documentation inaccuracy in the scorecard text that does not affect runtime behavior.

All three changed files are docs and a regression test. The test is correct and consistent with codebase conventions. The single P2 finding is a misleading Timeliness gap description in the scorecard, not a code defect.

docs/methodology/country-resilience-index.mdx — Timeliness scorecard gap text should be corrected before publishing.

Important Files Changed

Filename Overview
tests/resilience-cache-keys-health-sync.test.mts New drift-guard test asserting RESILIENCE_RANKING_CACHE_KEY literal appears in api/health.js and both prefix constants match versioned regex shapes; all three assertions are valid against the current constants in _shared.ts.
docs/methodology/country-resilience-index.mdx Adds v1.1 changelog entry and Phase 1 self-assessment scorecard; Timeliness gap text incorrectly states "no real-time signals in v1.1" and promises Phase 2 will add "conflict events and power outages" that are already live in the existing indicator registry.
docs/internal/country-resilience-upgrade-plan.md Closes all 7 Phase 1 acceptance items with correct PR references; T1.9 task bullet updated to reflect actual scope (drift test + scorecard, no cache-key bumps).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["_shared.ts constants\n(RESILIENCE_RANKING_CACHE_KEY\nRESILIENCE_SCORE_CACHE_PREFIX\nRESILIENCE_HISTORY_KEY_PREFIX)"] -->|"T1.9 drift guard\n(this PR)"| B["resilience-cache-keys-health-sync.test.mts"]
    B --> C{"ranking key in\napi/health.js?"}
    C -->|pass| D["health probe watches\ncorrect key"]
    C -->|fail| E["CI blocks merge\n— key bumped without\nupdating health.js"]
    B --> F{"score prefix matches\nresilience:score:v<n>:?"}
    F -->|pass| G["shape invariant holds"]
    F -->|fail| H["typo/rename caught\nat test time"]
    B --> I{"history prefix matches\nresilience:history:v<n>:?"}
    I -->|pass| G
    I -->|fail| H
Loading

Reviews (1): Last reviewed commit: "chore(resilience): T1.9 cache-key health..." | Re-trigger Greptile

| **Explainability** | 7.5 | Per-dimension confidence grid in the widget shows coverage %, imputation class, and freshness for every dimension on every country. Tooltip text is generated from the taxonomy so analysts can click through to the meaning without reading this document. Gap: no waterfall chart of individual signal contributions yet, that lands in Phase 3 T3.3. |
| **Reproducibility** | 8.0 | Every dimension's sourceKey, cadence, and goalpost lives in `_indicator-registry.ts` and is linted against this doc. Cache keys are versioned (`resilience:score:v7`, `ranking:v8`, `history:v4`). `dataVersion` is written by the seed and plumbed to the widget footer. Gap: the benchmark and backtest scripts do not yet run on a CI cron; those land in Phase 2 T2.7. |
| **Source quality** | 7.0 | World Bank, IMF, WHO, IEA, UNHCR, UCDP, IPC, BIS, FAO, RSF, GPI: all authoritative. Gap: curated-list sources (BIS ~40 economies, WTO) do not cover the full WorldMonitor country set, which is why the `unmonitored` imputation class exists. Phase 2 T2.9 adds language-normalized information signal to reduce English-press bias. |
| **Timeliness** | 6.5 | Annual sources dominate (WGI, GPI, RSF, WHO). Freshness classifier makes this visible at the dimension level so users can see which parts of a country score are fresh vs. 12 months old. Gap: no real-time signals in v1.1; Phase 2 adds FX volatility, conflict events, and power outages at daily cadence. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Timeliness gap description contradicts the existing indicator registry

The gap note claims "no real-time signals in v1.1; Phase 2 adds FX volatility, conflict events, and power outages at daily cadence," but the Dimensions and Indicators tables in this same document already list ucdpConflict (Realtime), internetOutages (Realtime), infraOutages (Realtime), unrestEvents (Realtime), and socialVelocity (Realtime) as live signals — and these predate Phase 1. "Conflict events" and "power outages" are therefore not Phase 2 additions. A reader scoring the index against this section will reach a false conclusion about what data it currently uses.

Suggested change
| **Timeliness** | 6.5 | Annual sources dominate (WGI, GPI, RSF, WHO). Freshness classifier makes this visible at the dimension level so users can see which parts of a country score are fresh vs. 12 months old. Gap: no real-time signals in v1.1; Phase 2 adds FX volatility, conflict events, and power outages at daily cadence. |
| **Timeliness** | 6.5 | Annual sources dominate (WGI, GPI, RSF, WHO). Freshness classifier makes this visible at the dimension level so users can see which parts of a country score are fresh vs. 12 months old. Gap: most structural indicators (WGI, GPI, RSF, WHO) are annual only; BIS FX data is monthly; the majority of indicator weight comes from annual sources even though several stress signals (conflict, outages, unrest, social velocity) are already realtime or daily. Phase 2 adds FX volatility at daily cadence and raises the share of high-frequency signals across more dimensions. |

Greptile P2 finding: the Timeliness row in the Phase 1 self-assessment
scorecard claimed "no real-time signals in v1.1" and described
conflict events and power outages as Phase 2 additions, which is
factually wrong. Thirteen stress-side indicators already run at
realtime or daily cadence via the cross-source stack:

  realtime: ucdpConflict, internetOutages, infraOutages,
            unrestEvents, socialVelocity
  daily:    sanctionCount, cyberThreats, gpsJamming,
            shippingStress, transitDisruption, gasStorageStress,
            energyPriceStress, newsThreatScore

The real cadence gap is that structural sources (WGI, GPI, RSF, WHO,
IMF macro) are annual and still carry the majority of index weight,
while the live-shock pillar is already rolling. Phase 2 T2.2 adds
FX volatility at daily cadence to narrow the gap on the
currency-external dimension.

Score itself unchanged (6.5), it was a defensible number. Only
the gap rationale is corrected to match reality.
@koala73

koala73 commented Apr 11, 2026

Copy link
Copy Markdown
Owner Author

Thanks, P2 was valid. Fixed in 325a60a. Corrected the Timeliness row gap rationale to match the actual _indicator-registry.ts cadences.

Verified against origin/main's registry:

  • Realtime: ucdpConflict, internetOutages, infraOutages, unrestEvents, socialVelocity
  • Daily: sanctionCount, cyberThreats, gpsJamming, shippingStress, transitDisruption, gasStorageStress, energyPriceStress, newsThreatScore

The real timeliness gap is that structural sources (WGI/GPI/RSF/WHO/IMF macro) remain annual and still carry the majority of weight, while the live-shock pillar is already rolling. Phase 2 T2.2 adds FX volatility daily to narrow the gap on currency-external. Score itself unchanged (6.5), it was a defensible number, only the gap rationale needed correcting.

lint:md and T1.8 dimension-parity linter both pass on the updated mdx.

@koala73
koala73 merged commit 49a2c54 into main Apr 11, 2026
11 checks passed
@koala73
koala73 deleted the chore/t1-9-phase-1-close-out branch April 11, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant