Skip to content

feat: Migrant Life-Map MVP — multi-country life expectancy + life-context modifiers (#27)#39

Merged
glebis merged 16 commits into
feat/cross-section-gene-linksfrom
feat/risk-demographic-selector
May 31, 2026
Merged

feat: Migrant Life-Map MVP — multi-country life expectancy + life-context modifiers (#27)#39
glebis merged 16 commits into
feat/cross-section-gene-linksfrom
feat/risk-demographic-selector

Conversation

@glebis

@glebis glebis commented May 30, 2026

Copy link
Copy Markdown
Owner

Migrant Life-Map MVP (#27, track A2+F)

A standalone #/life-map view that blends multiple countries' life expectancy for migrants, using real, citable data — not arithmetic guesses.

Stacked PR. Based on feat/cross-section-gene-links (open PR #36) since this branch was cut from it. The diff here is life-map-only. Retarget to main once #36 merges.

What it does

  • Country anchors are the primary truth: each lived-in country's life-expectancy-at-current-age, side by side (the spread is the point).
  • Migration context marker: a years-lived-weighted blend with current-residence emphasis, permanently labelled a heuristic — never "your life expectancy."
  • Life-context modifiers (stress / mental-health / family history): qualitative and supportive by default; an opt-in wide, caveated range is offered only for strong-evidence factors. Mental-health items are evidence-gated so they can never become a scary number.

Data

  • Reproducible fetcher (scripts/fetch_life_expectancy.py) pulls Eurostat demo_mlexpec (31 EU countries, single-year ages) + WHO GHO (Russia, sparse brackets) into a committed, version-stamped config/life_tables.json. Pure parsers are unit-tested against recorded fixtures; live fetch only under __main__.

Honesty guardrails

  • Country figures labelled period life expectancy, not a personal prediction.
  • Blend is always a labelled heuristic shown alongside the anchor spread.
  • WHO sparse brackets handled correctly (target age = matched bracket age + ex, not current age + ex).
  • Mental-health modifiers cannot produce a number.

Tests (TDD throughout)

  • lib/lifeBlend (9), useResidenceHistory + useLifeMap (8), LifeMap (4), LifeModifiers (4) — frontend 550 passed.
  • Fetch-script parsers + route + view registration — backend 624 passed.

Decisions

Design consulted with Codex; both agreed on the standalone view, anchors-primary blend, and deferring the genetic overlay. Specs + plan included under docs/superpowers/.

Deferred (separate tracks)

Life-calendar/timeline visuals (B), CLI/MCP shareable social cards (C), genetic-correlation overlay, functional self-tests (E).

🤖 Generated with Claude Code

glebis and others added 16 commits May 29, 2026 16:59
Continuation of #27: user-selectable demographic that swaps demographic-keyed
mortality data, plus life-expectancy/HALE data layer to unblock the future
life-calendar visual. Project A of a 3-part decomposition (data / visuals / share).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Standalone #/life-map view: blends multiple countries' life expectancy (Eurostat
EU + WHO Russia) as side-by-side anchors plus a clearly-labeled heuristic migration
marker, with qualitative stress/mental-health/family modifiers (evidence-gated, no
scary numbers). Real data via reproducible fetch script -> committed versioned file.
Design consulted with Codex; both agreed on standalone view, anchors-primary blend,
deferred genetic overlay.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rse data) (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ata (#27)

31 countries (broad EU via Eurostat single-year ages + Russia via WHO sparse
brackets), version-stamped with per-country source, committed to config/.
Pure parsers unit-tested against recorded fixtures; live fetch under __main__.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…difiers config (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…, wired into nav (#27)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Qualitative by default; opt-in caveated range only for strong-evidence factors;
mental-health items can never produce a number.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tic blend, qualitative modifiers only (#27)

Never exports opt-in year ranges; labels blend a heuristic not a prediction.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…port bar (#27)

SVG axis shows each country anchor + heuristic blend band; LifeMapGlyph is a
deterministic migration-journey glyph (not GenomeGlyph); HeroHeader gains an
optional icon slot. Codex-consulted redesign.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…talogue (#27)

Factors are now opt-in toggles persisted per user; only chosen factors render
detail cards and appear in export. Removes the false personalization where every
user saw 'Diagnosed anxiety disorder' etc. regardless. Evidence gating preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fix phantom `--text-primary` -> `--text` (axis labels were rendering pure black)
- Drop redundant fallbacks for tokens that exist (--border-strong/-dashed, --sig-monitor)
- Use --primary-strong for 'CURRENT' tag + selected chips (AA contrast on inset bg)

Addresses audit M1, M2 (feature-local), L3. Token-only; no behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… a11y semantics (#27)

- useLifeMap: surface fetch errors + reload(); LifeMap shows retry on failure (H1 audit)
- Residence rows wrap on mobile; long country names wrap; 44px touch targets on
  inputs/chips/radio/remove (H1/H2)
- HeroHeader title is now an <h1> (one heading per view, fixes hierarchy across sections; M3)
- LifeExpectancyAxis aria-label exposes per-country values + heuristic blend to SR (M4)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace inline chip styles with a .lifemap-chip class: hover/active/focus-visible
states, transitions (registered for prefers-reduced-motion), selected styling via
aria-pressed. Matches the app's .btn state system.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@glebis glebis merged commit 9c30823 into feat/cross-section-gene-links May 31, 2026
2 checks passed
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