Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions R/lnk_log.R
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,14 @@
"bcfishobs.observations",
"whse_fish.pscis_assessment_svw",
"cabd.dams",
"fresh.modelled_stream_crossings",
"public.wsg_outlet"
"fresh.modelled_stream_crossings"
),
source = c(
rep(fwapg, 7L),
"bcfishobs",
"bcdata bc2pg",
"CABD",
"snapshot_bcfp.sh <- bchamp objectstore",
"ad-hoc (link#227)"
"snapshot_bcfp.sh <- bchamp objectstore"
),
stringsAsFactors = FALSE
)
Expand Down
37 changes: 37 additions & 0 deletions RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,43 @@ per-source-per-species column + `lnk_barriers_unify` change — not a tweak.

---

## 8b. Drainage closure: never hand-roll it from ltree

**Use `lnk_wsg_resolve(cfg, loaded, wsgs, conn = conn)`.** It delegates to
`fresh::frs_wsg_drainage()` (fresh >= 0.33.0), which tests per-group outlet
**points** (`blue_line_key` + `downstream_route_measure`) with the measure-aware
`whse_basemapping.fwa_downstream()`.

**Do not** compute closure from `wscode_ltree` ancestry (`a.outlet @> b.outlet`).
That was the pre-#227 method and it silently over-includes, because **two watershed
groups on the same stream share an outlet code** — so `@>` is true in *both*
directions and calls each one downstream of the other. Closure is measure-aware,
not code-aware. This is why `c("PARS","BULK")` dropped from 15 WSGs to 9 when
#238 adopted fresh 0.33.0.

**Worked example — the Kootenay, where it bites hardest.** FWA carries the whole
river under one continuous `wscode_ltree = 300.625474`, including the stretch that
leaves BC near Newgate, runs through Montana and Idaho, and re-enters at Creston.
Measures chain with no gap:

```
LARL 0–130 → KOTL 130–431,808 → BULL 431,808–495,206 → SMAR 495,206–608,735 → KOTR 608,735–773,149
```

So KOTR/SMAR/BULL are **upstream** of Kootenay Lake, reached via the US loop — but
an ltree test sees them sharing KOTL's outlet code and reports them as downstream.
The correct closure of `c("LARL","KOTL","SLOC")` is **just those three**: LARL is
the terminal BC group (it holds the Kootenay's mouth at Castlegar and the Columbia
down to the border — hence Waneta and Seven Mile sitting in it), and below it is
the United States.

**`public.wsg_outlet` is gone as a concept** (#227). If you find the table in a
database it is a leftover from before fresh 0.33.0 — it still answers queries, and
it answers them wrongly. Outlets now ship in fresh at `inst/extdata/wsg_outlet.csv`
and reach the DB as a `VALUES` list; no table is needed anywhere.

---

## 8. Fast verification recipes

```bash
Expand Down
2 changes: 1 addition & 1 deletion data-raw/study_area_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#
# Cross-WSG `;DAM` correctness WITHOUT a post-consolidate recompute: each
# host gets a DRAINAGE-CLOSED bucket (focal WSGs + every WSG they drain
# through, via study_area_wsgs.R / public.wsg_outlet) run DOWNSTREAM-FIRST,
# through, via study_area_wsgs.R / lnk_wsg_resolve) run DOWNSTREAM-FIRST,
# so a WSG's downstream dam barriers are persisted before its access /
# mapping_code is computed. One study area (closed) per host.
#
Expand Down
2 changes: 1 addition & 1 deletion research/study_area_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ cyphers in order. Dispatcher-only (no cyphers): omit `--cy-workspaces`, pass one
1. **Pre-flight** (tunnel-free): local fwapg up, `fresh.streams_vw_bcfp` present,
doctl/tofu (only if cyphers).
2. **Drainage-closed DS-first buckets** (`study_area_wsgs.R`): each focal set →
its closure (every WSG it drains through, via `public.wsg_outlet`,
its closure (every WSG it drains through, via `lnk_wsg_resolve()`,
`f.outlet <@ w.outlet`) ordered downstream-first (`nlevel(outlet) ASC`),
then **filtered to bundle-species presence** (link#157).
3. **Spin + prep** cyphers (`cypher_up.sh`, `cypher_prep.sh` with
Expand Down
8 changes: 5 additions & 3 deletions research/study_areas.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ The 3 FWCP regions and their watershed groups — the parity-run scope for link

29 focal WSGs → **~52 with downstream-closure** (every WSG each drains through —
e.g. PARS → PCEA / UPCE / LPCE / FINA / PARA / LBTN). Closure + downstream-first
order are derived from `wscode_ltree` ancestry (`@>`) via the `public.wsg_outlet`
helper table (a per-WSG outlet `wscode_ltree`; see the Database Connection section
of `CLAUDE.md` and issue #227 for its reproducible build). Major drainages by root
order come from `lnk_wsg_resolve()`, which delegates to `fresh::frs_wsg_drainage()`
(fresh >= 0.33.0). **Do not hand-roll this from `wscode_ltree` ancestry (`@>`)** —
that was the pre-#227 method and it over-includes: two WSGs on the same stream share
an outlet code, so `@>` calls each downstream of the other. The closure is
measure-aware, not code-aware. See RUNBOOK section 8b. Major drainages by root
wscode: Fraser `100` (68 WSGs), Peace `200` (65), Columbia `300`/ELKR (17 — NOT a
study area), Skeena `400` (12).

Expand Down