Problem
lnk_pipeline_crossings v0.32.0 carries the PSCIS<->modelled crossing linkage only from the xref CSV (pscis_modelledcrossings_streams_xref). It's missing bcfp's automatic 100m-instream snap layer that produces the bulk of PSCIS<->modelled linkages.
See research/bcfp_table_map.md for the full mechanism analysis. Short version: bcfp's 02_pscis_streams_150m.sql (at smnorris/bcfishpass@v0.7.14-125-g6e9cf1c, current tunnel state bcfishpass.log.model_run_id=121 rebuilt 2026-05-05) auto-matches each PSCIS to its nearest modelled crossing within 100m instream distance on the same stream. The xref CSV layers manual overrides on top. link skips the auto-snap entirely.
Evidence (Phase A bcfp parity, 2026-05-10)
| WSG |
extra <schema>.barriers_anthropogenic vs tunnel |
mapping_code parity (worst species) |
| ADMS |
+89 |
bt 98.53% (211 diffs) |
| BULK |
+1391 |
bt 76.30% (9357 diffs) |
| WILL |
+N (unmeasured) |
bt 85.48% (2490 diffs) |
| PARS |
cross-WSG dnstr (#152) |
bt 56.16% (16445 diffs) |
The +1391 in BULK is the largest single contributor to BULK's mapping_code drift. Closing this gap is expected to bring all WSGs' mapping_code parity into >=99% (modulo cross-WSG dnstr, handled by #152).
Dependencies
Blocked by fresh#206 -- the generic frs_point_match primitive (point-to-point match on FWA network within instream distance). Once that ships, this issue is a thin integration.
Proposed solution
Once fresh ships frs_point_match:
- Add
<schema>.pscis build step in lnk_pipeline_crossings, mirroring bcfp's bcfishpass.pscis:
- Source:
<schema>.pscis_assessment_snapped (already produced by lnk_points_snap)
- Call
fresh::frs_point_match with table_a = <schema>.pscis_assessment_snapped, table_b = fresh.modelled_stream_crossings, table_to = <schema>.pscis, distance_max = 100, table_a_id_col = "stream_crossing_id", table_b_id_col = "modelled_crossing_id"
- Result: PSCIS rows with
modelled_crossing_id populated where auto-snap found a match
- Apply xref-CSV overrides on top (xref overrides auto-snap matches)
.lnk_crossings_union reads from <schema>.pscis for the PSCIS branch (instead of <schema>.pscis_assessment_snapped).
- The modelled-branch exclusion changes: drop the xref-based
WHERE NOT IN (xref) and replace with WHERE NOT IN (SELECT modelled_crossing_id FROM <schema>.pscis WHERE modelled_crossing_id IS NOT NULL) -- picks up both auto-snap and xref-derived linkages from the same source.
Acceptance
Out of scope
Problem
lnk_pipeline_crossingsv0.32.0 carries the PSCIS<->modelled crossing linkage only from the xref CSV (pscis_modelledcrossings_streams_xref). It's missing bcfp's automatic 100m-instream snap layer that produces the bulk of PSCIS<->modelled linkages.See
research/bcfp_table_map.mdfor the full mechanism analysis. Short version: bcfp's02_pscis_streams_150m.sql(atsmnorris/bcfishpass@v0.7.14-125-g6e9cf1c, current tunnel statebcfishpass.log.model_run_id=121rebuilt 2026-05-05) auto-matches each PSCIS to its nearest modelled crossing within 100m instream distance on the same stream. The xref CSV layers manual overrides on top. link skips the auto-snap entirely.Evidence (Phase A bcfp parity, 2026-05-10)
<schema>.barriers_anthropogenicvs tunnelThe +1391 in BULK is the largest single contributor to BULK's mapping_code drift. Closing this gap is expected to bring all WSGs' mapping_code parity into >=99% (modulo cross-WSG dnstr, handled by #152).
Dependencies
Blocked by fresh#206 -- the generic
frs_point_matchprimitive (point-to-point match on FWA network within instream distance). Once that ships, this issue is a thin integration.Proposed solution
Once fresh ships
frs_point_match:<schema>.pscisbuild step inlnk_pipeline_crossings, mirroring bcfp'sbcfishpass.pscis:<schema>.pscis_assessment_snapped(already produced bylnk_points_snap)fresh::frs_point_matchwithtable_a = <schema>.pscis_assessment_snapped,table_b = fresh.modelled_stream_crossings,table_to = <schema>.pscis,distance_max = 100,table_a_id_col = "stream_crossing_id",table_b_id_col = "modelled_crossing_id"modelled_crossing_idpopulated where auto-snap found a match.lnk_crossings_unionreads from<schema>.pscisfor the PSCIS branch (instead of<schema>.pscis_assessment_snapped).WHERE NOT IN (xref)and replace withWHERE NOT IN (SELECT modelled_crossing_id FROM <schema>.pscis WHERE modelled_crossing_id IS NOT NULL)-- picks up both auto-snap and xref-derived linkages from the same source.Acceptance
<schema>.pscis.modelled_crossing_idpopulated where bcfp'sbcfishpass.pscis.modelled_crossing_idis, for ADMS / BULK / WILL / PARS (within tolerance)<schema>.crossingsmodelled-source row count matchesbcfishpass.crossingsfor ADMS / BULK / WILL / PARS (within tolerance)compare_bcfp_mapping_code.R --wsgs=ADMS,BULK,WILL,PARSmapping_code parity >=99% for all species except PARS BT (cross-WSG, separately handled by Unified <persist_schema>.barriers (province-wide) with blocks_species predicate #152)Out of scope
dam_dnstr_ind-- Unified <persist_schema>.barriers (province-wide) with blocks_species predicate #152lnk_pipeline_species/lnk_presencealignment -- lnk_pipeline_species vs lnk_presence: align presence definitions for mapping_code parity #153pscis_assessment_svw-- bcfp uses all 4) -- separate question