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
25 changes: 25 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,31 @@ Experimental package — breaking all the time and loving the learning curve. St
**Prefix:** `lnk_`
**Branch:** `main` (current version: `DESCRIPTION` / [`NEWS.md`](NEWS.md))

## Status (2026-10-02, late) — MAD ranges for BT, GR, KO and RB in `default_tuned` (#302)

**`default_tuned` now carries mean-annual-discharge ranges for the four species
`default` leaves without one; they are inert while every group is on `cw`.**
- Values (m³/s, maxima open): BT 0.078 / 0.078, GR 0.96 spawn / 0.97 rear, RB 0.011 /
0.019, KO 0.57 (unscored). Scored on held-out WSGs by a rule fixed before the build;
every P10 → P05 loosening was refused except RB spawning.
- **Cost before moving any group to `mad`:** at least −33 % BT and −82 % GR stream
rearing against `cw` on the held-out WSGs. Stream size and sampling effort are not
separated; a size-stratified core is the next tuning. `research/habitat_thresholds.md`,
"MAD (discharge)"; archive `planning/archive/2026-10-issue-302-mad-thresholds/`.

**Facts not worth re-deriving:**
- **The variants harness scores MAD ladders now:** `model` / `set` columns, an anchor
rung (cw base → first `mad` rung, taken by construction), `_min` loosens downward, a
MAD ladder's core is its rungs only (the cw base cuts on width), `--floor`,
`--working-prefix` derived from `--prefix`. #284's re-score reproduces all ten outputs.
- **Build classifiers from fresh's compiled SQL, never from `rules.yaml`.** fresh's
main rear predicate ignores a W rule's `wetland_ha_min`, and its `L` rules include
reservoirs (fresh issue drafted, not filed). A rear size range gates the
`lake_rearing` / `wetland_rearing` bucket columns, never `rearing`.
- **`elevation_adjusted.csv`'s band classes are not the bands.** A segment takes the first
step whose flags differ, so an anchor's `removed` class is only what no rung restores.
Quote `bands_pooled.csv` for a band's rate.

## Status (2026-10-02) — the validator scores each group on its own model (#299)

