Add Canadian provinces and territories to the jurisdiction data - #1
Open
JonathanNus wants to merge 3 commits into
Open
Add Canadian provinces and territories to the jurisdiction data#1JonathanNus wants to merge 3 commits into
JonathanNus wants to merge 3 commits into
Conversation
JonathanNus
force-pushed
the
canada-jurisdictions
branch
from
August 16, 2026 03:50
814a0c0 to
193cc97
Compare
Bones ships US-only jurisdictions, so a Canadian project either falls back to INTL generics or, worse, picks a US state whose frost line is too shallow. Prairie frost penetration runs 1800-2400mm (71-94in) — deeper than any US state in the data — so footings were being under-dug by a foot or more with no warning. Adds 16 entries covering all 10 provinces, the 3 territories, and a generic NBC 2020 fallback. Ontario is split three ways because its frost line runs 1200mm in the GTA to 2100mm at Thunder Bay, which is a bigger spread than most US states carry in a single row. Data only — no engine changes. Canada is not an IRC jurisdiction, so every row sets `ircBase: null` and cites NBC Division B Part 9 (the analogue of the IRC for housing and small buildings), the way the Wisconsin UDC row already does for its non-IRC state code. Codes use ISO-3166-2 style (CA-ON-S, CA-BC…) for two reasons: bare `CA` is already California, and `jurisdictionOptions()` sorts by code, so the `CA-` prefix groups the Canadian entries together in the dropdown without touching the sort. Also maps the Canadian IANA timezones in guess.ts, and sends an `en-CA` locale to CA-GEN rather than INTL. Note tzdata folds Montreal into America/Toronto, so Quebec guesses as southern Ontario — the dropdown still wins, as it does for every guess. Conversions are documented per row: Canadian codes state ground snow as Ss in kPa and frost depth in mm, converted here to the psf/inch fields this schema uses (1 kPa = 20.885 psf).
JonathanNus
force-pushed
the
canada-jurisdictions
branch
from
August 16, 2026 03:52
193cc97 to
6861d07
Compare
…ss engine
Two changes a host needs:
1. The wall-mode takeover ('down' while X-raying) moves from the 3D
renderer to the panel. The renderer lives as long as the bones:framing
node does, so leaving the Bones tab kept the host's walls hidden — and
because wallMode is a persisted viewer preference, the stuck view
survived reloads, and merely OPENING a scene that contained an X-ray
node blanked the walls. The panel unmounts exactly when the user
leaves, which is the lifetime this intent actually has. The state
machine lives in view-takeover.ts (viewer-import-free, unit tested:
restore on leave, never stomp a user-picked mode, no ownership when
walls were already down). Also aligns with the plugin appearance
contract (#625): the renderer no longer writes host presentation state.
2. index.ts exports the pure derivation surface — computeLevel,
computeLevelUncached, computeTakeoff, cutList, the row/member types,
extractLevels/extractRoofs — so a host estimator can compute the same
quantities the panel shows without mounting anything.
computeLevelUncached is exported because a whole-building rollup loop
would otherwise thrash the 1-deep memo the panel and renderer share.
White-label commit for the PreSell deployment — intentionally NOT sent upstream (their product name is theirs). Panel heading and badge become "Structural Framing" / "Beta", and the 'Pascal project' fallbacks on the printed plan set become 'Project'. Keep this as the TOP commit when rebasing onto upstream bumps.
Snoopy147
added a commit
that referenced
this pull request
Aug 18, 2026
F1 (M2+S1 regression): unit #1's PAD inherited the cabinet's oblique equip-bearing rotation after an RO slide — a 45° square pad reaches (|sin|+|cos|)·half toward the wall and punched through the assembly (TX wythe, FL CMU). Pads now always pour parallel to the row wall; only the cabinet keeps the legacy facing. Gate: slid-anchor scenario, yaw multiple of 90° + clearance. F2 (E5+S8): a device override committed against a DROPPED colinear twin silently re-targeted the derived wall with the twin's wallT. applyDeviceOverrides now resolves through duplicateOf and re-projects the twin-relative t onto the kept centerline; unknown/unframed walls warn instead of silently falling back. Gate: twin-committed override lands at the world spot the user dropped it. F3 (S1+S6+E5): 'device blocking' embedded inside per-wall batts — splitBattsAroundBlocking notches the batt (below+above pieces, the installer's cut). Gate: no insulation×blocking overlap end-to-end. Byte-equality pin re-captured (F1's pad rotation is the intended diff). 858 tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Snoopy147
added a commit
that referenced
this pull request
Aug 18, 2026
…nchor buildServicePointNodes seeded at raw placeHeatPumpSpot, which can front a window RO the engine's condenserRow had already slid unit #1 away from — the sign stood apart from its unit (narrow-round finding). placeCondenserSeedSpot runs the same slide; gate pins seed == cabinet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Snoopy147
added a commit
that referenced
this pull request
Aug 21, 2026
#1) Four loop rounds: the 0.4m stub replaced by a wall-following suction 3/4" (insulated, cold-blue) + liquid 3/8" (warm-red) pair — ONE shared route (pair-envelope detour decisions), uniform +/-2cm vertical offset, risers ROLL 90 degrees perpendicular to their own wall (triplet-index axis — geometric lookup was ambiguous at corners), corner-cancel kills phantom down-up risers at junctions; routePipe reused from plumbing (bandHalf param, byte-pure); paper: schematic +/-2.5px nudge so both colors print, MEP legend rows, takeoff suction/liquid/insulation lf + >15m oil-return advisory. Examiner PASS on pixels round 2; merge-gate attacks run inline (skeptic agents stalled on API errors) — all four corner scenes zero SAT hits, no duplicates. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> # Conflicts: # src/framing/master-baseline.json # src/plans/plan-set.test.ts
Snoopy147
added a commit
that referenced
this pull request
Aug 23, 2026
The fence+RO compound broke A4 seed parity: placeCondenserSeedSpot's
corner-flip guard still consulted nearestExteriorExit(slid) — the exact
wrong-oracle the row fix retired. A garden fence 0.4 m from the slid pad
always beats the elected wall (0.6 m by construction), so the guard bailed
to the RAW anchor; the seeded node fed back as a verbatim override and the
post-seed compose drew the unit dead-center on the window the engine had
slid past, disconnect re-hosted to the fence, zero warnings. Every
activated scene seeds automatically — the wrong recompose was the DEFAULT
lifecycle.
(a) the guard now tests the slid spot's along-wall projection against the
ELECTED wall's span (condenserRow already anchors there); off-wall
slides keep the raw anchor (bail arm pinned);
(b) DECISION — machine-seeded override coherence: layoutHvac always runs
the election; an override within ε (1e-9, float round-trip tolerance,
not a snap radius) of the election spot or the engine's own slid
unit-#1 spot is the machine's point and keeps the ELECTED row wall —
post-seed compose == auto compose, byte-equal. Anything farther is a
real user drag and stays verbatim-nearest (A4: never silently
re-anchored). Chosen over board-noting the class because auto-seeding
makes the recompose path the default, not an edge.
Gates: fence+RO compound (engine unit #1 == seed; post-seed byte-equal;
disconnect stays w_south), fence-only (no flip w_south→w_fence + user-drag
arm stays verbatim-nearest), off-wall bail arm. Mutants bite both ways:
guard old-oracle, guard removed, ε-anchor removed, ε blown open (4/4).
Byte gates re-held: 16 hunt shapes, exhibit override path, E5 recapture
byte-identical. Suite 1621 + 1 todo, tsc clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gorkking
pushed a commit
to gorkking/Pascal-Editor-plugin-bones
that referenced
this pull request
Aug 23, 2026
… threading Anonymized minimal repro of the exhibit (misclassified interior walls + covered zoneless void): the walk skips the Bathroom spot AND the covered mid-plan void, lands 0.6 m outside the true south wall — outside every zone + outside coverage, unflagged, silent, disconnect present, line-set continuity to the AH on wall rails (E2). Pins: - coverage probe is load-bearing (blind walk validates the void at 5,1.9); - verbatim override still wins + warns (fast-follow unchanged); - seed parity: placeCondenserSeedSpot(coverage) == engine unit pascalorg#1; - walk exhaustion → least-bad spot kept + ⚠ flag + warning, distinct from the legacy no-exterior-wall class; - courtyard DECISION: outdoor zone legitimizes over a patio slab; no zone → covered court reads inside, walk continues; slab hole = court; - row anchors to the ELECTED wall (garden-fence divergence); - computeLevel threads probeSlabs (F3, mep-honesty) and the seed action threads them too (place.test). All 9 mutation probes bite (walk removal, coverage drop, outdoor-blocker, null-on-exhaustion, warning/flag drops, compute/place thread drops, elected-wall ignore). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Snoopy147
added a commit
that referenced
this pull request
Aug 23, 2026
…d gesture) Julien 2026-08-23 overrules the day-10 sign-as-only-handle trade: in xray with hvac ON the heat-pump service node mounts a near-invisible pick proxy (bones:device convention — opacity ~0, no depth write; the host outline mask pass re-renders silhouettes with its own material) sized to the engine cabinet ×1.04 at the unit center height and unit-#1 yaw (memoized computeLevel, zero extra derivation). Unit #1 is verbatim at the node (A4) so the proxy rides the node group — live drags track, engines re-route on commit via the proven sign-drag flow. Sign plates keep picking; visible bodies stay the handle (no proxy off/basement/toggle-off/no-framing); engine silence mounts nothing (no phantom hover volume); WH/meter stay proxy-less (stated follow-up candidates). The one stated exception to the X-ray raycast-no-op convention — a SERVICE mesh, documented at the mount; framing/asset meshes stay raycast-disabled (A6). - placement.ts: ServicePresentation.pickProxy column (suppression matrix) - service/proxy.ts: pure resolver + doctrine; renderer mounts the mesh - gates: place.test.ts matrix updated as INTENDED; proxy.test.ts footprint/height/yaw/A4 parity + silence + composition arms - CHECKLIST: A6 unwarp clause, new A7 row; HP-UNWARP expected-diff manifest Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bones ships US-only jurisdictions, so a Canadian project either falls back to the
INTLgenerics or, worse, gets pointed at a US state whose frost line is too shallow. The concrete failure: prairie frost penetration runs 1800–2400 mm (71–94 in), deeper than any US state in the data (max 60 in), so footings come out a foot or more short with nothing in the UI to say so.This adds 16 entries — all 10 provinces, the 3 territories, and a generic NBC 2020 fallback.
Data only
No engine changes. Everything rides the existing path: two JSON rows merged by
profileFor(), then the same five levers inapplyJurisdiction().Notes on the choices
Codes are ISO-3166-2 style (
CA-ON-S,CA-BC, …) for two reasons. BareCAis already California, so a "Canada" code there would be a genuine footgun. AndjurisdictionOptions()sorts by code, so theCA-prefix groups the Canadian entries together in the dropdown without touching the sort.Ontario is split three ways (South / East / North). Its frost line runs 1200 mm in the GTA, 1800 mm in the Ottawa Valley and 2100 mm at Thunder Bay — a wider spread than most US states carry in one row, and the Ottawa Valley is also Canada's second-highest seismic zone. One row could not represent it honestly. The other provinces are single rows.
Canada is not an IRC jurisdiction. Every row sets
ircBase: nulland cites NBC Division B Part 9 ("Housing and Small Buildings"), the analogue of the IRC — the same shape the Wisconsin UDC row already uses for its non-IRC state code. Thenotefield warns inference engines not to assume IRC section numbers or IRC braced-wall-panel methods, since NBC 9.23.13 selects lateral bracing from Sa(0.2) and hourly wind pressure instead.Unit conversions are documented per row. Canadian codes state ground snow as Ss in kPa and frost depth in mm; converted here to the psf/inch fields this schema uses, at 1 kPa = 20.885 psf.
Timezones:
guess.tsgains the Canadian IANA zones, and anen-CAlocale now resolves toCA-GENrather thanINTL. One caveat noted in the code: modern tzdata folds Montreal intoAmerica/Toronto, so Quebec guesses as southern Ontario. The dropdown still wins, as with every guess.Territories carry an explicit permafrost warning in
frostLineNote(so it surfaces in the panel's notes, not just the data file) — a spread-footing depth is not a meaningful output where pile or space-frame foundations are the norm.Sources
Values are typical provincial figures, not site-specific: each row carries a
caveatsaying so, matching the existing disclaimer style. Quebec is flagged as still on the NBC 2015 base.Tests
src/jurisdiction/canada.test.tsadds 10 tests. They pin the things that would regress silently — a missing data row degrades to the INTL fallback rather than throwing, so "it still renders" is not evidence a province landed. Also assertsprofileFor('CA').name === 'California'so the collision stays fixed.Full suite: 444 pass, 0 fail.
tsc --noEmitclean.One thing I found but did not fix
insulationByClimateZoneis keyed"1"–"8", butwall-layers.tslooks it up with the rawstateClimateZonevalue, which reads like"5A (4A NYC/LI, 6A Adk)". Zero of the 51 existing US entries resolve, so the R-value label never renders for anyone. I left it alone — it is orthogonal to this PR and fixing it would change output for every US state. Happy to send a separate PR if useful.