Phase 7 — Extensibility, reports, docs polish¶
Status: Planned. See plan.md for the phase overview. Scope: extensibility proof + reports + polish items. Covers #12, #32, #14 Tier 2 subset, #28 Storybook, #F Astro site, gap-14 full engine parity, rolling observability artifacts, #O privacy banner. Predecessor: Phase 6 — Admin + ops + catalog. Successor: none committed; see phase-managed-hosting.md and phase-parking-lot.md for candidates.
Goal¶
Prove the adapter-by-design commitment (ADR-027) is real: ship the first non-default compute adapter (CLIMADA-in-sidecar) and the first non-CLIMADA ingest adapter (GEM). Deliver the Tier 2 reports subset (save scenario is in Phase 3; add standardized PDF + map snapshot here). Stabilise the redesign with Storybook, split the marketing surface into a dedicated Astro site, land full engine-parity coverage, publish performance / log-sensitivity / engine-cost artifacts, and add the privacy banner.
This is the last phase in the currently committed roadmap. After closing this, the backbone + UI are feature-complete for the researcher + agency personas; anything further is in the parking lot or managed-hosting track.
Entry conditions¶
- Phase 6 closed: admin panel + catalog + ingest pipeline live.
- ADR-027 (adapter-by-design) merged in Phase 3.
Scenariomodel + provenance shipped.- UI redesign (ADR-030) stabilised — Storybook can start without rotting.
Out of scope (deferred)¶
- Managed hosting, K8s implementation — parked.
- Stripe billing, custom report templates (#14e), bulk scenario submission, webhooks, map drawing tools, building-level / 3D, GPU engine — parking lot.
- Scenario versioning (#P), data versioning (gap-8), frequency-curve uncertainty bands (#L) — parking lot / gated on engine work.
- User-provided engines Level 3b — parking lot, security-sensitive.
Scope¶
7.1 — IngestAdapter ABC + registry (#12 architecture)¶
Context. Vision #12 Tier 3 architecture. Defines the IngestAdapter
interface and a registry pattern so subsequent adapters (GEM, Hazus,
OASIS LMF) plug in without backbone changes.
Acceptance criteria.
- [ ] src/climate_lama/ingest/adapters/base.py defines the ABC:
supports(mime_type, manifest), validate(path, manifest),
ingest(path, manifest, dataset_id).
- [ ] Registry mechanism via Python entry points (under
climate_lama.ingest_adapters). Backbone discovers third-party
adapters from installed packages.
- [ ] Refactor existing CSV + XLSX upload paths (Phase 6) to sit behind
the ABC as the two first-party adapters.
- [ ] Unit tests: registry discovery, adapter selection per
mime_type/manifest.
- [ ] ADR-033 "IngestAdapter ABC + registry" in DECISIONS.md with
**Phase**: 7 header — the sub-ADR under the ADR-027 parent.
Cross-stack: backbone.
Linked ADR: authors ADR-033; sub-ADR of ADR-027.
Suggested /analyze tier: 4 (Opus · high) — architectural refactor
touching existing upload paths.
7.2 — First non-CLIMADA ingest adapter: GEM¶
Context. Vision #12 Tier 3 first alternative format. GEM exposure CSV is open, global building-stock standard — the lowest-friction non- CLIMADA format to prove the pattern.
Acceptance criteria.
- [ ] New repo / package climate-lama-adapter-gem per ADR-027 packaging
rule; publishes to PyPI.
- [ ] Implements IngestAdapter ABC (7.1): ingests GEM exposure CSV;
emits our exposure data model.
- [ ] Backbone declares optional extra: pip install climate-lama[gem]
pulls it.
- [ ] Integration test: a real GEM sample CSV ingests successfully and
appears in the catalog.
- [ ] Docs-site page adapters/gem.md.
Cross-stack: new repo + backbone packaging metadata + docs.
Linked ADR: references ADR-027, ADR-033.
Suggested /analyze tier: 4 (Opus · high) — new repo + publish
pipeline + schema mapping.
7.3 — CLIMADA compute engine adapter (#32, #24 Level 2)¶
Context. Vision #32 + #24 Level 2 reference implementation. A subprocess-based adapter invoking CLIMADA in a sidecar container, honouring ADR-024 (backbone never imports CLIMADA). Proves pluggable engines work end-to-end; acts as a compat bridge for CLIMADA users.
Acceptance criteria.
- [ ] New repo climate-lama-adapter-climada with ClimadaEngineAdapter
implementing ModelInterface from worker/models/base.py.
- [ ] Adapter communicates with a CLIMADA sidecar container over a
subprocess / IPC boundary — no import climada in the backbone or
engine; the sidecar is the only process with CLIMADA installed.
- [ ] Engine selection via X-Engine: climate_lama (default) or
X-Engine: climada header on POST /v1/compute/impact. Request
routing lives in worker/models/registry.py.
- [ ] Input/output contracts match the existing ModelInterface;
adapter translates to/from CLIMADA types.
- [ ] Integration test: same inputs through both engines, impact matrices
within 1% (ties to 7.7 parity harness).
- [ ] Docs-site page engines/climada-adapter.md explaining when to
use it (compat bridge, validation) and when not (default path stays
climate-lama-engine).
- [ ] ADR-034 "Engine registry + request-time dispatch" as the sub-ADR
under ADR-027 / #N; **Phase**: 7 header.
Cross-stack: new repo + backbone (registry + dispatch) + worker
(adapter loading).
Linked ADR: authors ADR-034.
Suggested /analyze tier: 5 (Opus · extra high) — CLIMADA-isolation-
adjacent (rubric bump), cross-process IPC, load-bearing.
7.4 — Standardized PDF report (#14a+d+b Tier 2 subset)¶
Context. Vision #14 Tier 2 subset: save scenario already shipped in Phase 3; this delivers the standardized PDF report via Quarto + the light map-snapshot via canvas export.
Acceptance criteria.
- [ ] Celery task render_report(scenario_id, template="standard")
invokes Quarto with a .qmd template + scenario data, writes the PDF
to reports/{org_id}/{report_id}.pdf per ADR-029.
- [ ] Standard template: cover, summary metrics, map, frequency curve,
cost-benefit, methodology, sources (attribution), reproducibility
stamp (Phase 3 #3.8).
- [ ] POST /v1/scenarios/{id}/reports triggers render;
GET /v1/scenarios/{id}/reports/{report_id} returns the PDF.
- [ ] Quarto container added to the stack; CI smoke test renders one
sample report.
- [ ] UI: "Export report" button on scenario view; progress indicator;
download when done.
- [ ] Map snapshot light: leaflet-image equivalent for MapLibre (native
map.getCanvas().toDataURL()) — saves current view as PNG embedded
in the report.
- [ ] Custom templates (#14e) remain out of scope (Tier 4).
Cross-stack: backbone + worker + UI + infra (Quarto container).
Linked ADR: short ADR "Quarto as report generator" optional —
author if the /build agent hits non-obvious trade-offs.
Suggested /analyze tier: 5 (Opus · extra high) — multi-component
(worker + template + UI + infra), new dep with real ops implications,
failure modes numerous.
7.5 — Storybook (#28 Tier 3)¶
Context. Vision #28 Tier 3 Storybook. Introduced now that redesign (ADR-030) has stabilised — stories won't rot on day one. Scope: shared components only; not every page.
Acceptance criteria.
- [ ] Storybook project at climate-lama-ui/.storybook/ with Vite
integration.
- [ ] Stories for shared components: buttons, panels, chart wrappers,
layer toggle, InfoIcon, ErrorDisplay, ImpactFunctionChart,
brand-aware theme preview.
- [ ] CI job builds Storybook on PR; static bundle deployed alongside
the docs site (or Netlify preview — decide during /build).
- [ ] Visual-regression tooling (Chromatic / Percy) deferred — note in
docs why.
- [ ] Docs-site page contributing/storybook.md for contributor
onboarding.
Cross-stack: UI + CI + docs.
Linked ADR: none.
Suggested /analyze tier: 3 (Sonnet · high).
7.6 — Astro marketing site (#F)¶
Context. Landing site placement resolution: start with MkDocs
Material's landing page (Phase 3 #3.6); now split to a dedicated Astro
site in climate-lama-site repo. Mobile-shareable demo URL is the
argument; docs and marketing diverge enough that keeping them fused
hurts both.
Acceptance criteria.
- [ ] New repo climate-lama-site with Astro scaffold.
- [ ] Pages: landing (hero + features + CTA to docs/quickstart + CTA to
GitHub), a "why Climate-Lama" narrative, pricing placeholder (empty
until managed hosting goes live), contact.
- [ ] Mobile-first responsive; Lighthouse score ≥90 on mobile.
- [ ] Deploy pipeline: Cloudflare Pages or Netlify, auto-deploy on push
to main, preview URLs on PR.
- [ ] Content migrated: the MkDocs landing page in Phase 3 reverts to a
neutral docs home; the marketing copy moves to Astro.
- [ ] Docs site links to the marketing site from its header; marketing
site links to docs from every page.
- [ ] **Phase**: 7 noted in the repo README.
Cross-stack: new repo + docs updates.
Linked ADR: none.
Suggested /analyze tier: 4 (Opus · high) — new repo, design copy,
deploy pipeline.
7.7 — Full engine parity coverage (gap-14)¶
Context. Phase 3 #3.12 shipped the parity harness scaffold + one working comparison. This item expands coverage to all four hazards (RF, TC, WF, WS) and a matrix of scenarios + exposures, publishes a parity report, and commits to a tolerance policy.
Acceptance criteria.
- [ ] Parity tests cover: RF × Greek buildings, TC × global coastal
exposure, WF × Mediterranean, WS × Western Europe — each at present +
2050 RCP4.5 + 2050 RCP8.5.
- [ ] Per-metric tolerances documented in
tests/parity/tolerances.yaml: EAD within 1%, AAI within 1%,
frequency-curve points within 2% at each return period.
- [ ] Parity report generated as part of the CI workflow (still gated
by workflow_dispatch — long-running); published to docs site under
architecture/engine-parity-report.md.
- [ ] Known discrepancies (if any) documented with root-cause analysis;
decide whether to align the engine, accept the deviation (with
rationale), or file an engine issue.
Cross-stack: tests + docs.
Linked ADR: none; extends #3.12 scaffold.
Suggested /analyze tier: 5 (Opus · extra high) — research-flavored
ambiguity, numerical correctness, CLIMADA-adjacent.
7.8 — Rolling observability artifacts (gap-10/11/12)¶
Context. Vision gaps 10 (performance budgets), 11 (cost of engine calls), 12 (log-sensitivity classification) — all Tier 3 "publish as we go." This item batches them into a single rolling publication.
Acceptance criteria.
- [ ] docs/architecture/performance-budgets.md published with benchmarks:
"100k points: <1s; 1M points: ~10s; 10M points: plan ahead." Ties to
Phase 4 #4.11 Playwright perf tests.
- [ ] docs/architecture/engine-call-cost.md: CPU-seconds + memory
envelope per hazard × dataset-size combination, read from the usage_events
table (Phase 6 #6.11).
- [ ] docs/architecture/log-sensitivity.md: classifies each structlog
field as PII / tenant-metadata / operational / debug. Introduces a
per-deployment filter config that can redact PII fields at the
structlog processor level.
- [ ] Log sensitivity filter config documented with a worked example for
a regulated self-hoster.
- [ ] CI job regenerates the performance budget doc on every Playwright
perf run so it stays fresh.
Cross-stack: docs + small backbone change (structlog filter config).
Linked ADR: none.
Suggested /analyze tier: 3 (Sonnet · high).
7.9 — Privacy / data residency banner (#O)¶
Context. Vision #O Tier 3. "No external calls, no telemetry, your data stays here" surfaced in marketing + UI footer. Already true per plan.md; just needs to be a marketed feature.
Acceptance criteria.
- [ ] UI footer component: "Self-hosted • No external calls • Your data
stays here" with link to concepts/privacy.md.
- [ ] Astro marketing site (7.6) has a "Privacy & data residency"
section on landing + a dedicated /privacy page.
- [ ] Docs-site page concepts/privacy.md enumerates the guarantees:
no egress, no telemetry, self-host-only compute, attribution of
third-party data sources (which may have their own terms).
- [ ] Verify: a backbone instance run without any external network
access (Docker network with internal: true) starts + serves +
completes one compute job. CI job captures the verification.
Cross-stack: UI + marketing site + docs + CI.
Linked ADR: none.
Suggested /analyze tier: 3 (Sonnet · high).
ADRs authored in this phase¶
| ID | Title | Owner work item |
|---|---|---|
| ADR-033 (approx.) | IngestAdapter ABC + registry | 7.1 |
| ADR-034 (approx.) | Engine registry + request-time dispatch | 7.3 |
Numbers assigned at merge time; may shift.
Exit criteria¶
- All 9 work items closed.
pip install climate-lama[climada]pulls the CLIMADA adapter and theX-Engine: climadaheader routes compute to it.pip install climate-lama[gem]pulls the GEM ingest adapter and a GEM CSV ingests successfully.- Standardized PDF report renders end-to-end and is downloadable from the UI.
- Engine parity report published; known discrepancies documented.
- Astro marketing site live at the project's public URL.
- Storybook bundle deployed alongside docs.
- Privacy guarantee verified by CI (instance boots + computes with no network egress).
Risks¶
- 7.3 CLIMADA adapter is the single most complex item in the phase.
Subprocess IPC, CLIMADA install in a sidecar, input/output translation
all have sharp edges. Budget the highest
/analyzetier;/build --reviewmandatory. - 7.4 report rendering via Quarto adds a container + a heavy dep; if the ops overhead turns out to be painful, descope to WeasyPrint as a fallback path documented in the report ADR.
- 7.7 parity coverage can discover real engine bugs. Treat engine bugs as Phase 1/engine-repo issues, not blockers on this phase — the parity work's deliverable is the report, not the fixes.
- 7.6 Astro site — ongoing content maintenance. Keep the scope tight: landing + 3-4 static pages. Growing it is a future phase.