Phase 8 — Showcase walkthrough readiness¶
Date: 2026-08-02 Author: Claude (desk audit; no stack launched) Purpose: establish, before a sitting is booked, which of the six Showcase moments can actually be demonstrated — and record the owner decision on the peril-coverage gap. Companion: mid-review-phase-8.md — the framework ritual. This file is its evidence pack; the mid-review cites it rather than repeating it.
Why this exists¶
The Phase 8 exit criterion is "the Showcase walkthrough runs end-to-end in one sitting — all six moments, on a clean stack." Booking that sitting is expensive and the walkthrough is the gate on Phase 9. This audit answers the cheap question first: is there anything that makes moments 1–6 undemonstrable before we start?
Everything below was established from the repository and issue tracker. No
stack was launched — the audit machine has no Docker (docker: command not
found), so the five runtime checks of the mid-review are explicitly out of scope
here and remain owner-run.
Decision: ship with fewer perils and say so¶
Adopted 2026-08-02 (owner direction). The Showcase walks with river_flood only, and states the gap rather than implying multi-peril coverage.
This is not an exception carved out after the fact — it is the escape hatch phase-8-foundations-orsa.md §Risks already authorised:
8.9 data sourcing is the least controllable item (availability/licensing of scenario-conditioned Greek hazard data) — start it first; if a peril lacks usable projections, the showcase ships with fewer perils and says so.
The alternatives considered and rejected: pulling #412 back out of Phase 9 to source footprints first (inverts the dependency — Phase 9 is the data-foundation phase, and holding Phase 8 open for it stalls the gate), and rewriting moment 1's text to promise less (loses the record of what was intended, and the manifests already carry the honest status).
The peril gap is documented, not discovered¶
The important correction this audit makes: the data gap is not an oversight.
Both catalog manifests carry a per-peril status field and were source-verified
on 2026-07-27, with the rejected sources and the reason recorded inline.
| Peril | Scenario catalog | Historical catalog | Notes |
|---|---|---|---|
river_flood |
ingested |
ingested |
WRI Aqueduct Floods Hazard Maps v2, intensity in metres |
wildfire |
gap |
gap |
No public scenario-conditioned or return-period wildfire hazard footprint for Greece. CDS sis-tourism-fire-danger-indicators is daily fire danger, not a footprint |
storm_europe |
gap |
gap |
CDS windstorm datasets are reanalysis or present-climate synthetic event sets; none scenario-conditioned |
tropical_cyclone |
— | — | Not a gap. Absent by design: the manifests are Greece-scoped and TC is out of region. Bands and impact functions are seeded globally (0004, 0057) |
Source: scripts/scenario_hazards_manifest.json, scripts/historical_catalog_manifest.json
(sources_verified: 2026-07-27).
So the real discrepancy is between the Goal prose and the manifests, not between plan and implementation. 8.9 did its job and recorded the truth; the Showcase Goal section was never amended to match. The decision above closes that gap in the honest direction.
This also corroborates, from an independent direction, the finding that closed
#481: wildfire is not
merely unsourced, it is not computable — the ingestor declares an FWI
intensity unit that no published damage function can consume, and no
FWI-calibrated curve exists. Sourcing footprints alone would not make moment 1
multi-peril; see #412
for the brightness-temperature/FRP route that would.
Per-moment readiness¶
Legend: Built = implementing code present on main. Data = a Greek
dataset exists to exercise it. Neither implies works — that is the walkthrough's
job.
| # | Moment | Built | Data | Expectation going in |
|---|---|---|---|---|
| 1 | Address search → multi-hazard score card + "why this score" drawer | ✅ core/geocoding.py, api/v1/geocode.py, core/scoring.py, bands in 0057 |
⚠️ river_flood only | Demonstrable, degraded. Card shows one peril with data. See the open question below — what the UI renders for a banded-but-dataless peril is the single most important thing to watch |
| 2 | Map → hazard/exposure/result layers render | ✅ Phase 4 stack (martin, titiler) | ⚠️ flood layers only | Demonstrable for flood |
| 3 | Portfolio CSV upload → per-asset scores + rollup, no compute wait | ✅ asset entity (8.5) | ⚠️ scores limited to flood | Demonstrable; rollup will aggregate one peril |
| 4 | Scenario matrix (2 scenarios × 3 horizons) on scenario-conditioned data | ✅ core/ matrix runner (8.12), api/v1/compute.py batch path |
✅ river_flood scenario-conditioned entries present | The strongest moment. Flood is genuinely scenario-conditioned |
| 5 | Two engines (engine + CLIMADA sidecar) → agreement view | ✅ docker/climada-sidecar, core/engine_comparison_service.py |
✅ uses flood | Demonstrable. Phase doc flags this as the hardest item — cross-process IPC and a CLIMADA container. Highest risk of a runtime failure |
| 6 | Provenance-cited PDF report pack (ORSA template) | ✅ core/reports/orsa.py, templates/orsa_report.html, scripts/orsa_report_demo.py |
✅ uses flood | Demonstrable. docs/quickstart/orsa-walkthrough.md already documents the path |
Verified as built by file presence on main; moments 2 and 3 were confirmed
at the phase/issue level rather than by reading their implementations, and are
marked accordingly in the mid-review.
The open question to resolve during the walk¶
Score bands are seeded for four perils; data exists for one. 0057 seeds
bands for river_flood, wildfire, storm_europe and tropical_cyclone. The
score card in moment 1 is therefore capable of rendering a band for a peril with
no hazard data behind it.
What it actually does is unknown from a desk audit and matters more than anything else on this page:
- If it renders a band with no data → misleading, and a
[CRITICAL]finding. A naked band implies a computed result. - If it omits the peril silently → acceptable for the demo, but the "fewer perils" story should be visible, not implicit.
- If it errors or renders empty → cosmetic but embarrassing;
[ENHANCE-NOW].
Watch this first. It is the one place where the documented data gap can turn into a credibility problem in front of an audience, and the phase doc's own risk register calls out score credibility as a standing concern ("keep the why this score drawer visible in every demo so bands never stand naked").
Walkthrough script¶
Run in one sitting, from a clean clone. Record the outcome of each step directly into the stubbed sections of mid-review-phase-8.md.
# 0. Clean stack (one-time: docker login ghcr.io with a read:packages PAT — ADR-038)
docker compose --profile fullstack up
# then, in the UI, in order:
# 1. search a Greek address (or drop a pin) -> score card + "why this score"
# 2. open the map -> hazard/exposure/result layers
# 3. upload a portfolio CSV -> per-asset scores + rollup
# 4. run a scenario matrix (2 scenarios x 3 horizons) -> batch completes
# 5. run the same scenario through both engines -> agreement view
# 6. download the ORSA PDF report pack -> provenance cited
Unhappy paths worth trying while the stack is up (mid-review check 3):
- Search an address outside the Greek data footprint → what does the score card say? Should be an honest "no coverage", not a zero.
- Upload a malformed portfolio CSV → is the error legible?
- Request a peril with
status: gap→ this is the open question above.
What this audit did not check¶
- Nothing was executed. No stack, no UI, no report render.
- Mid-review checks 1–5 (artifact health, happy path, unhappy paths, UI/UX presentability, user-path completeness) all require the running artifact.
- Moments 2 and 3 were not read at the implementation level.
- Whether the seeded demo data is present and current on a fresh clone — the seeder has a known no-op trap (#467).