Export the pooling group as a WINFAP-compatible .pt file
Brought by Chris Cameron-Hann · 21 Aug 2026, 09:12 · MIT
Progress
Shipped to dev- Submitted
- Picked up
- In preview
- Shipped to dev
Submitted → the agent picks it up and drafts a spec and pull request → a person reviews on a preview → it ships to dev.hydrometric.io.
Request
When I have settled on a pooling group in Hydrometric I still want to open the same sites in WINFAP for a second opinion, and to hand the group to a reviewer who only has WINFAP. Add an Export button on the Pooling Group card that writes a .pt file: one row per pooled site with station number, name, record length, L-CV, L-skew, and the site weighting Hydrometric used. Same column order WINFAP expects so it imports without editing.
Agent spec
## Problem Once an analyst has settled on a pooling group in Hydrometric they often want to open the same sites in WINFAP for a second opinion, or hand the group to a reviewer who only has WINFAP. Today the Pooling Group card offers no export, so the group has to be re-keyed by hand. ## Proposed change Add an **Export .pt** button to the Pooling Group panel header. Clicking it downloads `pooling-group-<stationId>.pt`, a plain-text file with one row per pooled site in the order WINFAP expects, so it can be imported without editing. Columns, in the contributor's stated order: 1. Station number 2. Station name (river + name) 3. Record length (years) 4. L-CV (at-site) 5. L-skew (at-site) 6. Site weighting used by Hydrometric (the L-CV weight) The export reflects the **effective** group: client-side exclusions are dropped, force-included stations are kept, and in read-only (original analysis) context fork edits are ignored — exactly what the table already displays. The button is only rendered when `labsEnabled()` is true. Because the pooling panel is a client component and the flag is server-only, the flag is passed down once from the `(app)` layout via a small React context (`LabsFlagProvider` / `useLabsEnabled`), no new env var. Nothing in the QMED chain, pooling formation or growth-curve fitting is touched — this is a formatting/download concern only. ## Files - `packages/web/src/lib/export/winfap-pt.ts` — pure `buildWinfapPt(stations, opts)` → string (new) - `packages/web/src/lib/export/__tests__/winfap-pt.test.ts` — unit tests (new) - `packages/web/src/lib/export/table-export.ts` — export existing `triggerDownload` for reuse - `packages/web/src/components/labs/labs-flag-context.tsx` — context + hook (new) - `packages/web/src/app/(app)/layout.tsx` — wrap children in `LabsFlagProvider` - `packages/web/src/components/analysis/pooling-panel.tsx` — Export button in `PanelHeader rightAction` ## Acceptance criteria 1. With `HYDROMETRIC_SHOW_LABS=true`, the Pooling Group panel shows an **Export .pt** button; with the flag unset the button is absent and no other behaviour changes. 2. Clicking it downloads `pooling-group-<stationId>.pt` with one row per displayed pooled site, columns in the order above, tab-separated, `\r\n` line endings, numeric values to 4 d.p. 3. Excluded stations are absent from the file; user-added stations are present; row order matches the on-screen table. 4. `buildWinfapPt` is covered by unit tests for: column order, exclusion filtering, number formatting, and neutralisation of CSV-injection-style names (reuse `neutraliseCsvCell`). 5. **Manual gate before un-drafting:** a reviewer imports the file into WINFAP 5 and confirms it loads without editing. This is the real acceptance test and cannot be automated here. ## Risks / open questions - **The exact WINFAP `.pt` layout is not in this repo.** No fixture or doc here describes the header block, delimiter or column order WINFAP 5 actually parses. The draft implements the contributor's stated columns as tab-separated text with a single `#` comment header. If WINFAP needs a different delimiter, a version/header block, or extra columns (e.g. QMED, AREA, discordancy), the writer is a single pure function and can be corrected without touching the UI. - Which L-CV/L-skew to emit is ambiguous: WINFAP works on deurbanised at-site L-moments for SM2025. The draft emits the at-site values the table shows (`lCV`, `lSkew`); if WINFAP expects the urban-adjusted or non-flood-adjusted values this needs a switch. - Weighting: Hydrometric carries separate L-CV and L-skew weights; WINFAP shows one. The draft exports the L-CV weight and flags this with a TODO. ## Credit Contributed by Chris Cameron-Hann under the MIT licence (Labs submission a1b2c3d4-0000-4000-8000-000000000001).