**`lnk_habitat_validate()` re-tests a `mad` group on discharge, not width.**
Expand Down
16 changes: 13 additions & 3 deletions RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -702,12 +702,22 @@ next dispatch.**
group. `log_input` fingerprints it.
- **What `mad` changes** (fresh's rules, after bcfishpass): stream rules that
inherit thresholds test `mad_m3s` against `*_mad_min/max` instead of channel
width, so species with no MAD thresholds (BT, GR, KO, RB) lose all stream
habitat; the rule-level `channel_width` river-polygon bypass is ignored; SK/KO
width, so species with no MAD thresholds (BT, GR, KO and RB in `default` and
`bcfishpass`) lose all stream habitat; the rule-level `channel_width` river-polygon bypass is ignored; SK/KO
lake rearing is polygon membership. **Lake, wetland and `thresholds: false`
rules inherit nothing under either model**, so BT keeps its wetland and
1050/1150-edge rearing in a `mad` group (ADMS: 63.5 km, all inside
waterbodies). link also skips the stream-order rearing bypass
waterbodies). That holds for the `rearing` flag. The separate `lake_rearing` /
`wetland_rearing` bucket columns (fresh's `build_wb_pred()`) are gated by the
species' rear size range whenever it has one: by width under `cw`, and by
discharge under `mad`. A species with no rear MAD range keeps them on polygon
membership alone. fresh's main predicate also ignores a W rule's
`wetland_ha_min` (only `build_wb_pred()` applies it).
- **`default_tuned` carries MAD ranges for BT, GR, KO and RB** (#302); `default`
and `bcfishpass` do not. They are inert until a group is moved to `mad`. At
the landed values a `mad` group keeps less stream rearing than `cw` (held-out:
at least −33 % BT and −82 % GR, −4 % RB). Read `research/habitat_thresholds.md`
before moving one. link also skips the stream-order rearing bypass
(`frs_order_child`) for a `mad` group — bcfp applies it in its cw branch only.
fresh does not implement bcfp's `stream_order >= 8` spawning bypass.
- **Discharge coverage is uneven.** A segment with NULL `mad_m3s` fails every mad
Expand Down
28 changes: 27 additions & 1 deletion data-raw/habitat_score/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# habitat_score

The inputs for scoring habitat-threshold variants against fish observations (#284 step 5).
The inputs for scoring habitat-threshold variants against fish observations (#284 step 5,
and the MAD ranges of #302).
The rule and the reasoning behind it are in `research/habitat_thresholds.md`, under
"Scoring design". Two scripts use these files:

Expand All @@ -24,6 +25,31 @@ row changes exactly one cell of `default`'s `parameters_habitat_thresholds.csv`.
| `obs_stage` | which observations count in the band: `any`, `spawn` or `rear` (the stage the threshold was calibrated on) |
| `step_from` | the neighbour nearer `default` in the ladder; the band is the difference between the two |
| `equals_bundle` | a shipped bundle whose thresholds this variant must equal byte for byte (checked at build) |
| `model` | optional (#302): `cw` (empty) or `mad`. A `mad` variant's bundle also carries a `parameters_habitat_method.csv` with every WSG holding a role for its species on `mad` |
| `set` | optional (#302): further cells the variant fixes, `col=value;col=value`, held constant along a ladder (a MAD rung's open maximum; the spawning range a clustered rearing ladder needs) |

### MAD ladders (#302)

A species with no MAD range has no "current value" to walk out from: under `mad` it has no
stream habitat at all. So a MAD ladder starts with an **anchor**, a rung that steps from the
`cw` base straight to `mad` at the tightest candidate. The score marks it
`take (anchor: model change)`, reports its bands both ways (what `mad` keeps that `cw` drops,
and the reverse) and decides nothing with them. The walk then scores the loosening rungs
beyond it as #284 did. The core is the habitat every ranged rung keeps: the `cw` base is
left out of it, because it tests a width floor (and fails NULL widths) that no `mad` rung
tests, so a core cut by it would differ from the bands on an axis no step is about.

A `mad` variant's `set` may name only `*_mad_min` / `*_mad_max` cells, so the rungs carry
`default`'s gradient cutoffs and every band differs from its neighbour in discharge alone. (`default_tuned`'s BT
`rear_gradient_max` 0.1349 was scored on its own, in #284.) The score checks that every
`set` cell holds its value, that a ladder holds `set` fixed past its anchor, that each step
reads the same species, column, flag and stage as its `step_from`, and that each bundle's
method table puts its WSGs on the variant's `model`.

A second scoring run gets its own `--prefix`; its working networks are then
`working_<prefix><wsg>` (#284's, under `score284_`, stay `working_score_<wsg>`).

The inputs for #302 are `variants_302.csv` and `wsg_roles_302.csv`.

## `wsg_roles.csv`

Expand Down
20 changes: 20 additions & 0 deletions data-raw/habitat_score/variants_302.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
variant,species_code,column,value,flag,obs_stage,step_from,equals_bundle,model,set
default,,,,,,,default,cw,
bt_rear_mad_p10,BT,rear_mad_min,0.078,rearing,any,default,,mad,rear_mad_max=9999;spawn_mad_min=0.027;spawn_mad_max=9999
bt_rear_mad_p05,BT,rear_mad_min,0.027,rearing,any,bt_rear_mad_p10,,mad,rear_mad_max=9999;spawn_mad_min=0.027;spawn_mad_max=9999
bt_rear_mad_p02,BT,rear_mad_min,0.0085,rearing,any,bt_rear_mad_p05,,mad,rear_mad_max=9999;spawn_mad_min=0.027;spawn_mad_max=9999
bt_spawn_mad_p10,BT,spawn_mad_min,0.078,spawning,any,default,,mad,spawn_mad_max=9999;rear_mad_min=0.027;rear_mad_max=9999
bt_spawn_mad_p05,BT,spawn_mad_min,0.027,spawning,any,bt_spawn_mad_p10,,mad,spawn_mad_max=9999;rear_mad_min=0.027;rear_mad_max=9999
bt_spawn_mad_p02,BT,spawn_mad_min,0.0085,spawning,any,bt_spawn_mad_p05,,mad,spawn_mad_max=9999;rear_mad_min=0.027;rear_mad_max=9999
gr_rear_mad_p10,GR,rear_mad_min,0.97,rearing,any,default,,mad,rear_mad_max=9999;spawn_mad_min=0.095;spawn_mad_max=9999
gr_rear_mad_p05,GR,rear_mad_min,0.095,rearing,any,gr_rear_mad_p10,,mad,rear_mad_max=9999;spawn_mad_min=0.095;spawn_mad_max=9999
gr_rear_mad_p02,GR,rear_mad_min,0.0026,rearing,any,gr_rear_mad_p05,,mad,rear_mad_max=9999;spawn_mad_min=0.095;spawn_mad_max=9999
gr_spawn_mad_p10,GR,spawn_mad_min,0.96,spawning,any,default,,mad,spawn_mad_max=9999;rear_mad_min=0.095;rear_mad_max=9999
gr_spawn_mad_p05,GR,spawn_mad_min,0.095,spawning,any,gr_spawn_mad_p10,,mad,spawn_mad_max=9999;rear_mad_min=0.095;rear_mad_max=9999
gr_spawn_mad_p02,GR,spawn_mad_min,0.0025,spawning,any,gr_spawn_mad_p05,,mad,spawn_mad_max=9999;rear_mad_min=0.095;rear_mad_max=9999
rb_rear_mad_p10,RB,rear_mad_min,0.019,rearing,any,default,,mad,rear_mad_max=9999;spawn_mad_min=0.011;spawn_mad_max=9999
rb_rear_mad_p05,RB,rear_mad_min,0.0094,rearing,any,rb_rear_mad_p10,,mad,rear_mad_max=9999;spawn_mad_min=0.011;spawn_mad_max=9999
rb_rear_mad_p02,RB,rear_mad_min,0.0048,rearing,any,rb_rear_mad_p05,,mad,rear_mad_max=9999;spawn_mad_min=0.011;spawn_mad_max=9999
rb_spawn_mad_p10,RB,spawn_mad_min,0.05,spawning,spawn,default,,mad,spawn_mad_max=9999;rear_mad_min=0.0094;rear_mad_max=9999
rb_spawn_mad_p05,RB,spawn_mad_min,0.011,spawning,spawn,rb_spawn_mad_p10,,mad,spawn_mad_max=9999;rear_mad_min=0.0094;rear_mad_max=9999
rb_spawn_mad_p02,RB,spawn_mad_min,0.0055,spawning,spawn,rb_spawn_mad_p05,,mad,spawn_mad_max=9999;rear_mad_min=0.0094;rear_mad_max=9999
22 changes: 22 additions & 0 deletions data-raw/habitat_score/wsg_roles_302.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
watershed_group_code,species_code,role
REVL,BT,held_out
ELKR,BT,held_out
KOTR,BT,held_out
UARL,BT,held_out
MURR,BT,held_out
UBTN,BT,held_out
LHAF,BT,held_out
PARS,BT,in_sample
KOTL,BT,in_sample
UBTN,GR,held_out
MURR,GR,held_out
LHAF,GR,held_out
PARS,GR,in_sample
SIML,RB,held_out
OKAN,RB,held_out
KETL,RB,held_out
ELKR,RB,held_out
REVL,RB,held_out
KOTR,RB,held_out
PARS,RB,in_sample
KOTL,RB,in_sample
Loading
Loading