Skip to content

Score each watershed group on its own habitat model in lnk_habitat_validate() (#299) - #301

Merged
NewGraphEnvironment merged 7 commits into
mainfrom
299-lnk-habitat-validate-scores-mad-watersh
Oct 2, 2026
Merged

NewGraphEnvironment merged 7 commits into
mainfrom
299-lnk-habitat-validate-scores-mad-watersh

Conversation

@NewGraphEnvironment

@NewGraphEnvironment NewGraphEnvironment commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • lnk_habitat_validate() re-tests each observation's segment on the habitat model its watershed group classified on (cw or mad), from the method table in the cfg it is given. The model is resolved by fresh's own .frs_habitat_models(), which lnk_pipeline_classify() now shares.
  • On a mad group, the predicates come from frs_habitat_predicates(model = "mad"), size relaxation moves mad_m3s (joined from fwa_stream_networks_discharge on linear_feature_id, since the persist does not carry it), and width_null tests discharge. Reason labels are shared across models; observations gains model and mad_m3s, summary gains model.
  • New reason no_mad_threshold: a mad miss that a MAD range alone would admit, for the species that have none (BT, GR, KO, RB). A miss whose gradient also fails reads fails_gradient_and_width; one with no discharge on its line reads width_null, as on cw.
  • Preflight now also asserts frs_habitat_predicates(model) and .frs_habitat_models. The miss-binning driver carries model.

Related Issues

Test plan

  • Full suite: 2,394 tests, 0 failed, 0 skipped (16 warnings, the existing baseline)
  • R CMD check: 0 errors. The 3 warnings and 2 notes are pre-existing (non-ASCII in other files, Rd cross-refs, setNames/getFromNamespace globals) and touch no line this branch adds
  • cw unchanged: ADMS on fresh_default, branch vs main, observations identical apart from the new columns and summary identical apart from model (94 locations)
  • mad live: ADMS modelled on mad into a scratch schema, then validated with branch and with main. Main calls 27 BT rearing misses post_predicate, the branch no_mad_threshold. See data-raw/logs/habitat_validate_299/README.md

Notes

  • Review: one plan review and four code-check rounds (five agents). Two defects sat inside the no_mad_threshold fixes: it relaxed gradient too, and it ignored a NULL discharge. Round 3 named the mechanism, a hand-copied relaxation ladder, and the loop ended on two enumerations rather than a quiet round. The first covered every miss arm × model × NULL pattern, evaluated in Postgres. The second was a test of the missing-range rule against fresh, case by case.
  • The planned acceptance metric did not discriminate. "Persisted TRUE, predicate FALSE" is 0 on main as well. A wrong model shows up as post_predicate, which is now recorded in CLAUDE.md.
  • Known limit: a run classified with a different method table (or lnk_pipeline_classify(method_csv =)) is not detected; swap the table on the cfg passed to the validator.
  • Follow-up: Tune MAD (discharge) thresholds for BT, GR, KO and RB rather than leave them missing #302 tunes and adds MAD thresholds for BT, GR, KO and RB.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WJE2szSCkeV9R3qKhuSwyx

NewGraphEnvironment and others added 7 commits October 2, 2026 00:52
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJE2szSCkeV9R3qKhuSwyx
.lnk_habitat_method_read() and .lnk_wsg_model() sit beside
.lnk_habitat_method_csv(); classify now uses them, and the validator will
in the next commit, so the two cannot resolve a group differently. The
resolver is fresh's .frs_habitat_models(), registered as a required
internal in the preflight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJE2szSCkeV9R3qKhuSwyx
lnk_habitat_validate() rebuilt every predicate on the channel-width
model, so on a group a bundle puts on mad the miss reasons tested a size
the classification never used. It now resolves each scored group's model
from cfg's method table (fresh's own rule, shared with classify), builds
the predicates with frs_habitat_predicates(model =), relaxes the model's
size column, and tests width_null on mad_m3s for mad groups. mad_m3s is
joined from fwa_stream_networks_discharge on linear_feature_id, since the
persist does not carry it.

Reason labels are unchanged (width means the group's size dimension);
observations gain model and mad_m3s, summary gains model. New reason
no_mad_threshold: a mad miss that a MAD range alone would admit, for the
species that have none (BT, GR, KO, RB). cw output is identical apart from
the new columns (ADMS on fresh_default, branch vs main).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJE2szSCkeV9R3qKhuSwyx
Roxygen, RUNBOOK §7, research/habitat_validation.md and CLAUDE.md now say
how a mad group is scored and what the shared reason labels mean there.
data-raw/habitat_validate.R carries model into misses.csv and bins a mad
row's size under "mad", so misses_binned.csv still sums to misses.csv.
A follow-up issue for adding MAD thresholds to BT, GR, KO and RB is
drafted in planning/active/, not filed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJE2szSCkeV9R3qKhuSwyx
cw: validator output on fresh_default identical to main apart from the
new columns. mad: ADMS modelled into a scratch schema with the method
table swapped; main labels 27 BT rearing misses post_predicate (the cw
predicate it rebuilds is looser than the one that classified the run),
the branch labels them no_mad_threshold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJE2szSCkeV9R3qKhuSwyx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJE2szSCkeV9R3qKhuSwyx
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJE2szSCkeV9R3qKhuSwyx
@NewGraphEnvironment
NewGraphEnvironment merged commit 211c18d into main Oct 2, 2026
1 check passed
@NewGraphEnvironment
NewGraphEnvironment deleted the 299-lnk-habitat-validate-scores-mad-watersh branch October 2, 2026 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lnk_habitat_validate() scores mad watershed groups as if they were cw

1 participant