Skip to content

fix(disc_walker): §TE-ARC-DATUM — walk-time measured z-datum reconciliation#40

Merged
red1oon merged 1 commit into
masterfrom
fix/te-arc-datum
Jul 10, 2026
Merged

fix(disc_walker): §TE-ARC-DATUM — walk-time measured z-datum reconciliation#40
red1oon merged 1 commit into
masterfrom
fix/te-arc-datum

Conversation

@red1oon

@red1oon red1oon commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Verified independently from a fresh detached worktree (MANAGER review): all 7 claims confirmed exact — pure-translation root cause (dz=14.66, dx=545.6, dy=51.2, 35552/35552 GUIDs), rule_frame_ref mining + walk-time zOff, mining-copy unchanged (744/888), T8 shipped-substrate proof (ELEC 860/638+36/19, PLB 869/739+100/111, 0 violations), falsifier 1865→642, no regressions, clean merge. See prompts/Modeller/DISC_Walker/RESUME_DISC_WALKER_ENVELOPE_BOUND.md §TE-ARC-DATUM for full context. Named follow-up not in this PR: port §DW-DATUM to bim-ootb's modeller/disc_walker.js + re-stamp its shipped terminal_rules.db.

…iation (rule_frame_ref) + T8 shipped-substrate witness

The baked rules_meta.z_datum_offset (14.593) targets ONE frame — the mining
extraction's site frame. The shipped Modeller Terminal_ARC.db sits in the
raw-IFC building frame (pure translation, extraction = ARC + 14.66 m in z,
measured per-GUID over all 35,552 elements), so every mined z-band starved
there and all disciplines collapsed (ELEC 744→390, PLB 888→252).

Fix per RESUME_DISC_WALKER_ENVELOPE_BOUND.md §TE-ARC-DATUM-FIX (option b,
refined): project_rule_mesh_binding.py also stamps rule_frame_ref (per-class
mean-z refs in the band frame, non-generatable classes only, n>=5);
placeMeasured() measures zOff at walk time as the median per-class delta vs
the walked substrate (>=3 shared classes, else legacy fallback, both §-logged).
Same-frame walks reproduce the legacy constant exactly (MAD=0.000, T1-T7
placed counts unchanged); the shipped file reconciles at zOff=-0.060.

W-TERM-NOSPACES grows T8: walks the SHIPPED ~/bim-ootb/modeller/Terminal_ARC.db,
grades ELEC+PLB vs n_measured in [0.5,2.0] + envelope/z-band/hash conformance;
falsifier DROP rule_frame_ref collapses 1865→642 (= the pre-fix probe numbers).
8/8 PASS. Follow-up (named, separate): port to diverged bim-ootb walker copy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@red1oon red1oon merged commit b202eb4 into master Jul 10, 2026
1 check failed
red1oon added a commit that referenced this pull request Jul 10, 2026
…m-ootb port

Records the merge (b202eb4) and hands off the one remaining task: port
rule_frame_ref mining + walk-time zOff to bim-ootb's own disc_walker.js and
terminal_rules.db — the fix is bim-compiler-only, the actual Modeller app still
has the collapse bug live until this ports over.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
red1oon added a commit that referenced this pull request Jul 11, 2026
)

* docs: correct guide-screenshot verdict — reattempt succeeded

* docs: add prompts/MANAGER.md — cross-session review/admin role

* docs(disc_walker): ROOM_INJECTION_HYBRID hardened for Fable handoff — Modeller-only scope

Renumber WalkerDoctrine.md's duplicate §13 to §14 (rooms rule) and fix the citation.
Drop the dead SAMPLECASTLE_REAL_ROOMS_RECONCILE.md anchor (lives only on an unmerged
branch, not this one). Reframe the Viewer Find Panel Room Lens reference as a one-way,
read-only borrow-from source for the Modeller's ARC-import step, name its unfiltered
query as a live false positive, and explicitly scope Task 5 to Modeller-only — no
Viewer files touched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): anchor THE GOAL to VISION-LOCK — "working" was undefined

MANAGER.md said "get the actual thing working" without citing what working means,
letting review verdicts drift toward generic pass/fail instead of the actual product
bar. Point at RESUME_GRAPH_MODELLER_INTEGRATION.md §VISION-LOCK's five sentences.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): correct §2 — Terminal's 43 rooms are synthetic, not real

Direct query (object_type=COMPILED, ≈-named) proves Terminal has zero real IfcSpace
rooms — the doc previously miscounted them as "real rooms already baked in." Same
correction applied to HHS's 14 rows (already caught by Task 5 but §2's table hadn't
been updated to match). Adds the full 8-building room-count table: only Duplex has
real, habitability-filtered data, and it isn't merged to main yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §2 — source-IFC check finds SampleHouse extraction bug

Direct grep of internal/sources/Ifc4_SampleHouse.ifc finds 4 real IFCSPACE entities
(Living room, Bedroom, Entrance hall, Roof) that never made it into the shipped
SampleHouse_ARC.db (0 rooms) — an extraction gap, not a source-data gap as previously
assumed. Clinic/Garage/Hospital/HHS have no source IFC in this checkout to check
either way, so their "0 rooms" state is unverified, not confirmed-no-data.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add Task 6 (SampleHouse extraction bug), reassign forward work to Sonnet

Task 6: 3 usable real rooms exist in SampleHouse's source IFC but never reached the
shipped ARC — an extraction bug, not a data gap. Per user directive, all further work
on this doc goes to Sonnet, not Fable, from here on; Tasks 1+5's Fable history is left
as an accurate record, not rewritten.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(compile_rooms): §DOOR-RESCUE — recover real small rooms (toilets/utility) below MIN_AREA

User-flagged, verified before fixing: HHS ("large U-shape office block, lots of office rooms
with doors") only compiled 2 rooms; restrooms/utility rooms were being missed across every
building, not just HHS. Instrumented the flood-fill to log ALL candidate pockets (not just
accepted ones) — confirmed this was NOT a mis-tuned MIN_AREA=4.0 threshold hiding rooms that
were actually detected: most sub-threshold pockets are <1.0 m^2 wall-joint/cavity artefacts
(noise), but a real population of 1.0-4.0 m^2 pockets IS a genuine small room (restroom/closet/
riser) wrongly dropped by the same blanket cutoff.

The user's hint ("rooms has doors" / "look for clues that define a toilet, utility that house
MEP") pointed at the fix: MEP fixture data isn't reliable (ARC-only discipline strip already
removed sanitary/plumbing elements from 4 of 5 buildings), but door adjacency is a real,
non-invented structural signal already in every ARC.db — a genuine small room a person uses
always has a door; a wall cavity never does. Measured before shipping: for HHS/Clinic/Hospital/
SampleCastle, pockets <1.0 m^2 are rarely door-adjacent (noise); pockets in [1.0, 4.0) m^2 are
door-adjacent in the large majority (real small rooms) — the two size bands are different
populations, not an arbitrary split.

- storey_doors() + _door_adjacent(): per-storey real IfcDoor centres, 1.0m buffer.
- flood_rooms(): a pocket in [DOOR_RESCUE_MIN_AREA=1.0, MIN_AREA=4.0) m^2 is now accepted iff
  door-adjacent; still-tagged ≈/RM_/COMPILED (spacesOf()'s placement-exclusion untouched) but
  predefined_type='INTERNAL_SMALL' (vs 'INTERNAL') for traceability of which path found it.
- Re-ran --write on the 5 gap buildings: HHS 2→5, Clinic 113→190, Hospital 142→213,
  SampleCastle 25→47, Garage unchanged (0 door-adjacent small pockets found).
- W-ROOM-INJECT-ALL8 rerun 32/32 on bim-ootb worktree: placement-eligibility still 0 for every
  synthetic-only building — door-rescued rooms are exactly as display-only as any other
  compiled room, never reach schedule placement.

Doc: prompts/Modeller/DISC_Walker/ROOM_INJECTION_HYBRID.md updated with the finding + fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): DB Storage Policy — stop new .db commits, GitHub LFS bandwidth cap hit

GitHub flagged 10GB/month LFS bandwidth usage. 59+ .db files already LFS-tracked
(deploy/buildings/*, build/*.db) burn quota on every clone/fetch. Going forward:
schema/rules DBs regenerate via migration/*.sql or their mining scripts; extracted/
derived building DBs distribute via OCI (already the dev/live channel), not git.
Existing LFS-tracked files are left alone — this only stops new commits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(compile_rooms): replace fitted door-rescue band with an abstract rule

User pushback (correct): the previous §DOOR-RESCUE fix used DOOR_RESCUE_MIN_AREA=1.0 and a flat
1.0m buffer picked by eyeballing HHS/Clinic/Hospital's specific data — a fitted band, not a rule.
This generalizes it:

- The room definition is now architectural, not size-banded: an enclosed pocket is a room if it
  is big enough on its own (area >= MIN_AREA, unchanged) OR it has a real door AND isn't a bare
  rasterization sliver. No area number stands between "noise" and "small room" anymore.
- Door adjacency buffer is now each door's OWN extracted footprint (half its real leaf/frame
  span) + one grid cell of slack (RES) -- self-scaling to whatever doors a building actually has,
  not a fixed metre guess that happened to work on 5 sample buildings.
- The noise floor is NOISE_FLOOR_DIM = 3*RES (0.6m) -- a pocket narrower than a few grid cells in
  EITHER axis is rasterization noise by construction, a property of the flood-fill's own
  resolution, not an area threshold reverse-engineered from observed rooms.

Re-verified: HHS 6, Clinic 195, Hospital 201, SampleCastle 53, Garage 5 (close to, not identical
to, the earlier fitted-band numbers -- expected, since the rule is now geometry-derived rather
than tuned to match them). W-ROOM-INJECT-ALL8 rerun 32/32 on bim-ootb worktree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record both door-rescue passes — fitted band superseded by abstract rule

* fix(compile_rooms): §DOOR-NOT-ROOM — lift/elevator doors aren't room evidence

Tested SEAL=1 (narrower wall-dilation) to try to recover HHS's WC-stall spaces the user found
named in German ("WC Trennwand") — rejected: doesn't fix HHS (the WC block's OWN enclosing walls,
not just its internal stall partitions, are simply absent from this extraction, a resolution/
data-completeness issue SEAL can't touch) AND it fragments real rooms elsewhere into spurious
1-2 sq.m splinters in Hospital (142->253, mostly noise) and SampleCastle -- a regression, not an
improvement. Reverted to SEAL=2 (already-shipped, verified value unchanged).

Separately, user asked whether doors have standard dimensions we could use as a smell test.
Checked: real hinged doors cluster 0.7-1.1m (single leaf) / 1.2-2.7m (double leaf/wide entrance)
across all 5 buildings' door data -- consistent, no anomaly, EXCEPT SampleCastle: 28 IfcDoor rows
at 0.5m width, all named 'liftdeur' (Dutch: elevator door). Real, correctly-classified doors --
but they lead to a lift shaft, not a room, and 2 of them were rescuing actual elevator-shaft
fragments as fake compiled "rooms" (verified directly: room count with vs without lift doors as
the door-rescue signal differs). Same shape of problem as the existing §STAIR-EXCLUDE pattern --
excluded via a maintained, multi-language door-name keyword list (liftdeur/lift/elevator/aufzug/
fahrstuhl/hoist), not a width cutoff (a lift door's width isn't reliably distinct from a narrow
single-leaf door's).

SampleCastle 53->51 (the 2 lift-shaft fakes removed); HHS/Clinic/Hospital/Garage unchanged (no
lift doors in their door-rescue signal). W-ROOM-INJECT-ALL8 rerun 32/32.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record SEAL=1 rejection + lift-door exclusion passes, HHS WC gap flagged open

* feat(compile_rooms): §DOOR-PARTITION — every door leads to a room, even where walls can't

User's repeated, correct point: HHS has 43/39/34 real doors across 3 floors (verified directly,
German-named "Türelement... Drehflügel" = swing-door elements) -- "each door must be to a room."
Flood-fill (even with §DOOR-RESCUE) only ever found 4/2/0 rooms on those floors because HHS's
extraction is missing the walls that would divide the floor into individual offices at all (91%+
of each floor floods as one exterior-reachable blob) -- door-rescue only widens acceptance for
pockets flood-fill ALREADY finds enclosed; it can't help where nothing is enclosed to begin with.

New technique for where wall-enclosure structurally cannot work: partition the storey's free space
by NEAREST DOOR (multi-source BFS through real free cells, real walls still block) -- each door
claims whatever space no other door reaches first, exactly the "every door leads to a room"
principle stated directly, not an area/threshold proxy for it.

Gate (measured, not fitted per-building): use door-partition only where flood-fill's OWN result
(with door-rescue already applied) finds fewer rooms than DOOR_SHORTFALL_RATIO=0.15 of the
storey's real door count -- HHS's floors find 0-11% of their door count via flood-fill; every
other building's WORKING floors find 20-100%+ of theirs (Garage's sparsest working floor: 5/8=62%;
Hospital's sparsest: 1/5=20%) -- the ratio sits below every failing floor and above every working
one, verified directly so it never overrides an already-functioning result (Garage's 5-room floor
and Hospital's 1-room floor both correctly kept their flood-fill result unchanged).

Result: HHS 6->105 (36/31/29/9 per floor -- in the "tens per floor" range the user predicted from
door counts alone). Clinic/Hospital/Garage/SampleCastle counts unchanged except Clinic's near-empty
'Unknown' storey (0->2, same gate correctly firing there too). predefined_type='INTERNAL_DOORPART'
marks these rows for traceability; object_type='COMPILED' (what tag-purity/placement-exclusion
checks key on) unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record §DOOR-PARTITION pass — HHS 6→105 rooms

* docs(disc_walker): add VIEWER_FIND_PANEL_ROOM_ACCURACY.md — port habitability+door-partition results to Find Panel

* docs(disc_walker): §TE-ARC-DATUM merged (PR #40) — entry point for bim-ootb port

Records the merge (b202eb4) and hands off the one remaining task: port
rule_frame_ref mining + walk-time zOff to bim-ootb's own disc_walker.js and
terminal_rules.db — the fix is bim-compiler-only, the actual Modeller app still
has the collapse bug live until this ports over.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): Worktree Hygiene — the other LFS bandwidth drain

Committing DBs wasn't the only cost: 49 bim-ootb worktrees + a duplicate ~/Projects/bim-ootb
clone were each pulling fresh 100-250MB mesh.db/geo.db LFS blobs. Real end users never
touch git LFS at all (they hit the deployed static site) — 100% of the quota was dev-side
worktree churn. Removed the duplicate clone (confirmed clean, 100+ commits stale) and
pruned 25 safe (clean + fully-pushed) stale worktrees in bim-ootb. Protocol: check
`git worktree list` before creating a new one, one clone per repo, prune on sight.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): LFS QUOTA EXHAUSTED — hard block, all-local, no exceptions

GitHub confirmed 0 bandwidth budget remaining, not just approaching the cap. Escalates
the earlier reduce-usage guidance to a hard block: no pushing any commit that touches
LFS-tracked content, no fetching/checking-out branches whose LFS blobs aren't already
locally cached, until the user confirms the quota has reset. Applies to every Agent-tool
prompt that touches git, not just this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add COMPILE_ROOMS_TYPE_INFERENCE.md — room-function guessing where no IfcSpace ever named it

* fix(disc_walker): correct VIEWER_FIND_PANEL_ROOM_ACCURACY.md — right repo, right file, new findings

User caught it: the doc anchored on bim-compiler/deploy/dev/navigate_find.js, which turns out to
be a STALE, unmaintained fork (2859-line diff vs the live copy, no recent commits since this
repo's initial migration). The actual, actively-developed Viewer code is bim-ootb/viewer/
navigate_find.js (3640 lines, commits as recent as pill-drawer/HBA work) -- same repo as Modeller's
disc_walker.js, removing the cross-repo constraint the original doc assumed.

Checked the live code directly and found it's further along than assumed (storey grouping + a
Storey/Type toggle already exist) but also found a new, concrete bug: the Type toggle's
`object_type || predefined_type` fallback never reaches predefined_type for compiled rooms, since
object_type='COMPILED' is always truthy -- masks the INTERNAL/INTERNAL_SMALL/INTERNAL_DOORPART
distinction compile_rooms.py now writes.

Biggest correction: confirmed viewer/import_db_builder.js (the live "drop your own IFC" schema
builder) never creates a spatial_structure table at all -- a user's own imported building gets ZERO
room data today, real or synthetic. Scoped as its own Task 5, separate from the display-only fixes,
since fixing it means porting compile_rooms.py's algorithm from Python to JS (no Python runs in a
browser) -- not a quick win.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add ROOM_WALKER_JS_PORT.md — retire Python, compute-once via explicit trigger

User's call, this session: since real usage is 100% JS (no server, no Python runtime in the
browser — confirmed for the live IFC-import path), retire compile_rooms.py in favor of one JS
port usable both offline (Node CLI, replacing today's Python bake for the 8 shipped residents) and
in-browser (a new Modeller Outliner "Room Walker" action, parallel to the existing Disc Walker
convention). Explicitly NOT "recompute live on every open" -- user's own point that this costs
real time (HHS's grid alone is ~90k cells/floor) -- compute once, on demand or at import, persist,
same principle as today's offline bake just relocated to whichever moment actually needs it.

5 tasks specced: (1) verify how Disc Walker is actually triggered today before assuming a UI
pattern to copy -- unconfirmed this session; (2) port the algorithm verbatim to a shared JS module;
(3) Node CLI mode replacing compile_rooms.py, witnessed byte-for-byte against this session's Python
counts (SampleHouse 3/Duplex 20/Terminal 43/SampleCastle 51/HHS 105/Clinic 197/Garage 5/Hospital
201) before Python is touched; (4) the browser-mode Room Walker Outliner action; (5) retire
compile_rooms.py once Task 3's parity witness is 100% green.

Cross-referenced from ROOM_INJECTION_HYBRID.md's Task 3 (now has a concrete trigger mechanism
instead of an open-ended display spec) and VIEWER_FIND_PANEL_ROOM_ACCURACY.md's Task 5 (this doc
is its actual breakdown).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): LFS quota resets 2026-08-01; any push may hang regardless of content

User-confirmed reset date. Also sharpens the finding: a push touching zero LFS-tracked
files still hung 2+ min and never landed (fix/dw-datum-port push attempt) - the git-lfs
pre-push hook appears to probe the endpoint unconditionally. Rule is now "any push may
hang until reset," not just LFS-content pushes. Don't retry a hung push blindly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): anchor to the published ModellerGuide as the tangible external target

VISION-LOCK is the internal engineering bar; the guide site is the user-facing proof
it's met. Notes current known gaps (Terminal datum port stuck behind LFS block,
room-mode data coverage, x-ray bug, 2 live Viewer UI bugs) so a new session doesn't
have to re-derive "how far are we" from scratch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §DW-DATUM bim-ootb port DONE — pushed, PR #726 open

Verified and pushed successfully (earlier push attempt's 2-min hang was transient,
not a hard LFS block - retry succeeded in 25s). Terminal collapse bug heals once
PR #726 merges (user's call).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): sharpen Task 3 — test AND inject into the real showcase ARC.db files, both required

* docs(disc_walker): require the report table (building/count/method/status/total) as Task 3's actual output shape

* docs(progress): session closeout — TE-ARC-DATUM done, room-injection status, LFS quota, 2 Viewer bugs

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §LIVEWIRE re-verify 2026-07-11 — stale round-1 challenge answered, W-SCHED-MINE 7/7 + W-DX-WALKBACK-RSGT 14/14 clean-room on committed state

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(migration): MDB001 — 26 §LIVEWIRE device-mesh rows as hex-literal SQL, no-LFS channel for stale mesh.db copies (W-MESHDB-RESOLVE 2/5→5/5, byte-identical, idempotent)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(disc_walker): ROOM_INJECTION_HYBRID Task 4 — harden embed-8 pipeline against silent spatial_structure loss

Reframed the task after checking Task 6's own finding: the regression source isn't the
b93ca13 ARC-only strip (already disproven — spatial_structure was unchanged across it),
it's finalize_all_8.js's generic per-building meta-split silently shipping an empty
spatial_structure table whenever its (ephemeral, unpreserved) source lacks one — the
confirmed cause of 7/8 buildings' room-data loss in 6068fab.

Hardened finalize_all_8.js: explicit carrySpatialStructureForward() falls back to the
currently-shipped resident ARC.db when the fresh source has no room data, plus a
regression gate that aborts if carry-forward reported data but the write-time db
disagrees. module.exports + require.main guard added so the logic is unit-witnessable
without the vanished /tmp scratch inputs.

Witness W-SPATIAL-CARRY (9/9) reproduces the exact Duplex/SampleHouse regression shapes
against real data already local in /tmp/wt-fable-livewire (read-only, no LFS fetch).

Re-running the full pipeline against bim-ootb main and pushing regenerated *_ARC.db
files stays LFS-blocked until 2026-08-01 — this commit is the script fix + witness only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(disc_walker): ROOM_INJECTION_HYBRID Task 4 follow-up — SQL migration scripts carry spatial_structure into main, no binary push

Per repo convention (migration/DV_*_rules.sql, CL002_name_value_component_library.sql):
never touch a shipped DB as a binary commit when a deterministic SQL script can carry
the same content. bim-ootb main's 6 residents (SampleHouse/HHS/Clinic/Garage/Hospital/
SampleCastle) still ship 0 spatial_structure rows, and Duplex still carries the
unfiltered Roof row -- both real, verified on the unmerged fable/modeller-lod400-livewire
branch but not on main.

ROOM001-006_*_spatial_structure_carry.sql: full spatial_structure DDL + INSERT rows dumped
straight off livewire's real data (sqlite3 .mode insert, no BLOB columns in this table).
ROOM007_Duplex_strip_roof.sql: single DELETE -- confirmed by direct diff that main's 26
rows differ from livewire's 25 by exactly the R301 Roof row.

witness_room_migration_apply.sh (W-ROOM-MIGRATION-APPLY, 7/7): applies every script to a
scratch copy of main's real *_ARC.db and diffs the FULL resulting table against livewire's
real data -- byte-identical on all 7. Text-only diff, no LFS content touched.

This gets any local main checkout on par with the branch's room data by running
`sqlite3 modeller/{Name}_ARC.db < ROOM00N_*.sql` -- it does not deploy to the live site
(needs an actual DB commit, still LFS-blocked until 2026-08-01).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_INJECTION_HYBRID Task 4 SQL-migration follow-up

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): ROOM_WALKER_JS_PORT Task 1+2 — trace dwWalk trigger, port compile_rooms.py to JS

Task 1: traced dwWalk()'s real call chain (missed by a modeller/*.js-only grep — the actual
call site is in modeller.html's inline script). Confirmed explicit-user-action only (Outliner
discipline-row click -> onWalk callback -> bonsai_outliner.js's single dispatch chokepoint),
never automatic-on-load. No inconsistency to flag — Room Walker can copy this exact convention.

Task 2: build/room_walker.js ports compile_rooms.py's flood-fill/door-rescue/door-partition
algorithm verbatim (every constant + its justifying comment carried over unchanged). Same
db.exec()/_rows() sql.js interface disc_walker.js and finalize_all_8.js already use, so one
implementation genuinely serves both Node and browser -- no dual-implementation split.

Witness W-ROOM-WALKER-PARITY (6/6): runs the real Python and the JS port against separate
scratch copies of the same real building data and diffs the FULL resulting spatial_structure +
rel_contained_in_space content (not just counts) -- byte-identical on SampleCastle/HHS/Clinic/
Garage/Hospital/Terminal, both the door-rescue and door-partition paths exercised.

Surfaced, not silently fixed: Terminal's fresh algorithm run gives 53 rooms, not the 43
currently shipped -- shipped data predates the door-rescue/door-partition refinements. Flagged
as a content decision (BLOCKED), not assumed either way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_WALKER_JS_PORT Tasks 1+2 done, Terminal room-count question flagged

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(disc_walker): ship Terminal's corrected 53-room count via SQL migration, not a binary

User decision 2026-07-11: precision over staleness for display-only data. Terminal's shipped
spatial_structure (43 rooms) predates the door-rescue/door-partition refinements to the
compile-rooms algorithm; re-running today's algorithm (verified byte-identical between
compile_rooms.py and its JS port) gives 53. ROOM008_Terminal_correction_43_to_53.sql applies
the fix via sqlite3, no binary DB commit -- full replace is safe since Terminal's entire
spatial_structure table is synthetic (0 real rows).

witness_room008_terminal_correction.js (W-ROOM008-TERMINAL 4/4): migration-applied result is
byte-identical to room_walker.js computed fresh from the same real source geometry right now,
elements_meta confirmed untouched. This closes ROOM_WALKER_JS_PORT.md Task 3 fully (both bars).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_INJECTION_HYBRID self-heal SQL-patch loader shipped

Ports the Task 4 SQL migrations + MDB001 into bim-ootb modeller/patches/,
wired into str_walker_outliner.js's resident/geoDb open path (W-PATCH-SELFHEAL
43/43) — closes the manual-sqlite3-step gap the prior follow-up left open.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): §W5-RATCHET item 4 — per-room Z offsets mined from real Duplex MEP (11 rows, all guard-allowed families median-exact; M3 two-level verbatim; W5-ZFAM diagnostic; 14/14+7/7)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(disc_walker): ROOM_WALKER_JS_PORT Task 4+5 — wire Rooms Outliner category, retire compile_rooms.py from room-injection duty

Task 4 (browser wiring done in bim-ootb worktree, this commit is the bim-compiler-side fix
the browser witness caught): compileRooms() queried spatial_structure unconditionally for
storey guids, but Python's compile_rooms.py wraps that specific query in try/except because a
truly fresh building has no such table yet. The node-side parity witness never exercised this
path since every real shipped _ARC.db it compared against already had a spatial_structure
table -- only the live browser test (dropping the table entirely to simulate a fresh building)
surfaced it. Fixed with a table-existence check, mirroring Python's guard exactly. Re-verified:
node parity witness still 6/6, browser witness 12/12 (see bim-ootb companion commit).

Task 5: compile_rooms.py is retired from room-injection duty but NOT deleted -- found a real,
unrelated dependency (scripts/witness_geomap_tier3.py imports it directly as a Python baseline-
scoring library). Updated ROOM_INJECTION_HYBRID.md's Task 2 (automation half superseded by the
explicit-trigger Room Walker design, not built as originally specced) and
COMPILE_ROOMS_TYPE_INFERENCE.md's anchor (points future work at room_walker.js, not the now-
superseded Python file) so no future session gets misdirected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): ROOM_WALKER_JS_PORT all 5 tasks DONE

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): §WALL-LIGHT — measured sconce rows swap to wall-anchored WALL_HIGH + mined z (detector: median edge 0.09m vs pendants 0.96-2.28m; W6 0.963→1.000; pendants honestly refused)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(disc_walker): §WALL-SLOT — which-wall slot seam (miner/projection/walker/M3), 0 slots on Duplex BY MEASUREMENT: wall choice is mirror-dependent, absolute MIN/MAX refs refuse honestly (seam proven by falsifier, byte-inert at 0 rows)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(rooms): §7 ROOM WELL-FORMEDNESS — corridor/wall-crossing fix, SUSPECT_* review rows (ROOM009-014)

User visual review on HHS localhost found two algorithmic defects: a corridor accepted
as a room (open non-wall edge) and a room rect crossing through a wall. Root-caused on
real ARC data across all 8 buildings (not HHS-patched):
- §WALL-VERT: IfcCurtainWall parents have NO transform — curtain walls rasterized as
  nothing. Their IfcMember/IfcPlate children join the raster iff bbox_z >= 0.5×median
  real door height (self-scaling; Terminal's 33k flat Metal Deck plates stay out).
- §STOREY-Z: 'Unknown'-storey enclosure/doors (HHS 716, Hospital 3760 rows) reassigned
  to the z-nearest real floor. HHS flood-fill recovers on all 3 levels — door-partition
  (the corridor-blob source) no longer triggers there.
- §RECT-HONESTY: room rect = largest inscribed rectangle expanded to raw walls, replacing
  the region bbox — a rect can no longer paint across a wall into the next room.
- §ROOM-FORM (user doctrine "a room must be well formed, fully enclosed, has door"):
  openM (unsealed perimeter, 3-wide probe) > 2×median door width → SUSPECT_OPEN;
  no adjacent door → SUSPECT_NO_DOOR. Suspects keep '⚠'-marked rows for a future review
  feature, excluded from rel_contained_in_space; never silently dropped.

Both implementations updated in lockstep (compile_rooms.py numpy paths → plain flat
arrays mirroring the JS port operation-for-operation). Witnesses: W-ROOM-WALKER-PARITY
6/6 byte-identical; NEW W-ROOM-WELLFORMED 19/19 (independent-raster falsifiers: zero
wall-crossing non-suspect rects, zero suspect containment, HHS corridor collapse cannot
re-form). ROOM009-014 migrations verified apply-identical to walker output (6/6).
New counts: SC 51(9⚠) HHS 33(2⚠) Clinic 209(26⚠) Garage 5(3⚠) Hospital 213(66⚠)
Terminal 53(10⚠). Spec: ROOM_INJECTION_HYBRID.md §7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(progress): compact room-lane entries to spec-doc pointers (80-line budget)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(rooms): §8 MULTI-RECT — room space as a rectangle set, room_guid grouping (ROOM015-020)

A confirmed room's single §RECT-HONESTY rect under-covered non-rectangular rooms
(measured coverage down to 0.23-0.26 — the user's "doesn't fully form the inner room
space"). Per ROOM_INJECTION_HYBRID.md §8 (user-directed 3-step design):
1. Fill-ratio preprocessor: rooms whose first rect covers >=0.95 of the (seal-band-
   recovered) region stay single-row — the majority, cheapest path.
2. Room space set: below the bar, the region decomposes via repeated CONSTRAINED
   maximal-rectangle scan (both dims >= NOISE_FLOOR_DIM, grid-derived; stop at 0.95
   coverage or 8 rects — measured max used: 7). No wall-crossing by construction;
   curved-wall residue reported honestly, never faked.
3. Shared identity: one spatial_structure row per sub-rect; primary keeps RM_<st>_<k>,
   extras lettered (b, c, ...); NEW room_guid column groups the set; identical
   name/predefined_type; rel_contained_in_space keys LOGICAL guids only (any-rect
   containment). SUSPECT rooms stay single-rect (orthogonal to §ROOM-FORM).

Both ports lockstep; includes the concurrent §DISC-ARC discipline filter (Sonnet,
same working tree — merged, not overwritten). Coverage gains (W-ROOM-FILL, median/
worst): Hospital 0.74→0.86 / 0.32→0.67, Terminal 0.81→0.87 / 0.42→0.69, Clinic
0.78→0.81 / 0.45→0.57, per-room monotone. Witnesses: W-ROOM-WALKER-PARITY 6/6
byte-identical (dump now covers room_guid), W-ROOM-WELLFORMED 19/19 (zero regression,
sub-rects in the wall-crossing oracle), NEW W-ROOM-FILL 18/18, ROOM015-020 migrations
apply-identical 6/6 (supersede ROOM009-014's single-rect data).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(prompts): archive audit 2026-07-11 — 9 stale prompts to prompts/archive/ (evidence-logged)

9 archived (self-declared DONE/DEPRECATED/DRAINED + zero blocking refs), 22 kept live,
6 flagged ambiguous. Full per-file evidence trail in prompts/PROMPTS_ARCHIVE_AUDIT_2026-07-11.md
§Log. docs/*.md swept: nothing to archive (all live mkdocs pages, post-07-03 unified pass).
git mv only — history preserved. CLAUDE.md/PROGRESS.md FLM pointer fixes left uncommitted
(files dirty from concurrent lanes).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(resume): §8E-3 DONE — bim-ootb PR #731, render wiring was already shipped, real gap was substrate

Corrects this doc's own "render wiring not started" framing: _renderDiscChains/_commitDiscChains
(§ROUTER-NNCHAIN, §CAMPAIGN M4/M5) already render routeChains' segments as cylinder tubes. The
actual remaining gap: witness_modeller_router_nnchain.js is RED on bim-ootb main (shipped
Terminal_ARC.db resident is ARC-only, 0 MEP) and __dwPixelProbe's A/B-isolation missed dwChain-
tagged tubes (fixed). New witness_mep_route_render.js proves Terminal PLB 4315 + ACMV 1002 = 5317
and Duplex PLB 358 segs render + paint real isolated pixels, matching W-WALKBACK-MEP's oracle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(resume): note PR #731 was auto-merged by repo bot, not manually

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): ROOM021 — carry 105-row spatial_structure into Viewer's HHS buildings db + §4 execution log

VIEWER_FIND_PANEL_ROOM_ACCURACY.md §2b: buildings/HHS_Office_Federated_extracted.db
(the file the Viewer actually fetches for HHS) still shipped the stale 14-row set;
ROOM021 ports the SAME source-of-truth data as ROOM002 (modeller/HHS_ARC.db @
fable/modeller-lod400-livewire fd7da67, extracted via sqlite3 .mode insert) to the
buildings/ target. Applied+verified locally (§ROOM021-PARITY byte-identical, 109
rows); binary stays uncommitted per the DB-via-SQL-migration rule. §4 appended:
Tasks 1+2 DONE in bim-ootb fix/viewer-room-accuracy @ a995908 (local only, LFS
block) — W-VIEWER-ROOM-HAB 6/6 (Duplex 20 habitable + R301 label:ROOF excluded;
HHS 105/0 leaks), W-VIEWER-TYPE-GROUP (COMPILED:105 -> INTERNAL_DOORPART:105).
No Viewer-side self-heal .sql loader exists (checked; Modeller's is on unmerged
fix/meshdb-selfheal-loader only) — noted as open follow-up, not invented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(rooms): VIEWER_FIND_PANEL_ROOM_ACCURACY §5 — Task 1/2 + §2b shipped, supersedes stuck §4

§4's fix/viewer-room-accuracy worktree was left uncommitted-beyond-local and unpushed, missing its
own named follow-up (no Viewer-side self-heal loader). Rebuilt clean this session: bim-ootb PR #732
ships the habitability filter (Task 1), the Type-toggle COMPILED fallthrough fix (Task 2), and the
HHS buildings/patches/ SQL migration + runtime self-heal loader (§2b) — witness 11/11, pushed with
no LFS stall (corrects §4's over-cautious "no push possible" note). ROOM021_HHS_buildings_extracted_
carry.sql (already committed by §4) cross-validated byte-identical to the new patch's payload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): correct §5 — PR #732 was auto-merge-bot merged, not left open; flag concurrent worktree

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(terminal): root-cause coordinate-frame mismatch + fix deploy DB in place

TERMINAL_COORDINATE_FRAME_MISMATCH.md: bim-ootb's Terminal_ARC.db matches
raw-IFC ground truth (<2cm, verified via ifcopenshell world-bbox-center on
the source .ifc); bim-compiler's deploy/buildings/Terminal_extracted.db was
a carve-out of the multi-building sandbox_1M city demo (extract_per_building.py
reading T0_Terminal_ rows verbatim from build_sandbox_1M.py's tile-placement
output, scripts/build_sandbox_1M.py L216-320) stacked on extractIFCtoDB.py's
S169 centroid-normalize (L1453-1506) — both uncorrected. Delta proven constant
across 12 sampled guids (stdev <1mm): (545.61m, 51.22m, 14.66m).

Fixed deploy/buildings/Terminal_extracted.db (gitignored build artifact, not
committed) in place with the proven-constant offset correction; backed up,
integrity-checked, re-verified against ground truth (<6mm on all axes).

PROGRESS.md: mark item resolved, flag other CBD_BUILDINGS sharing the same
carve-out path as unverified for the same bug class.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): ROOM_INJECTION_HYBRID.md §9 — Room Lens volume-box fix shipped, OCI upload block lifted

Room_guid multi-rect grouping ported into viewer/navigate_find.js's _allRoomVolumes()/
_roomLensOn() (bim-ootb PR #733), witnessed 8/8 (rendered box footprint-area SUM = spatial_
structure's own rect-union area SUM, diff=0.000m2) with zero regression to the existing
habitability-filter witness (11/11). Closes the standing OCI room-data upload blocker.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): harden DB/migration-script rule, PR-merge authority, room-template strategy specs

- CLAUDE.md: DB changes are permanently migration-script+self-heal-loader, not an LFS workaround —
  stop citing LFS as the blocker for DB fixes.
- prompts/MANAGER.md: PR merge is standing Manager scope once independently verified, don't kick
  back an already-answerable merge decision.
- VIEWER_FIND_PANEL_ROOM_ACCURACY.md / UBBL_RULES_GATE.md: MANAGER assignment markers + doc-trail
  corrections from today's dispatched work.
- ROOM_TYPE_TEMPLATE_CLASSIFIER.md: new spec, room-type classification via size/aspect-ratio
  template mined from Duplex's real object_type ground truth, repeat-confirmation methodology.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
red1oon added a commit that referenced this pull request Jul 11, 2026
…ects stale marathon framing

Investigated "the DiscWalk task" per user request. Found the 2026-07-10
marathon memory's framing is stale: the Z-datum bug it called "the actual
next real gap" is fully done and merged in BOTH repos (bim-compiler PR
#40, bim-ootb PR #726 squash 3d09ad6 — confirmed already an ancestor of
local main, correcting PROGRESS.md's "open, not merged" note) — as is
fix/dw-rot-units (PR #723). Only 3 small, already-verified, no-conflict
branches remain genuinely unmerged (PRs #722/#724/#725), plus one real
open question: the guide-screenshot camera bug from the same marathon,
never diagnosed. Scoped a Fable session: re-verify the 3 branches fresh
(no merge/push — Sonnet reviews before any of that), then chase the
screenshot bug's root cause. Named the stale-radians migration question
as explicitly out of scope (separate, harder design task).
red1oon added a commit that referenced this pull request Jul 11, 2026
…plant correlation (weak/none) — drains the meshdb-livewire backlog (#42)

* docs: correct guide-screenshot verdict — reattempt succeeded

* docs: add prompts/MANAGER.md — cross-session review/admin role

* docs(disc_walker): ROOM_INJECTION_HYBRID hardened for Fable handoff — Modeller-only scope

Renumber WalkerDoctrine.md's duplicate §13 to §14 (rooms rule) and fix the citation.
Drop the dead SAMPLECASTLE_REAL_ROOMS_RECONCILE.md anchor (lives only on an unmerged
branch, not this one). Reframe the Viewer Find Panel Room Lens reference as a one-way,
read-only borrow-from source for the Modeller's ARC-import step, name its unfiltered
query as a live false positive, and explicitly scope Task 5 to Modeller-only — no
Viewer files touched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): anchor THE GOAL to VISION-LOCK — "working" was undefined

MANAGER.md said "get the actual thing working" without citing what working means,
letting review verdicts drift toward generic pass/fail instead of the actual product
bar. Point at RESUME_GRAPH_MODELLER_INTEGRATION.md §VISION-LOCK's five sentences.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): correct §2 — Terminal's 43 rooms are synthetic, not real

Direct query (object_type=COMPILED, ≈-named) proves Terminal has zero real IfcSpace
rooms — the doc previously miscounted them as "real rooms already baked in." Same
correction applied to HHS's 14 rows (already caught by Task 5 but §2's table hadn't
been updated to match). Adds the full 8-building room-count table: only Duplex has
real, habitability-filtered data, and it isn't merged to main yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §2 — source-IFC check finds SampleHouse extraction bug

Direct grep of internal/sources/Ifc4_SampleHouse.ifc finds 4 real IFCSPACE entities
(Living room, Bedroom, Entrance hall, Roof) that never made it into the shipped
SampleHouse_ARC.db (0 rooms) — an extraction gap, not a source-data gap as previously
assumed. Clinic/Garage/Hospital/HHS have no source IFC in this checkout to check
either way, so their "0 rooms" state is unverified, not confirmed-no-data.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add Task 6 (SampleHouse extraction bug), reassign forward work to Sonnet

Task 6: 3 usable real rooms exist in SampleHouse's source IFC but never reached the
shipped ARC — an extraction bug, not a data gap. Per user directive, all further work
on this doc goes to Sonnet, not Fable, from here on; Tasks 1+5's Fable history is left
as an accurate record, not rewritten.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(compile_rooms): §DOOR-RESCUE — recover real small rooms (toilets/utility) below MIN_AREA

User-flagged, verified before fixing: HHS ("large U-shape office block, lots of office rooms
with doors") only compiled 2 rooms; restrooms/utility rooms were being missed across every
building, not just HHS. Instrumented the flood-fill to log ALL candidate pockets (not just
accepted ones) — confirmed this was NOT a mis-tuned MIN_AREA=4.0 threshold hiding rooms that
were actually detected: most sub-threshold pockets are <1.0 m^2 wall-joint/cavity artefacts
(noise), but a real population of 1.0-4.0 m^2 pockets IS a genuine small room (restroom/closet/
riser) wrongly dropped by the same blanket cutoff.

The user's hint ("rooms has doors" / "look for clues that define a toilet, utility that house
MEP") pointed at the fix: MEP fixture data isn't reliable (ARC-only discipline strip already
removed sanitary/plumbing elements from 4 of 5 buildings), but door adjacency is a real,
non-invented structural signal already in every ARC.db — a genuine small room a person uses
always has a door; a wall cavity never does. Measured before shipping: for HHS/Clinic/Hospital/
SampleCastle, pockets <1.0 m^2 are rarely door-adjacent (noise); pockets in [1.0, 4.0) m^2 are
door-adjacent in the large majority (real small rooms) — the two size bands are different
populations, not an arbitrary split.

- storey_doors() + _door_adjacent(): per-storey real IfcDoor centres, 1.0m buffer.
- flood_rooms(): a pocket in [DOOR_RESCUE_MIN_AREA=1.0, MIN_AREA=4.0) m^2 is now accepted iff
  door-adjacent; still-tagged ≈/RM_/COMPILED (spacesOf()'s placement-exclusion untouched) but
  predefined_type='INTERNAL_SMALL' (vs 'INTERNAL') for traceability of which path found it.
- Re-ran --write on the 5 gap buildings: HHS 2→5, Clinic 113→190, Hospital 142→213,
  SampleCastle 25→47, Garage unchanged (0 door-adjacent small pockets found).
- W-ROOM-INJECT-ALL8 rerun 32/32 on bim-ootb worktree: placement-eligibility still 0 for every
  synthetic-only building — door-rescued rooms are exactly as display-only as any other
  compiled room, never reach schedule placement.

Doc: prompts/Modeller/DISC_Walker/ROOM_INJECTION_HYBRID.md updated with the finding + fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): DB Storage Policy — stop new .db commits, GitHub LFS bandwidth cap hit

GitHub flagged 10GB/month LFS bandwidth usage. 59+ .db files already LFS-tracked
(deploy/buildings/*, build/*.db) burn quota on every clone/fetch. Going forward:
schema/rules DBs regenerate via migration/*.sql or their mining scripts; extracted/
derived building DBs distribute via OCI (already the dev/live channel), not git.
Existing LFS-tracked files are left alone — this only stops new commits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(compile_rooms): replace fitted door-rescue band with an abstract rule

User pushback (correct): the previous §DOOR-RESCUE fix used DOOR_RESCUE_MIN_AREA=1.0 and a flat
1.0m buffer picked by eyeballing HHS/Clinic/Hospital's specific data — a fitted band, not a rule.
This generalizes it:

- The room definition is now architectural, not size-banded: an enclosed pocket is a room if it
  is big enough on its own (area >= MIN_AREA, unchanged) OR it has a real door AND isn't a bare
  rasterization sliver. No area number stands between "noise" and "small room" anymore.
- Door adjacency buffer is now each door's OWN extracted footprint (half its real leaf/frame
  span) + one grid cell of slack (RES) -- self-scaling to whatever doors a building actually has,
  not a fixed metre guess that happened to work on 5 sample buildings.
- The noise floor is NOISE_FLOOR_DIM = 3*RES (0.6m) -- a pocket narrower than a few grid cells in
  EITHER axis is rasterization noise by construction, a property of the flood-fill's own
  resolution, not an area threshold reverse-engineered from observed rooms.

Re-verified: HHS 6, Clinic 195, Hospital 201, SampleCastle 53, Garage 5 (close to, not identical
to, the earlier fitted-band numbers -- expected, since the rule is now geometry-derived rather
than tuned to match them). W-ROOM-INJECT-ALL8 rerun 32/32 on bim-ootb worktree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record both door-rescue passes — fitted band superseded by abstract rule

* fix(compile_rooms): §DOOR-NOT-ROOM — lift/elevator doors aren't room evidence

Tested SEAL=1 (narrower wall-dilation) to try to recover HHS's WC-stall spaces the user found
named in German ("WC Trennwand") — rejected: doesn't fix HHS (the WC block's OWN enclosing walls,
not just its internal stall partitions, are simply absent from this extraction, a resolution/
data-completeness issue SEAL can't touch) AND it fragments real rooms elsewhere into spurious
1-2 sq.m splinters in Hospital (142->253, mostly noise) and SampleCastle -- a regression, not an
improvement. Reverted to SEAL=2 (already-shipped, verified value unchanged).

Separately, user asked whether doors have standard dimensions we could use as a smell test.
Checked: real hinged doors cluster 0.7-1.1m (single leaf) / 1.2-2.7m (double leaf/wide entrance)
across all 5 buildings' door data -- consistent, no anomaly, EXCEPT SampleCastle: 28 IfcDoor rows
at 0.5m width, all named 'liftdeur' (Dutch: elevator door). Real, correctly-classified doors --
but they lead to a lift shaft, not a room, and 2 of them were rescuing actual elevator-shaft
fragments as fake compiled "rooms" (verified directly: room count with vs without lift doors as
the door-rescue signal differs). Same shape of problem as the existing §STAIR-EXCLUDE pattern --
excluded via a maintained, multi-language door-name keyword list (liftdeur/lift/elevator/aufzug/
fahrstuhl/hoist), not a width cutoff (a lift door's width isn't reliably distinct from a narrow
single-leaf door's).

SampleCastle 53->51 (the 2 lift-shaft fakes removed); HHS/Clinic/Hospital/Garage unchanged (no
lift doors in their door-rescue signal). W-ROOM-INJECT-ALL8 rerun 32/32.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record SEAL=1 rejection + lift-door exclusion passes, HHS WC gap flagged open

* feat(compile_rooms): §DOOR-PARTITION — every door leads to a room, even where walls can't

User's repeated, correct point: HHS has 43/39/34 real doors across 3 floors (verified directly,
German-named "Türelement... Drehflügel" = swing-door elements) -- "each door must be to a room."
Flood-fill (even with §DOOR-RESCUE) only ever found 4/2/0 rooms on those floors because HHS's
extraction is missing the walls that would divide the floor into individual offices at all (91%+
of each floor floods as one exterior-reachable blob) -- door-rescue only widens acceptance for
pockets flood-fill ALREADY finds enclosed; it can't help where nothing is enclosed to begin with.

New technique for where wall-enclosure structurally cannot work: partition the storey's free space
by NEAREST DOOR (multi-source BFS through real free cells, real walls still block) -- each door
claims whatever space no other door reaches first, exactly the "every door leads to a room"
principle stated directly, not an area/threshold proxy for it.

Gate (measured, not fitted per-building): use door-partition only where flood-fill's OWN result
(with door-rescue already applied) finds fewer rooms than DOOR_SHORTFALL_RATIO=0.15 of the
storey's real door count -- HHS's floors find 0-11% of their door count via flood-fill; every
other building's WORKING floors find 20-100%+ of theirs (Garage's sparsest working floor: 5/8=62%;
Hospital's sparsest: 1/5=20%) -- the ratio sits below every failing floor and above every working
one, verified directly so it never overrides an already-functioning result (Garage's 5-room floor
and Hospital's 1-room floor both correctly kept their flood-fill result unchanged).

Result: HHS 6->105 (36/31/29/9 per floor -- in the "tens per floor" range the user predicted from
door counts alone). Clinic/Hospital/Garage/SampleCastle counts unchanged except Clinic's near-empty
'Unknown' storey (0->2, same gate correctly firing there too). predefined_type='INTERNAL_DOORPART'
marks these rows for traceability; object_type='COMPILED' (what tag-purity/placement-exclusion
checks key on) unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record §DOOR-PARTITION pass — HHS 6→105 rooms

* docs(disc_walker): add VIEWER_FIND_PANEL_ROOM_ACCURACY.md — port habitability+door-partition results to Find Panel

* docs(disc_walker): §TE-ARC-DATUM merged (PR #40) — entry point for bim-ootb port

Records the merge (b202eb44b) and hands off the one remaining task: port
rule_frame_ref mining + walk-time zOff to bim-ootb's own disc_walker.js and
terminal_rules.db — the fix is bim-compiler-only, the actual Modeller app still
has the collapse bug live until this ports over.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): Worktree Hygiene — the other LFS bandwidth drain

Committing DBs wasn't the only cost: 49 bim-ootb worktrees + a duplicate ~/Projects/bim-ootb
clone were each pulling fresh 100-250MB mesh.db/geo.db LFS blobs. Real end users never
touch git LFS at all (they hit the deployed static site) — 100% of the quota was dev-side
worktree churn. Removed the duplicate clone (confirmed clean, 100+ commits stale) and
pruned 25 safe (clean + fully-pushed) stale worktrees in bim-ootb. Protocol: check
`git worktree list` before creating a new one, one clone per repo, prune on sight.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): LFS QUOTA EXHAUSTED — hard block, all-local, no exceptions

GitHub confirmed 0 bandwidth budget remaining, not just approaching the cap. Escalates
the earlier reduce-usage guidance to a hard block: no pushing any commit that touches
LFS-tracked content, no fetching/checking-out branches whose LFS blobs aren't already
locally cached, until the user confirms the quota has reset. Applies to every Agent-tool
prompt that touches git, not just this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add COMPILE_ROOMS_TYPE_INFERENCE.md — room-function guessing where no IfcSpace ever named it

* fix(disc_walker): correct VIEWER_FIND_PANEL_ROOM_ACCURACY.md — right repo, right file, new findings

User caught it: the doc anchored on bim-compiler/deploy/dev/navigate_find.js, which turns out to
be a STALE, unmaintained fork (2859-line diff vs the live copy, no recent commits since this
repo's initial migration). The actual, actively-developed Viewer code is bim-ootb/viewer/
navigate_find.js (3640 lines, commits as recent as pill-drawer/HBA work) -- same repo as Modeller's
disc_walker.js, removing the cross-repo constraint the original doc assumed.

Checked the live code directly and found it's further along than assumed (storey grouping + a
Storey/Type toggle already exist) but also found a new, concrete bug: the Type toggle's
`object_type || predefined_type` fallback never reaches predefined_type for compiled rooms, since
object_type='COMPILED' is always truthy -- masks the INTERNAL/INTERNAL_SMALL/INTERNAL_DOORPART
distinction compile_rooms.py now writes.

Biggest correction: confirmed viewer/import_db_builder.js (the live "drop your own IFC" schema
builder) never creates a spatial_structure table at all -- a user's own imported building gets ZERO
room data today, real or synthetic. Scoped as its own Task 5, separate from the display-only fixes,
since fixing it means porting compile_rooms.py's algorithm from Python to JS (no Python runs in a
browser) -- not a quick win.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add ROOM_WALKER_JS_PORT.md — retire Python, compute-once via explicit trigger

User's call, this session: since real usage is 100% JS (no server, no Python runtime in the
browser — confirmed for the live IFC-import path), retire compile_rooms.py in favor of one JS
port usable both offline (Node CLI, replacing today's Python bake for the 8 shipped residents) and
in-browser (a new Modeller Outliner "Room Walker" action, parallel to the existing Disc Walker
convention). Explicitly NOT "recompute live on every open" -- user's own point that this costs
real time (HHS's grid alone is ~90k cells/floor) -- compute once, on demand or at import, persist,
same principle as today's offline bake just relocated to whichever moment actually needs it.

5 tasks specced: (1) verify how Disc Walker is actually triggered today before assuming a UI
pattern to copy -- unconfirmed this session; (2) port the algorithm verbatim to a shared JS module;
(3) Node CLI mode replacing compile_rooms.py, witnessed byte-for-byte against this session's Python
counts (SampleHouse 3/Duplex 20/Terminal 43/SampleCastle 51/HHS 105/Clinic 197/Garage 5/Hospital
201) before Python is touched; (4) the browser-mode Room Walker Outliner action; (5) retire
compile_rooms.py once Task 3's parity witness is 100% green.

Cross-referenced from ROOM_INJECTION_HYBRID.md's Task 3 (now has a concrete trigger mechanism
instead of an open-ended display spec) and VIEWER_FIND_PANEL_ROOM_ACCURACY.md's Task 5 (this doc
is its actual breakdown).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): LFS quota resets 2026-08-01; any push may hang regardless of content

User-confirmed reset date. Also sharpens the finding: a push touching zero LFS-tracked
files still hung 2+ min and never landed (fix/dw-datum-port push attempt) - the git-lfs
pre-push hook appears to probe the endpoint unconditionally. Rule is now "any push may
hang until reset," not just LFS-content pushes. Don't retry a hung push blindly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): anchor to the published ModellerGuide as the tangible external target

VISION-LOCK is the internal engineering bar; the guide site is the user-facing proof
it's met. Notes current known gaps (Terminal datum port stuck behind LFS block,
room-mode data coverage, x-ray bug, 2 live Viewer UI bugs) so a new session doesn't
have to re-derive "how far are we" from scratch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §DW-DATUM bim-ootb port DONE — pushed, PR #726 open

Verified and pushed successfully (earlier push attempt's 2-min hang was transient,
not a hard LFS block - retry succeeded in 25s). Terminal collapse bug heals once
PR #726 merges (user's call).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): sharpen Task 3 — test AND inject into the real showcase ARC.db files, both required

* docs(disc_walker): require the report table (building/count/method/status/total) as Task 3's actual output shape

* docs(progress): session closeout — TE-ARC-DATUM done, room-injection status, LFS quota, 2 Viewer bugs

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §LIVEWIRE re-verify 2026-07-11 — stale round-1 challenge answered, W-SCHED-MINE 7/7 + W-DX-WALKBACK-RSGT 14/14 clean-room on committed state

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(migration): MDB001 — 26 §LIVEWIRE device-mesh rows as hex-literal SQL, no-LFS channel for stale mesh.db copies (W-MESHDB-RESOLVE 2/5→5/5, byte-identical, idempotent)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(disc_walker): ROOM_INJECTION_HYBRID Task 4 — harden embed-8 pipeline against silent spatial_structure loss

Reframed the task after checking Task 6's own finding: the regression source isn't the
b93ca13 ARC-only strip (already disproven — spatial_structure was unchanged across it),
it's finalize_all_8.js's generic per-building meta-split silently shipping an empty
spatial_structure table whenever its (ephemeral, unpreserved) source lacks one — the
confirmed cause of 7/8 buildings' room-data loss in 6068fab.

Hardened finalize_all_8.js: explicit carrySpatialStructureForward() falls back to the
currently-shipped resident ARC.db when the fresh source has no room data, plus a
regression gate that aborts if carry-forward reported data but the write-time db
disagrees. module.exports + require.main guard added so the logic is unit-witnessable
without the vanished /tmp scratch inputs.

Witness W-SPATIAL-CARRY (9/9) reproduces the exact Duplex/SampleHouse regression shapes
against real data already local in /tmp/wt-fable-livewire (read-only, no LFS fetch).

Re-running the full pipeline against bim-ootb main and pushing regenerated *_ARC.db
files stays LFS-blocked until 2026-08-01 — this commit is the script fix + witness only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(disc_walker): ROOM_INJECTION_HYBRID Task 4 follow-up — SQL migration scripts carry spatial_structure into main, no binary push

Per repo convention (migration/DV_*_rules.sql, CL002_name_value_component_library.sql):
never touch a shipped DB as a binary commit when a deterministic SQL script can carry
the same content. bim-ootb main's 6 residents (SampleHouse/HHS/Clinic/Garage/Hospital/
SampleCastle) still ship 0 spatial_structure rows, and Duplex still carries the
unfiltered Roof row -- both real, verified on the unmerged fable/modeller-lod400-livewire
branch but not on main.

ROOM001-006_*_spatial_structure_carry.sql: full spatial_structure DDL + INSERT rows dumped
straight off livewire's real data (sqlite3 .mode insert, no BLOB columns in this table).
ROOM007_Duplex_strip_roof.sql: single DELETE -- confirmed by direct diff that main's 26
rows differ from livewire's 25 by exactly the R301 Roof row.

witness_room_migration_apply.sh (W-ROOM-MIGRATION-APPLY, 7/7): applies every script to a
scratch copy of main's real *_ARC.db and diffs the FULL resulting table against livewire's
real data -- byte-identical on all 7. Text-only diff, no LFS content touched.

This gets any local main checkout on par with the branch's room data by running
`sqlite3 modeller/{Name}_ARC.db < ROOM00N_*.sql` -- it does not deploy to the live site
(needs an actual DB commit, still LFS-blocked until 2026-08-01).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_INJECTION_HYBRID Task 4 SQL-migration follow-up

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): ROOM_WALKER_JS_PORT Task 1+2 — trace dwWalk trigger, port compile_rooms.py to JS

Task 1: traced dwWalk()'s real call chain (missed by a modeller/*.js-only grep — the actual
call site is in modeller.html's inline script). Confirmed explicit-user-action only (Outliner
discipline-row click -> onWalk callback -> bonsai_outliner.js's single dispatch chokepoint),
never automatic-on-load. No inconsistency to flag — Room Walker can copy this exact convention.

Task 2: build/room_walker.js ports compile_rooms.py's flood-fill/door-rescue/door-partition
algorithm verbatim (every constant + its justifying comment carried over unchanged). Same
db.exec()/_rows() sql.js interface disc_walker.js and finalize_all_8.js already use, so one
implementation genuinely serves both Node and browser -- no dual-implementation split.

Witness W-ROOM-WALKER-PARITY (6/6): runs the real Python and the JS port against separate
scratch copies of the same real building data and diffs the FULL resulting spatial_structure +
rel_contained_in_space content (not just counts) -- byte-identical on SampleCastle/HHS/Clinic/
Garage/Hospital/Terminal, both the door-rescue and door-partition paths exercised.

Surfaced, not silently fixed: Terminal's fresh algorithm run gives 53 rooms, not the 43
currently shipped -- shipped data predates the door-rescue/door-partition refinements. Flagged
as a content decision (BLOCKED), not assumed either way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_WALKER_JS_PORT Tasks 1+2 done, Terminal room-count question flagged

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(disc_walker): ship Terminal's corrected 53-room count via SQL migration, not a binary

User decision 2026-07-11: precision over staleness for display-only data. Terminal's shipped
spatial_structure (43 rooms) predates the door-rescue/door-partition refinements to the
compile-rooms algorithm; re-running today's algorithm (verified byte-identical between
compile_rooms.py and its JS port) gives 53. ROOM008_Terminal_correction_43_to_53.sql applies
the fix via sqlite3, no binary DB commit -- full replace is safe since Terminal's entire
spatial_structure table is synthetic (0 real rows).

witness_room008_terminal_correction.js (W-ROOM008-TERMINAL 4/4): migration-applied result is
byte-identical to room_walker.js computed fresh from the same real source geometry right now,
elements_meta confirmed untouched. This closes ROOM_WALKER_JS_PORT.md Task 3 fully (both bars).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_INJECTION_HYBRID self-heal SQL-patch loader shipped

Ports the Task 4 SQL migrations + MDB001 into bim-ootb modeller/patches/,
wired into str_walker_outliner.js's resident/geoDb open path (W-PATCH-SELFHEAL
43/43) — closes the manual-sqlite3-step gap the prior follow-up left open.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): §W5-RATCHET item 4 — per-room Z offsets mined from real Duplex MEP (11 rows, all guard-allowed families median-exact; M3 two-level verbatim; W5-ZFAM diagnostic; 14/14+7/7)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(disc_walker): ROOM_WALKER_JS_PORT Task 4+5 — wire Rooms Outliner category, retire compile_rooms.py from room-injection duty

Task 4 (browser wiring done in bim-ootb worktree, this commit is the bim-compiler-side fix
the browser witness caught): compileRooms() queried spatial_structure unconditionally for
storey guids, but Python's compile_rooms.py wraps that specific query in try/except because a
truly fresh building has no such table yet. The node-side parity witness never exercised this
path since every real shipped _ARC.db it compared against already had a spatial_structure
table -- only the live browser test (dropping the table entirely to simulate a fresh building)
surfaced it. Fixed with a table-existence check, mirroring Python's guard exactly. Re-verified:
node parity witness still 6/6, browser witness 12/12 (see bim-ootb companion commit).

Task 5: compile_rooms.py is retired from room-injection duty but NOT deleted -- found a real,
unrelated dependency (scripts/witness_geomap_tier3.py imports it directly as a Python baseline-
scoring library). Updated ROOM_INJECTION_HYBRID.md's Task 2 (automation half superseded by the
explicit-trigger Room Walker design, not built as originally specced) and
COMPILE_ROOMS_TYPE_INFERENCE.md's anchor (points future work at room_walker.js, not the now-
superseded Python file) so no future session gets misdirected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): ROOM_WALKER_JS_PORT all 5 tasks DONE

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): §WALL-LIGHT — measured sconce rows swap to wall-anchored WALL_HIGH + mined z (detector: median edge 0.09m vs pendants 0.96-2.28m; W6 0.963→1.000; pendants honestly refused)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(disc_walker): §WALL-SLOT — which-wall slot seam (miner/projection/walker/M3), 0 slots on Duplex BY MEASUREMENT: wall choice is mirror-dependent, absolute MIN/MAX refs refuse honestly (seam proven by falsifier, byte-inert at 0 rows)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(rooms): §7 ROOM WELL-FORMEDNESS — corridor/wall-crossing fix, SUSPECT_* review rows (ROOM009-014)

User visual review on HHS localhost found two algorithmic defects: a corridor accepted
as a room (open non-wall edge) and a room rect crossing through a wall. Root-caused on
real ARC data across all 8 buildings (not HHS-patched):
- §WALL-VERT: IfcCurtainWall parents have NO transform — curtain walls rasterized as
  nothing. Their IfcMember/IfcPlate children join the raster iff bbox_z >= 0.5×median
  real door height (self-scaling; Terminal's 33k flat Metal Deck plates stay out).
- §STOREY-Z: 'Unknown'-storey enclosure/doors (HHS 716, Hospital 3760 rows) reassigned
  to the z-nearest real floor. HHS flood-fill recovers on all 3 levels — door-partition
  (the corridor-blob source) no longer triggers there.
- §RECT-HONESTY: room rect = largest inscribed rectangle expanded to raw walls, replacing
  the region bbox — a rect can no longer paint across a wall into the next room.
- §ROOM-FORM (user doctrine "a room must be well formed, fully enclosed, has door"):
  openM (unsealed perimeter, 3-wide probe) > 2×median door width → SUSPECT_OPEN;
  no adjacent door → SUSPECT_NO_DOOR. Suspects keep '⚠'-marked rows for a future review
  feature, excluded from rel_contained_in_space; never silently dropped.

Both implementations updated in lockstep (compile_rooms.py numpy paths → plain flat
arrays mirroring the JS port operation-for-operation). Witnesses: W-ROOM-WALKER-PARITY
6/6 byte-identical; NEW W-ROOM-WELLFORMED 19/19 (independent-raster falsifiers: zero
wall-crossing non-suspect rects, zero suspect containment, HHS corridor collapse cannot
re-form). ROOM009-014 migrations verified apply-identical to walker output (6/6).
New counts: SC 51(9⚠) HHS 33(2⚠) Clinic 209(26⚠) Garage 5(3⚠) Hospital 213(66⚠)
Terminal 53(10⚠). Spec: ROOM_INJECTION_HYBRID.md §7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(progress): compact room-lane entries to spec-doc pointers (80-line budget)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(rooms): §8 MULTI-RECT — room space as a rectangle set, room_guid grouping (ROOM015-020)

A confirmed room's single §RECT-HONESTY rect under-covered non-rectangular rooms
(measured coverage down to 0.23-0.26 — the user's "doesn't fully form the inner room
space"). Per ROOM_INJECTION_HYBRID.md §8 (user-directed 3-step design):
1. Fill-ratio preprocessor: rooms whose first rect covers >=0.95 of the (seal-band-
   recovered) region stay single-row — the majority, cheapest path.
2. Room space set: below the bar, the region decomposes via repeated CONSTRAINED
   maximal-rectangle scan (both dims >= NOISE_FLOOR_DIM, grid-derived; stop at 0.95
   coverage or 8 rects — measured max used: 7). No wall-crossing by construction;
   curved-wall residue reported honestly, never faked.
3. Shared identity: one spatial_structure row per sub-rect; primary keeps RM_<st>_<k>,
   extras lettered (b, c, ...); NEW room_guid column groups the set; identical
   name/predefined_type; rel_contained_in_space keys LOGICAL guids only (any-rect
   containment). SUSPECT rooms stay single-rect (orthogonal to §ROOM-FORM).

Both ports lockstep; includes the concurrent §DISC-ARC discipline filter (Sonnet,
same working tree — merged, not overwritten). Coverage gains (W-ROOM-FILL, median/
worst): Hospital 0.74→0.86 / 0.32→0.67, Terminal 0.81→0.87 / 0.42→0.69, Clinic
0.78→0.81 / 0.45→0.57, per-room monotone. Witnesses: W-ROOM-WALKER-PARITY 6/6
byte-identical (dump now covers room_guid), W-ROOM-WELLFORMED 19/19 (zero regression,
sub-rects in the wall-crossing oracle), NEW W-ROOM-FILL 18/18, ROOM015-020 migrations
apply-identical 6/6 (supersede ROOM009-014's single-rect data).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(prompts): archive audit 2026-07-11 — 9 stale prompts to prompts/archive/ (evidence-logged)

9 archived (self-declared DONE/DEPRECATED/DRAINED + zero blocking refs), 22 kept live,
6 flagged ambiguous. Full per-file evidence trail in prompts/PROMPTS_ARCHIVE_AUDIT_2026-07-11.md
§Log. docs/*.md swept: nothing to archive (all live mkdocs pages, post-07-03 unified pass).
git mv only — history preserved. CLAUDE.md/PROGRESS.md FLM pointer fixes left uncommitted
(files dirty from concurrent lanes).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(resume): §8E-3 DONE — bim-ootb PR #731, render wiring was already shipped, real gap was substrate

Corrects this doc's own "render wiring not started" framing: _renderDiscChains/_commitDiscChains
(§ROUTER-NNCHAIN, §CAMPAIGN M4/M5) already render routeChains' segments as cylinder tubes. The
actual remaining gap: witness_modeller_router_nnchain.js is RED on bim-ootb main (shipped
Terminal_ARC.db resident is ARC-only, 0 MEP) and __dwPixelProbe's A/B-isolation missed dwChain-
tagged tubes (fixed). New witness_mep_route_render.js proves Terminal PLB 4315 + ACMV 1002 = 5317
and Duplex PLB 358 segs render + paint real isolated pixels, matching W-WALKBACK-MEP's oracle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(resume): note PR #731 was auto-merged by repo bot, not manually

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): ROOM021 — carry 105-row spatial_structure into Viewer's HHS buildings db + §4 execution log

VIEWER_FIND_PANEL_ROOM_ACCURACY.md §2b: buildings/HHS_Office_Federated_extracted.db
(the file the Viewer actually fetches for HHS) still shipped the stale 14-row set;
ROOM021 ports the SAME source-of-truth data as ROOM002 (modeller/HHS_ARC.db @
fable/modeller-lod400-livewire fd7da67, extracted via sqlite3 .mode insert) to the
buildings/ target. Applied+verified locally (§ROOM021-PARITY byte-identical, 109
rows); binary stays uncommitted per the DB-via-SQL-migration rule. §4 appended:
Tasks 1+2 DONE in bim-ootb fix/viewer-room-accuracy @ a995908 (local only, LFS
block) — W-VIEWER-ROOM-HAB 6/6 (Duplex 20 habitable + R301 label:ROOF excluded;
HHS 105/0 leaks), W-VIEWER-TYPE-GROUP (COMPILED:105 -> INTERNAL_DOORPART:105).
No Viewer-side self-heal .sql loader exists (checked; Modeller's is on unmerged
fix/meshdb-selfheal-loader only) — noted as open follow-up, not invented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(rooms): VIEWER_FIND_PANEL_ROOM_ACCURACY §5 — Task 1/2 + §2b shipped, supersedes stuck §4

§4's fix/viewer-room-accuracy worktree was left uncommitted-beyond-local and unpushed, missing its
own named follow-up (no Viewer-side self-heal loader). Rebuilt clean this session: bim-ootb PR #732
ships the habitability filter (Task 1), the Type-toggle COMPILED fallthrough fix (Task 2), and the
HHS buildings/patches/ SQL migration + runtime self-heal loader (§2b) — witness 11/11, pushed with
no LFS stall (corrects §4's over-cautious "no push possible" note). ROOM021_HHS_buildings_extracted_
carry.sql (already committed by §4) cross-validated byte-identical to the new patch's payload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): correct §5 — PR #732 was auto-merge-bot merged, not left open; flag concurrent worktree

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(terminal): root-cause coordinate-frame mismatch + fix deploy DB in place

TERMINAL_COORDINATE_FRAME_MISMATCH.md: bim-ootb's Terminal_ARC.db matches
raw-IFC ground truth (<2cm, verified via ifcopenshell world-bbox-center on
the source .ifc); bim-compiler's deploy/buildings/Terminal_extracted.db was
a carve-out of the multi-building sandbox_1M city demo (extract_per_building.py
reading T0_Terminal_ rows verbatim from build_sandbox_1M.py's tile-placement
output, scripts/build_sandbox_1M.py L216-320) stacked on extractIFCtoDB.py's
S169 centroid-normalize (L1453-1506) — both uncorrected. Delta proven constant
across 12 sampled guids (stdev <1mm): (545.61m, 51.22m, 14.66m).

Fixed deploy/buildings/Terminal_extracted.db (gitignored build artifact, not
committed) in place with the proven-constant offset correction; backed up,
integrity-checked, re-verified against ground truth (<6mm on all axes).

PROGRESS.md: mark item resolved, flag other CBD_BUILDINGS sharing the same
carve-out path as unverified for the same bug class.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): ROOM_INJECTION_HYBRID.md §9 — Room Lens volume-box fix shipped, OCI upload block lifted

Room_guid multi-rect grouping ported into viewer/navigate_find.js's _allRoomVolumes()/
_roomLensOn() (bim-ootb PR #733), witnessed 8/8 (rendered box footprint-area SUM = spatial_
structure's own rect-union area SUM, diff=0.000m2) with zero regression to the existing
habitability-filter witness (11/11). Closes the standing OCI room-data upload blocker.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): harden DB/migration-script rule, PR-merge authority, room-template strategy specs

- CLAUDE.md: DB changes are permanently migration-script+self-heal-loader, not an LFS workaround —
  stop citing LFS as the blocker for DB fixes.
- prompts/MANAGER.md: PR merge is standing Manager scope once independently verified, don't kick
  back an already-answerable merge decision.
- VIEWER_FIND_PANEL_ROOM_ACCURACY.md / UBBL_RULES_GATE.md: MANAGER assignment markers + doc-trail
  corrections from today's dispatched work.
- ROOM_TYPE_TEMPLATE_CLASSIFIER.md: new spec, room-type classification via size/aspect-ratio
  template mined from Duplex's real object_type ground truth, repeat-confirmation methodology.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): push-pause standing mode + Room Intelligence execution plan

CLAUDE.md: local/localhost-only until a named breakthrough, hardened per user directive.
MANAGER.md: synthesized today's strategy discussion into a concrete execution plan —
the competitive bet, what's shipped, what's mid-flight, named next axes (grid, door-access,
disqualifiers, Outliner flywheel).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): §ROOM-TYPE — size+aspect-ratio template classifier, measured from Duplex+SampleHouse

Adds config/room_templates.yaml (7 promoted templates, confidence:measured, N=2-5 each, fit from
Duplex's + SampleHouse's real object_type room labels — the only 2 shipped buildings with genuine
human-authored room-type ground truth) + build/room_type_classifier.js (probabilistic Gaussian
scorer, refuse-to-classify below a z-threshold, §MULTI-RECT-aware area/aspect from a rect-set) +
build/witness_room_type_classifier.js (W-ROOM-TYPE, run over all 8 shipped buildings' compiled
spatial_structure rows, 3/3 checks PASS).

Held-out inference on the other 6 buildings' synthetic COMPILED rooms: 378/602 (62.8%) honestly
unclassified — expected, not a shortfall, per prompts/ROOM_TYPE_TEMPLATE_CLASSIFIER.md's own
discipline against unearned confidence. No `confidence: prior` templates added — the only in-repo
external room-size numbers are the already-flagged-uncorroborated UBBL landmine values (3
conflicting numbers across config/profiles/malaysian_residential.yaml and config/spacetypes.yaml);
reusing them here would be a 4th, so they were deliberately left out.

Scope: config + classifier + witness only, per prompts/ROOM_TYPE_TEMPLATE_CLASSIFIER.md. Modeller
Outliner wiring + user-correction flywheel (Step 4) is a named, separate follow-up, not started.

Local-only commit per coordinator directive (batch-verify before pushing more today) — not pushed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): §DOOR-ACCESS — door-count second signal for room-type classifier

Adds door-count/adjacency as a second discriminating signal alongside the
existing size+aspect-ratio Gaussian scorer (ROOM_TYPE_TEMPLATE_CLASSIFIER.md
follow-up, ROOM_TYPE_DOOR_ACCESS_SIGNAL.md).

- build/room_type_classifier.js: countAdjacentDoors() reuses compile_rooms.py's
  own _door_adjacent() buffer test (extended boolean->count, same
  DOOR_BUFFER_SLACK=0.20m constant); scoreTemplate() gains an optional 3rd
  quadrature dimension, backward-compatible when doorCount isn't supplied.
- build/measure_door_counts.js: measures door_count per room type from
  Duplex+SampleHouse real labeled ground truth (same 2-building anchor, same
  >=2-occurrence promotion bar as area/aspect).
- config/room_templates.yaml: all 7 promoted templates carry a measured
  door_count band; KITCHEN=0 (genuine open-plan finding) and UTILITY's
  buffer-noise caveat both documented honestly.
- build/witness_room_type_classifier.js: computes real door counts across all
  8 buildings, logs every classification the signal flips either way.

Honest witness result (logs/witness_room_type_classifier_door_access_*.log,
4/4 checks pass): 3 genuine real-data wins (2 HALLWAY->KITCHEN corrections on
doorless rooms, 1 false HALLWAY match on SampleHouse's Entrance Hall
correctly refused) but a net regression if blended unconditionally at today's
n=2..5 fitting scale (held-out unclassified 62.8%->84.2%) — reported plainly,
not oversold. classifyRoom() stays backward-compatible: door_count only
applies when a caller opts in by supplying features.doorCount.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): §DOOR-ACCESS — cross-check against the parent task's named miss case

SampleHouse's real Bedroom (the specific example that motivated this task) still
misclassifies as LIVING_ROOM with door_count added — confidence only nudges 75.1%->70.6%.
Confirms the net-regression finding rather than contradicting it.

* docs(manager): self-dispatch reinforcement, note peer-session cross-verification pattern

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): §PRIMARY-VS-SUPPLEMENTARY tier + BOM wiring to required_spaces

Follow-up to ROOM_TYPE_TEMPLATE_CLASSIFIER.md's "dwelling set" and "bigger
reframing" notes.

1. config/room_templates.yaml: every promoted template gets a
   tier: primary|supplementary field. HALLWAY/FOYER = supplementary
   (measured: highest door_count of all 7 templates, most elongated
   aspect_ratio — real circulation signature). BEDROOM/BATHROOM/KITCHEN/
   LIVING_ROOM = primary. UTILITY (not named by the coordinator) decided via
   the same measured-signal discipline: compact aspect_ratio wins the
   tie-break over its already-flagged-unreliable door_count band.

2. build/check_required_spaces.js: feeds the classifier's PRIMARY-tier room
   counts into config/profiles/malaysian_residential.yaml's dormant
   required_spaces BOM recipe. Reuses the count-vs-minCount-shortfall shape
   already present in DAGCompiler's ProtocolValidatorRegistry.java (different
   data source, same pattern) rather than inventing a new validation style.
   Splits Duplex into its two real dwelling units (A101.."A/B" name prefix,
   a real naming convention in the source IFC) so a per-unit shortfall can't
   hide inside a combined-building total.

Witness (logs/check_required_spaces_202607110959.log, 2/2 mechanism checks
pass): Duplex units A and B each genuinely satisfy required_spaces (2
bedroom/2 bathroom/1 kitchen/1 living each, matching the coordinator's own
expectation, checked for real not assumed). SampleHouse genuinely does NOT
satisfy it — honestly explained, not a classifier bug: its extraction only
carries 3 real labeled rooms total (no real Kitchen/Bathroom label exists to
classify in the first place).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): DISC-walk room-type-awareness + corridor pathway routing specs, dispatched

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): harden abstract/mathematical discipline for room-intelligence lane

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(competitive): prior-art analysis with verified citations

Real web-searched, author-verified references — not training-data recall. Corrected one
overclaim (Revit has no native room classification, but third-party ML plugins do exist).
Found a near-exact academic prior-art match (Buruzs et al 2022, Energies) covering both
today's room-type classifier and room-adjacency graph in one published pipeline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): measure discipline x room-type MEP density on real Duplex data

prompts/DISC_WALK_ROOM_TYPE_AWARE.md: build/measure_disc_room_type_density.js measures real
element density per discipline x classified room-type on the only substrate with both real space
geometry+labels and real MEP fixtures (Duplex — Terminal has 0 real IfcSpace rows, refused as a
substrate). Found real replicated signal for PLB (BATHROOM/UTILITY) and FP (FOYER); no signal for
ELEC (present everywhere) or ACMV (0 real elements). Corridor/supplementary tier explicitly checked
against both. Full table + wiring into bim-ootb disc_walker.js recorded in the prompt doc.

Not pushed (session-wide PUSH PAUSE discipline extended here out of caution; only these two files
staged, other pre-existing working-tree changes left untouched).

* docs(prompts): §7 room-to-room adjacency graph + pathfinding — DONE, witnessed

Records the bim-ootb feat/room-pathfind-graph work (common/room_graph.js, Find panel Room
axis "Path" sub-mode): real door-adjacency graph, Dijkstra pathfinding, hub/leaf pattern
confirmed on real Duplex data (Hallway/Foyer avg degree 2.50 vs Bedroom/Bathroom/Utility
avg 1.20), door-guid-continuity-verified path witness (15/15 node-side + 13/13 browser),
honest disconnected-room reporting. PUSH PAUSE in effect — local commit only, not pushed.

* docs(manager): session closeout — scoreboard doc, flag-on-the-hill mission, standing rules

- New prompts/ROOM_INTELLIGENCE_SCOREBOARD.md: standard scored-table reporting format
  (13-feature verdict table + 8-building coverage table), confirmed by user as the
  expected baseline going forward. Includes the HHS-corridor scale-mismatch finding
  (79 unclassified INTERNAL_DOORPART rooms, several corridor-shaped up to aspect 37:1 —
  real circulation the residential-trained classifier can't yet see).
- MANAGER.md: added the FLAG ON THE HILL section — next session's named mission (expand
  the room/space taxonomy to all building parts: stairways, air wells, ventilation, lift
  shafts, plant rooms — so Find panel, Modeller Outliner, and DISC Walker are all complete).
  Added STANDING RULES (localhost-verify, local-commits-only, migration-script-DB-policy)
  and KEY DOCUMENTS navigation section linking every doc from this session.
- PROGRESS.md: compacted the Room Intelligence block to a scoreboard pointer (was ~70 lines
  of now-superseded detail), added the push-pause status line.
- project_room_intelligence_lane.md memory: was referenced but never created — fixed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): trim redundant UBBL detail, point to scoreboard

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* chore: commit regen artifacts left uncommitted from prior session

build/duplex_rules.db — rule_placement table (16 rows) from
measure_disc_room_type_density.js, companion binary to 680e673ee
(DISC_WALK_ROOM_TYPE_AWARE.md, scoreboard item 12) which only staged the
script+spec, not the regenerated DB.

deploy/dev/navigate_find.js — restores explicit position:fixed+display:none
on #find-panel (self-contained fallback, was dropped in ae1cd738b when the
panel started inheriting from .bim-panel) — same fix as scoreboard item 1
(Find-panel visibility, bim-ootb PR #728), applied to this repo's copy.

* feat(migration): W024 component_dimension_range — Q1 LOD touch-up aggregation

Adds GROUP BY type_id aggregation over component_definitions.local_min/max,
persisting per-class min/max (34 classes, 23887 instances covered). Raw
instance rows already existed (e.g. 129 IfcDoor rows spanning 0.147-1.86m
local width) — only the aggregate was missing, per PARAMETRIC_DEPTH_RECON_FINDINGS.md Q1.

migration/W024_component_dimension_range.sql is the durable append-only record
(per Sacred Files policy — library/*.db is regenerated from migrations, never
committed directly). tools/aggregate_component_dimension_range.py runs the same
SQL directly for local dev/witness convenience and prints the §Q1_AGG evidence.

Witness: §Q1_AGG type=IfcDoor count=129 minWidth=0.147194 maxWidth=1.860000,
§Q1_AGG_CHECK aggCount=129 rawCount=129 expected=129 match=True.

* feat(rooms): §BUILDING-PARTS-TAXONOMY — stairway/lift-shaft/plant-room checklist, first ratchet on FLAG ON THE HILL

Implements prompts/MANAGER.md §🚩 THE FLAG ON THE HILL per the user's own framing: a taxonomy
checklist config walked top-down (does this building-class have every expected part) or bottom-up
(look up each real entity against the same table) — same data, both directions.

config/building_taxonomy.yaml generalizes the existing required_spaces/check_required_spaces.js
BOM-shape (count-vs-minCount, ported from ProtocolValidatorRegistry.java) from habitable-room-types
only to any building part, sourced from whichever signal is real: direct IfcStair/IfcStairFlight
entity query for STAIRWAY, the existing NON_ROOM_DOOR_NAMES lift-keyword list (widened scope, not
re-derived) for LIFT_SHAFT, MEP-keyword density for PLANT_ROOM (Terminal-only, n=1, advisory).

STORAGE and AIR_LIGHT_WELL are deliberately absent — zero real evidence found in any of the 8
shipped buildings (see prompts/BUILDING_PARTS_TAXONOMY.md's recon table) — explicit refusal, not an
invented category.

Found and documented a real data-shape issue while building the witness (§PARENT-NO-TRANSFORM):
assembly parents (IfcStair) often carry no transform of their own, only their IfcStairFlight
children do — a transform-requiring join silently undercounts (Duplex 4 real entities -> 2
positionable, Hospital 60 -> 30). extractParts() now reports both .all (existence) and .positioned
(markerable) counts. Also corrected the initial recon agent's exploratory PLANT_ROOM tally
(117/"Aras 01 R3" 22/117) against this module's own reproducible query (74/"Aras Tanah R11" 10/74)
— the reproducible number is treated as authoritative, per this project's non-invent discipline.

Witness: W-BUILDING-PARTS 13/13 PASS, re-run against all 8 real *_ARC.db files.

Not pushed — session-wide PUSH PAUSE (CLAUDE.md §⏸).

* docs(scoreboard): fold building-parts-taxonomy data into the coverage table

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): SPARSE_WALL_ROOM_INFERENCE.md — the real-world-IFC challenge, dispatched

Phase 0 (data health guard, external idea corrected against real schema+thresholds) +
Phase 1 (signal-fusion inference: grid/door/slab/envelope) to recover room structure when
flood-fill's wall data is genuinely too sparse, per HHS's root-caused 1.06 walls/room finding.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): cross-reference SPARSE_WALL_ROOM_INFERENCE root-cause into taxonomy scoreboard

HHS's Stairway=0 (building_parts_taxonomy) and its wall-flood-fill failure (sparse-wall inference
thread) share one root cause: zero IfcStair/IfcRamp entities + 1.06 walls/room in HHS's federated
IFC — confirmed absence in source data, not an extraction gap on either thread's side. Also logs
the parallel thread in PROGRESS.md's juggled list so it isn't silently lost track of.

* feat(rooms): §PHASE0-HEALTH — Data Health Guard, wall/door + STR-fingerprint + circulation flags

Pre-flood-fill sparsity check per SPARSE_WALL_ROOM_INFERENCE.md Phase 0. Real-schema queries
(elements_meta.ifc_class/discipline, verified live). Thresholds derived from Hospital/Clinic/HHS's
own measured wall/door ratios and STR-discipline shares, not asserted round numbers. Uses wall/DOOR
ratio (not wall/space) since IfcSpace is absent from all 3 raw extracts (0 rows, confirmed) — using
flood-fill's own output as denominator would be circular and provably unstable (HHS's room count
moved from failing to 71 honest rooms via a same-day unrelated commit, §WALL-VERT 7133bbe06).

Witnessed: Hospital OK (3.27 ratio, 4.5% STR), Clinic OK (4.25 ratio, 10.1% STR), HHS FLAGGED
(1.20 ratio < 2.235 threshold, 24.8% STR > 17.4% threshold) — zero regression on wall-rich
buildings, correct flag on the sparse one. Guard informs only, never blocks — flood-fill still
runs on every building regardless of flag state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): Find-panel Parts axis landed (bim-ootb d04ddd5), MANAGER-verified

Independently checked the dispatched worker's diff (not just its report) and one real
discrepancy (Duplex Stairway=2 vs this repo's witness=4): confirmed a genuine DB-variant
divergence (bim-ootb's served Duplex_extracted.db lacks the parent IfcStair rows that
Duplex_ARC.db has), not a bug in the ported query. Documented so it isn't mistaken for a
regression later. Scoreboard row 15 bumped 7->8; Outliner wiring (the other VISION-LOCK
sentence-5 half) still open.

* docs(rooms): SPARSE_WALL_ROOM_INFERENCE checkpoint — Phase 0 done+witnessed, Phase 1 scoped as follow-up

Records: two stale premises found on re-verification (HHS no longer 105/105 DOORPART — a same-day
unrelated commit §WALL-VERT already fixed it via curtain-wall glazing evidence; HHS does have real
stair data, 20 rows, not zero as originally diagnosed). Phase 0 witness numbers, threshold
derivations, and a concrete 4-step Phase 1 follow-up spec for a fresh session to pick up cleanly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): correct HHS Stairway=0 — DB-snapshot divergence, not real absence (2nd confirmed instance, memory saved)

* docs(progress): log Outliner wiring dispatch (Building Parts Taxonomy → Modeller)

* docs(rooms): Modeller Outliner wiring landed (bim-ootb f10c5295), MANAGER-verified — both VISION-LOCK sentence-5 UI halves done

Independently checked the diff: new modeller/building_parts_outliner.js mirrors the existing
dw_instances_outliner.js extension-seam pattern correctly, bonsai_outliner.js untouched, real
leaf-id bug caught+fixed during verification (compound id broke the existing click-to-frame path).
Third Duplex Stairway data point (4, matching bim-compiler's own witness) narrows the earlier
DB-divergence finding to the Viewer's specific served copy being the outlier, not a universal
disagreement. Scoreboard row 15 bumped 8->9.

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — spec for a fresh Sonnet session

User's own live review of today's Modeller work: LOD confirmed no longer bad, but material
rendering still wrong (glass walls/windows not see-through, unlike the Viewer). Blocks adding
today's Building Parts Outliner screenshot to docs/ModellerGuide.md — "not fitting for the guide."
Also folds in a named UI quirk (Outliner panel collapse control not discoverable) per user request,
tracked rather than dropped. Delegated as a written spec, not fire-fought reactively mid-session.

* docs(manager): harden anti-ad-hoc-debugging conduct rule + write the missing Viewer-side spec

User caught it live twice in one session: material-parity got a proper prompts/# after the first
correction, but the Find-panel screenshot chase (3 failed attempts to find the panel-open
mechanism) was still ad-hoc debugging inline in the MANAGER turn, not delegated. Hardened
prompts/MANAGER.md with the rule (stop after a second failed quick-check, write the spec instead
of continuing to guess) and wrote prompts/VIEWER_FIND_PANEL_PARTS_VERIFICATION.md so a dispatched
session picks this up with the 3 known dead-ends already named, not repeated.

* docs(progress): session closeout — compact juggled-list, close building-parts+disc-walk threads, note guide-blocker specs

* docs(rooms): READ FIRST anti-drift pointer — taxonomy is CLOSED, don't re-open without new cause

* docs(prompts): VIEWER_FIND_PANEL_PARTS_VERIFICATION.md RESULT — panel-open blocker solved + real bug found

Root cause of MANAGER's 3 failed guesses: window.A never existed, A is a local closure
parameter aliasing window.APP. window.APP.openFindPanel('') works; so does the real-user
path (press 'f', per scene.js's own keyboard shortcut). Live-driven evidence captured
(2 screenshots, §-tagged console logs) confirming the Parts axis renders real Stairway(4)/
Plant Room(6) counts on Duplex from a fresh page load.

Byproduct finding, not fixed (out of this file's verification-only scope): PLANT_KEYWORDS'
bare 'vent' substring match false-positives on "Backflow Preventer" (4 of 6 Duplex "Plant
Room" hits are false positives) and the live Parts axis has no class gate, unlike
checklistReport()'s class-gated report. Also a 4th confirmed instance of the DB-snapshot
divergence landmine (root buildings/Duplex_extracted.db vs the actually-served
viewer/buildings/Duplex_extracted.db disagree on Stairway count, 2 vs 4).

PUSH PAUSE in effect — commit local-only, no push, no PR.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — Task 1+2 findings, both DONE

bim-ootb fix/modeller-render-material-parity @ 2fc3964 (local, unpushed —
push pause in effect): glass/window transparency threaded through from
elements_meta.material_rgba alpha (mirrors viewer/streaming.js's own
opacity gate), and the Outliner collapse button's discoverability fixed
(was functionally correct, just zero visual weight at rest). Both verified
in real headless Chrome against the real Duplex resident, no regressions
in existing suites. Guide unblocked.

* docs(viewer): add Find panel section to BIMUserGuide.md

Cherry-picked from agent worktree (40d0c2444) to consolidate onto this
branch. Documents the Find panel's open path, search/voice query box,
and all six axes incl. the new Parts axis. Screenshot placeholders only
(img/viewer/*.png), no images captured yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): scoreboard — file PLANT_KEYWORDS false-positive + missing class-gate finding

From VIEWER_FIND_PANEL_PARTS_VERIFICATION.md's byproduct bug (found, not fixed there).
Row 15 now names both the substring-collision fix and the live-query class-gate fix
so they aren't lost before the follow-up session picks them up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): FIND_PANEL_PLANT_ROOM_GATE_FIX.md — spec the 2 named Find-panel bugs

Bounded follow-up to VIEWER_FIND_PANEL_PARTS_VERIFICATION.md's byproduct findings
(substring false-positive + missing class-gate), ready to dispatch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — PR #735 merged, localhost-gap root cause logged

Session's own working file, not memory, per user's steer this turn.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — deployment landmine + collapse-all button + Find-panel-highlight proposal

Follow-up to the earlier findings entry: the fix wasn't reaching the
user's actual test server (worktree vs shared checkout + stale SW
precache, both now fixed and merged into ~/bim-ootb). Added a real
Collapse All button. Documented 3 ranked options for the open "click a
higher-level row to highlight the section" question — not yet
implemented, needs user's pick given a real collision risk with the
existing disc-walk-on-click wiring.

* docs(manager): scope narrowed — user guides + git/localhost admin only

Lane sessions now self-review and administer their own follow-up prompts.
User's own words captured verbatim so this doesn't drift back silently.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — option 1 shipped + verified live

Documents the select-then-collapse conflict found and resolved (auto-
expand-on-pick vs manual collapse-toggle, can't coexist on one click),
the final select-only design, and live verification against the user's
actual port-8080 server.

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — scope for Fable, corrects stale marathon framing

Investigated "the DiscWalk task" per user request. Found the 2026-07-10
marathon memory's framing is stale: the Z-datum bug it called "the actual
next real gap" is fully done and merged in BOTH repos (bim-compiler PR
#40, bim-ootb PR #726 squash 3d09ad6 — confirmed already an ancestor of
local main, correcting PROGRESS.md's "open, not merged" note) — as is
fix/dw-rot-units (PR #723). Only 3 small, already-verified, no-conflict
branches remain genuinely unmerged (PRs #722/#724/#725), plus one real
open question: the guide-screenshot camera bug from the same marathon,
never diagnosed. Scoped a Fable session: re-verify the 3 branches fresh
(no merge/push — Sonnet reviews before any of that), then chase the
screenshot bug's root cause. Named the stale-radians migration question
as explicitly out of scope (separate, harder design task).

* fix(rooms): word-boundary keyword match for PLANT_KEYWORDS/LIFT_KEYWORDS

prompts/FIND_PANEL_PLANT_ROOM_GATE_FIX.md Bug 1 (bim-ootb port ported byte-identical
to viewer/navigate_find.js + modeller/building_parts_outliner.js, same session).

build/building_parts_taxonomy.js's checklistReport() already class-gated PLANT_ROOM
correctly via config/building_taxonomy.yaml (Bug 2 doesn't apply here) — only the
bare LIKE '%vent%' substring match needed fixing. Real-data-driven: surveyed 59
distinct element_name templates across 5 buildings before picking the fix (token
split on delimiters + camelCase, keyword-as-token-prefix match).

Verified: Clinic 1890->1881 (9 "Backflow Preventer" false positives dropped, all
real duct/fan/pump/chiller/vent rows kept). Terminal 74->74 unchanged (no
true-positive regression). witness_building_parts_taxonomy.js 13/13 PASS, unchanged.

PUSH PAUSE stands in this repo per CLAUDE.md standing directive — local commit only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(viewer,modeller): real screenshots for Find panel + new Building Parts/glass section

Cherry-picked from agent worktree (a77fcc2b0). Replaces the 5 Find-panel placeholders
with real Playwright captures off bim-ootb main (f0f0994), corrects two prose details
the source-only draft got wrong (search placeholder text, Navigate drawer row name).
Adds ModellerGuide.md coverage for Building Parts Outliner + glass transparency, both
previously undocumented. Two new findings flagged in-doc: NL-query hint never renders
live (CSS gating bug), Parts axis Plant Room false-positive (tracked in
FIND_PANEL_PLANT_ROOM_GATE_FIX.md, not duplicated here).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — verification worktrees already built, only the witness re-run + report remain

Found /tmp/wt-verify-{grid-tilt,oracle,dwprobe} already exist with the
target branches merged into fresh checkouts off current main (dwprobe hit
a real conflict since my last check, resolved KEEP-BOTH). None have a
logged witness re-run yet — that's the only remaining step before a
Manager-scoped session can make the merge call. Noted so the next
dispatch doesn't redo the merge work.

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — 2026-07-11 findings appended (3 PRs re-verified, guide-shot bug diagnosed+fixed)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — Manager verification result, 2 merged 1 held

#722 and #725 (as #741) merged after fresh re-verification. #724 held — real regression
in the KEEP-BOTH conflict resolution (SampleCastle MEP disc node now absent from UI,
was 8/8 historically, now 6/8), needs a fix, not Manager's to patch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): Sonnet verification clears #724 (not a regression) + dispatch WITNESS_SAMPLECASTLE_MEP_STALE.md

Independently verified Manager's flagged "regression" on fable/dwprobe-dedup
(#724): ran witness_modeller_disc_walk.js directly against pristine
origin/main (9b62c4f, zero relation to the branch) and reproduced the
IDENTICAL B5/B6 failure. Conclusive — the branch/merge isn't the cause.
Root cause: SampleCastle_ARC.db is ARC-only (0 MEP rows, confirmed via
direct SQL), a data-vs-witness staleness, not a code regression. #724
is clear to merge on the same terms as #722/#725. Scoped the actual fix
(retarget or honestly skip B5/B6, fix the uncaught-rejection crash path)
as its own small follow-up rather than blocking the branch verification
task on it.

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — correct #724 verdict, merged

My earlier "real regression" call was wrong — independently re-verified Sonnet 1's
counter-finding (pristine main reproduces the same failure, unrelated to the branch)
before merging. Root cause was stale SampleCastle_ARC.db data, not the KEEP-BOTH merge.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): WITNESS_SAMPLECASTLE_MEP_STALE — findings appended, B5/B6 retargeted to Clinic, 8/8 green (local-only per push pause)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(viewer): swap Parts-axis screenshot to HHS (real institutional data, post-fix)

The Duplex screenshot predated bim-ootb PR #740/#742 (word-boundary + class-gate
fix) and showed the pre-fix false-positive behavior. Replaced with a real capture
on HHS Office (complex-class): Stairway(20), Lift Shaft(3), Plant Room(1769) all
visible at once, and updated the caveat note now that the fix is landed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): DISCWALK_PLANT_ROOM_INDUSTRIAL_TAXONOMY.md — Fable-scoped next mission

DiscWalk-strengthening + Plant Room industrial taxonomy expansion, next step on
MANAGER.md's own "Flag on the Hill" mission. Grounded in live HHS Find-panel
verification this session (real 1769-match Plant Room evidence, class-checked
not just LIKE-counted). Terminal named explicitly as the calibration anchor
(real professional project, not public-sourced like the other buildings).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): WALKER_FIXTURE_RENDER_MATERIAL_AND_GEOMETRY_CHECK.md — investigation only

User spotted geometry chaos + no material/LOD400 on the live ModellerGuide's
walker-fixtures screenshot. Traced to _renderDiscWalk in modeller.html (confirmed
a separate, flat disc-tinted material path from today's ARC-seed glass fix, and
confirmed placement x/y/z comes straight from disc_walker.js with no clamping in
the renderer) before writing the spec, so the dispatched session isn't starting
from a guess. Explicitly investigation-only, gates whether this is a render bug,
a disc_walker placement-data defect, or a screenshot fr…
red1oon added a commit that referenced this pull request Jul 12, 2026
… raster (#43)

* docs: correct guide-screenshot verdict — reattempt succeeded

* docs: add prompts/MANAGER.md — cross-session review/admin role

* docs(disc_walker): ROOM_INJECTION_HYBRID hardened for Fable handoff — Modeller-only scope

Renumber WalkerDoctrine.md's duplicate §13 to §14 (rooms rule) and fix the citation.
Drop the dead SAMPLECASTLE_REAL_ROOMS_RECONCILE.md anchor (lives only on an unmerged
branch, not this one). Reframe the Viewer Find Panel Room Lens reference as a one-way,
read-only borrow-from source for the Modeller's ARC-import step, name its unfiltered
query as a live false positive, and explicitly scope Task 5 to Modeller-only — no
Viewer files touched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): anchor THE GOAL to VISION-LOCK — "working" was undefined

MANAGER.md said "get the actual thing working" without citing what working means,
letting review verdicts drift toward generic pass/fail instead of the actual product
bar. Point at RESUME_GRAPH_MODELLER_INTEGRATION.md §VISION-LOCK's five sentences.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): correct §2 — Terminal's 43 rooms are synthetic, not real

Direct query (object_type=COMPILED, ≈-named) proves Terminal has zero real IfcSpace
rooms — the doc previously miscounted them as "real rooms already baked in." Same
correction applied to HHS's 14 rows (already caught by Task 5 but §2's table hadn't
been updated to match). Adds the full 8-building room-count table: only Duplex has
real, habitability-filtered data, and it isn't merged to main yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §2 — source-IFC check finds SampleHouse extraction bug

Direct grep of internal/sources/Ifc4_SampleHouse.ifc finds 4 real IFCSPACE entities
(Living room, Bedroom, Entrance hall, Roof) that never made it into the shipped
SampleHouse_ARC.db (0 rooms) — an extraction gap, not a source-data gap as previously
assumed. Clinic/Garage/Hospital/HHS have no source IFC in this checkout to check
either way, so their "0 rooms" state is unverified, not confirmed-no-data.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add Task 6 (SampleHouse extraction bug), reassign forward work to Sonnet

Task 6: 3 usable real rooms exist in SampleHouse's source IFC but never reached the
shipped ARC — an extraction bug, not a data gap. Per user directive, all further work
on this doc goes to Sonnet, not Fable, from here on; Tasks 1+5's Fable history is left
as an accurate record, not rewritten.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(compile_rooms): §DOOR-RESCUE — recover real small rooms (toilets/utility) below MIN_AREA

User-flagged, verified before fixing: HHS ("large U-shape office block, lots of office rooms
with doors") only compiled 2 rooms; restrooms/utility rooms were being missed across every
building, not just HHS. Instrumented the flood-fill to log ALL candidate pockets (not just
accepted ones) — confirmed this was NOT a mis-tuned MIN_AREA=4.0 threshold hiding rooms that
were actually detected: most sub-threshold pockets are <1.0 m^2 wall-joint/cavity artefacts
(noise), but a real population of 1.0-4.0 m^2 pockets IS a genuine small room (restroom/closet/
riser) wrongly dropped by the same blanket cutoff.

The user's hint ("rooms has doors" / "look for clues that define a toilet, utility that house
MEP") pointed at the fix: MEP fixture data isn't reliable (ARC-only discipline strip already
removed sanitary/plumbing elements from 4 of 5 buildings), but door adjacency is a real,
non-invented structural signal already in every ARC.db — a genuine small room a person uses
always has a door; a wall cavity never does. Measured before shipping: for HHS/Clinic/Hospital/
SampleCastle, pockets <1.0 m^2 are rarely door-adjacent (noise); pockets in [1.0, 4.0) m^2 are
door-adjacent in the large majority (real small rooms) — the two size bands are different
populations, not an arbitrary split.

- storey_doors() + _door_adjacent(): per-storey real IfcDoor centres, 1.0m buffer.
- flood_rooms(): a pocket in [DOOR_RESCUE_MIN_AREA=1.0, MIN_AREA=4.0) m^2 is now accepted iff
  door-adjacent; still-tagged ≈/RM_/COMPILED (spacesOf()'s placement-exclusion untouched) but
  predefined_type='INTERNAL_SMALL' (vs 'INTERNAL') for traceability of which path found it.
- Re-ran --write on the 5 gap buildings: HHS 2→5, Clinic 113→190, Hospital 142→213,
  SampleCastle 25→47, Garage unchanged (0 door-adjacent small pockets found).
- W-ROOM-INJECT-ALL8 rerun 32/32 on bim-ootb worktree: placement-eligibility still 0 for every
  synthetic-only building — door-rescued rooms are exactly as display-only as any other
  compiled room, never reach schedule placement.

Doc: prompts/Modeller/DISC_Walker/ROOM_INJECTION_HYBRID.md updated with the finding + fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): DB Storage Policy — stop new .db commits, GitHub LFS bandwidth cap hit

GitHub flagged 10GB/month LFS bandwidth usage. 59+ .db files already LFS-tracked
(deploy/buildings/*, build/*.db) burn quota on every clone/fetch. Going forward:
schema/rules DBs regenerate via migration/*.sql or their mining scripts; extracted/
derived building DBs distribute via OCI (already the dev/live channel), not git.
Existing LFS-tracked files are left alone — this only stops new commits.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(compile_rooms): replace fitted door-rescue band with an abstract rule

User pushback (correct): the previous §DOOR-RESCUE fix used DOOR_RESCUE_MIN_AREA=1.0 and a flat
1.0m buffer picked by eyeballing HHS/Clinic/Hospital's specific data — a fitted band, not a rule.
This generalizes it:

- The room definition is now architectural, not size-banded: an enclosed pocket is a room if it
  is big enough on its own (area >= MIN_AREA, unchanged) OR it has a real door AND isn't a bare
  rasterization sliver. No area number stands between "noise" and "small room" anymore.
- Door adjacency buffer is now each door's OWN extracted footprint (half its real leaf/frame
  span) + one grid cell of slack (RES) -- self-scaling to whatever doors a building actually has,
  not a fixed metre guess that happened to work on 5 sample buildings.
- The noise floor is NOISE_FLOOR_DIM = 3*RES (0.6m) -- a pocket narrower than a few grid cells in
  EITHER axis is rasterization noise by construction, a property of the flood-fill's own
  resolution, not an area threshold reverse-engineered from observed rooms.

Re-verified: HHS 6, Clinic 195, Hospital 201, SampleCastle 53, Garage 5 (close to, not identical
to, the earlier fitted-band numbers -- expected, since the rule is now geometry-derived rather
than tuned to match them). W-ROOM-INJECT-ALL8 rerun 32/32 on bim-ootb worktree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record both door-rescue passes — fitted band superseded by abstract rule

* fix(compile_rooms): §DOOR-NOT-ROOM — lift/elevator doors aren't room evidence

Tested SEAL=1 (narrower wall-dilation) to try to recover HHS's WC-stall spaces the user found
named in German ("WC Trennwand") — rejected: doesn't fix HHS (the WC block's OWN enclosing walls,
not just its internal stall partitions, are simply absent from this extraction, a resolution/
data-completeness issue SEAL can't touch) AND it fragments real rooms elsewhere into spurious
1-2 sq.m splinters in Hospital (142->253, mostly noise) and SampleCastle -- a regression, not an
improvement. Reverted to SEAL=2 (already-shipped, verified value unchanged).

Separately, user asked whether doors have standard dimensions we could use as a smell test.
Checked: real hinged doors cluster 0.7-1.1m (single leaf) / 1.2-2.7m (double leaf/wide entrance)
across all 5 buildings' door data -- consistent, no anomaly, EXCEPT SampleCastle: 28 IfcDoor rows
at 0.5m width, all named 'liftdeur' (Dutch: elevator door). Real, correctly-classified doors --
but they lead to a lift shaft, not a room, and 2 of them were rescuing actual elevator-shaft
fragments as fake compiled "rooms" (verified directly: room count with vs without lift doors as
the door-rescue signal differs). Same shape of problem as the existing §STAIR-EXCLUDE pattern --
excluded via a maintained, multi-language door-name keyword list (liftdeur/lift/elevator/aufzug/
fahrstuhl/hoist), not a width cutoff (a lift door's width isn't reliably distinct from a narrow
single-leaf door's).

SampleCastle 53->51 (the 2 lift-shaft fakes removed); HHS/Clinic/Hospital/Garage unchanged (no
lift doors in their door-rescue signal). W-ROOM-INJECT-ALL8 rerun 32/32.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record SEAL=1 rejection + lift-door exclusion passes, HHS WC gap flagged open

* feat(compile_rooms): §DOOR-PARTITION — every door leads to a room, even where walls can't

User's repeated, correct point: HHS has 43/39/34 real doors across 3 floors (verified directly,
German-named "Türelement... Drehflügel" = swing-door elements) -- "each door must be to a room."
Flood-fill (even with §DOOR-RESCUE) only ever found 4/2/0 rooms on those floors because HHS's
extraction is missing the walls that would divide the floor into individual offices at all (91%+
of each floor floods as one exterior-reachable blob) -- door-rescue only widens acceptance for
pockets flood-fill ALREADY finds enclosed; it can't help where nothing is enclosed to begin with.

New technique for where wall-enclosure structurally cannot work: partition the storey's free space
by NEAREST DOOR (multi-source BFS through real free cells, real walls still block) -- each door
claims whatever space no other door reaches first, exactly the "every door leads to a room"
principle stated directly, not an area/threshold proxy for it.

Gate (measured, not fitted per-building): use door-partition only where flood-fill's OWN result
(with door-rescue already applied) finds fewer rooms than DOOR_SHORTFALL_RATIO=0.15 of the
storey's real door count -- HHS's floors find 0-11% of their door count via flood-fill; every
other building's WORKING floors find 20-100%+ of theirs (Garage's sparsest working floor: 5/8=62%;
Hospital's sparsest: 1/5=20%) -- the ratio sits below every failing floor and above every working
one, verified directly so it never overrides an already-functioning result (Garage's 5-room floor
and Hospital's 1-room floor both correctly kept their flood-fill result unchanged).

Result: HHS 6->105 (36/31/29/9 per floor -- in the "tens per floor" range the user predicted from
door counts alone). Clinic/Hospital/Garage/SampleCastle counts unchanged except Clinic's near-empty
'Unknown' storey (0->2, same gate correctly firing there too). predefined_type='INTERNAL_DOORPART'
marks these rows for traceability; object_type='COMPILED' (what tag-purity/placement-exclusion
checks key on) unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): record §DOOR-PARTITION pass — HHS 6→105 rooms

* docs(disc_walker): add VIEWER_FIND_PANEL_ROOM_ACCURACY.md — port habitability+door-partition results to Find Panel

* docs(disc_walker): §TE-ARC-DATUM merged (PR #40) — entry point for bim-ootb port

Records the merge (b202eb44b) and hands off the one remaining task: port
rule_frame_ref mining + walk-time zOff to bim-ootb's own disc_walker.js and
terminal_rules.db — the fix is bim-compiler-only, the actual Modeller app still
has the collapse bug live until this ports over.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): Worktree Hygiene — the other LFS bandwidth drain

Committing DBs wasn't the only cost: 49 bim-ootb worktrees + a duplicate ~/Projects/bim-ootb
clone were each pulling fresh 100-250MB mesh.db/geo.db LFS blobs. Real end users never
touch git LFS at all (they hit the deployed static site) — 100% of the quota was dev-side
worktree churn. Removed the duplicate clone (confirmed clean, 100+ commits stale) and
pruned 25 safe (clean + fully-pushed) stale worktrees in bim-ootb. Protocol: check
`git worktree list` before creating a new one, one clone per repo, prune on sight.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): LFS QUOTA EXHAUSTED — hard block, all-local, no exceptions

GitHub confirmed 0 bandwidth budget remaining, not just approaching the cap. Escalates
the earlier reduce-usage guidance to a hard block: no pushing any commit that touches
LFS-tracked content, no fetching/checking-out branches whose LFS blobs aren't already
locally cached, until the user confirms the quota has reset. Applies to every Agent-tool
prompt that touches git, not just this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add COMPILE_ROOMS_TYPE_INFERENCE.md — room-function guessing where no IfcSpace ever named it

* fix(disc_walker): correct VIEWER_FIND_PANEL_ROOM_ACCURACY.md — right repo, right file, new findings

User caught it: the doc anchored on bim-compiler/deploy/dev/navigate_find.js, which turns out to
be a STALE, unmaintained fork (2859-line diff vs the live copy, no recent commits since this
repo's initial migration). The actual, actively-developed Viewer code is bim-ootb/viewer/
navigate_find.js (3640 lines, commits as recent as pill-drawer/HBA work) -- same repo as Modeller's
disc_walker.js, removing the cross-repo constraint the original doc assumed.

Checked the live code directly and found it's further along than assumed (storey grouping + a
Storey/Type toggle already exist) but also found a new, concrete bug: the Type toggle's
`object_type || predefined_type` fallback never reaches predefined_type for compiled rooms, since
object_type='COMPILED' is always truthy -- masks the INTERNAL/INTERNAL_SMALL/INTERNAL_DOORPART
distinction compile_rooms.py now writes.

Biggest correction: confirmed viewer/import_db_builder.js (the live "drop your own IFC" schema
builder) never creates a spatial_structure table at all -- a user's own imported building gets ZERO
room data today, real or synthetic. Scoped as its own Task 5, separate from the display-only fixes,
since fixing it means porting compile_rooms.py's algorithm from Python to JS (no Python runs in a
browser) -- not a quick win.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): add ROOM_WALKER_JS_PORT.md — retire Python, compute-once via explicit trigger

User's call, this session: since real usage is 100% JS (no server, no Python runtime in the
browser — confirmed for the live IFC-import path), retire compile_rooms.py in favor of one JS
port usable both offline (Node CLI, replacing today's Python bake for the 8 shipped residents) and
in-browser (a new Modeller Outliner "Room Walker" action, parallel to the existing Disc Walker
convention). Explicitly NOT "recompute live on every open" -- user's own point that this costs
real time (HHS's grid alone is ~90k cells/floor) -- compute once, on demand or at import, persist,
same principle as today's offline bake just relocated to whichever moment actually needs it.

5 tasks specced: (1) verify how Disc Walker is actually triggered today before assuming a UI
pattern to copy -- unconfirmed this session; (2) port the algorithm verbatim to a shared JS module;
(3) Node CLI mode replacing compile_rooms.py, witnessed byte-for-byte against this session's Python
counts (SampleHouse 3/Duplex 20/Terminal 43/SampleCastle 51/HHS 105/Clinic 197/Garage 5/Hospital
201) before Python is touched; (4) the browser-mode Room Walker Outliner action; (5) retire
compile_rooms.py once Task 3's parity witness is 100% green.

Cross-referenced from ROOM_INJECTION_HYBRID.md's Task 3 (now has a concrete trigger mechanism
instead of an open-ended display spec) and VIEWER_FIND_PANEL_ROOM_ACCURACY.md's Task 5 (this doc
is its actual breakdown).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(protocol): LFS quota resets 2026-08-01; any push may hang regardless of content

User-confirmed reset date. Also sharpens the finding: a push touching zero LFS-tracked
files still hung 2+ min and never landed (fix/dw-datum-port push attempt) - the git-lfs
pre-push hook appears to probe the endpoint unconditionally. Rule is now "any push may
hang until reset," not just LFS-content pushes. Don't retry a hung push blindly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): anchor to the published ModellerGuide as the tangible external target

VISION-LOCK is the internal engineering bar; the guide site is the user-facing proof
it's met. Notes current known gaps (Terminal datum port stuck behind LFS block,
room-mode data coverage, x-ray bug, 2 live Viewer UI bugs) so a new session doesn't
have to re-derive "how far are we" from scratch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §DW-DATUM bim-ootb port DONE — pushed, PR #726 open

Verified and pushed successfully (earlier push attempt's 2-min hang was transient,
not a hard LFS block - retry succeeded in 25s). Terminal collapse bug heals once
PR #726 merges (user's call).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): sharpen Task 3 — test AND inject into the real showcase ARC.db files, both required

* docs(disc_walker): require the report table (building/count/method/status/total) as Task 3's actual output shape

* docs(progress): session closeout — TE-ARC-DATUM done, room-injection status, LFS quota, 2 Viewer bugs

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(disc_walker): §LIVEWIRE re-verify 2026-07-11 — stale round-1 challenge answered, W-SCHED-MINE 7/7 + W-DX-WALKBACK-RSGT 14/14 clean-room on committed state

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(migration): MDB001 — 26 §LIVEWIRE device-mesh rows as hex-literal SQL, no-LFS channel for stale mesh.db copies (W-MESHDB-RESOLVE 2/5→5/5, byte-identical, idempotent)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(disc_walker): ROOM_INJECTION_HYBRID Task 4 — harden embed-8 pipeline against silent spatial_structure loss

Reframed the task after checking Task 6's own finding: the regression source isn't the
b93ca13 ARC-only strip (already disproven — spatial_structure was unchanged across it),
it's finalize_all_8.js's generic per-building meta-split silently shipping an empty
spatial_structure table whenever its (ephemeral, unpreserved) source lacks one — the
confirmed cause of 7/8 buildings' room-data loss in 6068fab.

Hardened finalize_all_8.js: explicit carrySpatialStructureForward() falls back to the
currently-shipped resident ARC.db when the fresh source has no room data, plus a
regression gate that aborts if carry-forward reported data but the write-time db
disagrees. module.exports + require.main guard added so the logic is unit-witnessable
without the vanished /tmp scratch inputs.

Witness W-SPATIAL-CARRY (9/9) reproduces the exact Duplex/SampleHouse regression shapes
against real data already local in /tmp/wt-fable-livewire (read-only, no LFS fetch).

Re-running the full pipeline against bim-ootb main and pushing regenerated *_ARC.db
files stays LFS-blocked until 2026-08-01 — this commit is the script fix + witness only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(disc_walker): ROOM_INJECTION_HYBRID Task 4 follow-up — SQL migration scripts carry spatial_structure into main, no binary push

Per repo convention (migration/DV_*_rules.sql, CL002_name_value_component_library.sql):
never touch a shipped DB as a binary commit when a deterministic SQL script can carry
the same content. bim-ootb main's 6 residents (SampleHouse/HHS/Clinic/Garage/Hospital/
SampleCastle) still ship 0 spatial_structure rows, and Duplex still carries the
unfiltered Roof row -- both real, verified on the unmerged fable/modeller-lod400-livewire
branch but not on main.

ROOM001-006_*_spatial_structure_carry.sql: full spatial_structure DDL + INSERT rows dumped
straight off livewire's real data (sqlite3 .mode insert, no BLOB columns in this table).
ROOM007_Duplex_strip_roof.sql: single DELETE -- confirmed by direct diff that main's 26
rows differ from livewire's 25 by exactly the R301 Roof row.

witness_room_migration_apply.sh (W-ROOM-MIGRATION-APPLY, 7/7): applies every script to a
scratch copy of main's real *_ARC.db and diffs the FULL resulting table against livewire's
real data -- byte-identical on all 7. Text-only diff, no LFS content touched.

This gets any local main checkout on par with the branch's room data by running
`sqlite3 modeller/{Name}_ARC.db < ROOM00N_*.sql` -- it does not deploy to the live site
(needs an actual DB commit, still LFS-blocked until 2026-08-01).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_INJECTION_HYBRID Task 4 SQL-migration follow-up

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): ROOM_WALKER_JS_PORT Task 1+2 — trace dwWalk trigger, port compile_rooms.py to JS

Task 1: traced dwWalk()'s real call chain (missed by a modeller/*.js-only grep — the actual
call site is in modeller.html's inline script). Confirmed explicit-user-action only (Outliner
discipline-row click -> onWalk callback -> bonsai_outliner.js's single dispatch chokepoint),
never automatic-on-load. No inconsistency to flag — Room Walker can copy this exact convention.

Task 2: build/room_walker.js ports compile_rooms.py's flood-fill/door-rescue/door-partition
algorithm verbatim (every constant + its justifying comment carried over unchanged). Same
db.exec()/_rows() sql.js interface disc_walker.js and finalize_all_8.js already use, so one
implementation genuinely serves both Node and browser -- no dual-implementation split.

Witness W-ROOM-WALKER-PARITY (6/6): runs the real Python and the JS port against separate
scratch copies of the same real building data and diffs the FULL resulting spatial_structure +
rel_contained_in_space content (not just counts) -- byte-identical on SampleCastle/HHS/Clinic/
Garage/Hospital/Terminal, both the door-rescue and door-partition paths exercised.

Surfaced, not silently fixed: Terminal's fresh algorithm run gives 53 rooms, not the 43
currently shipped -- shipped data predates the door-rescue/door-partition refinements. Flagged
as a content decision (BLOCKED), not assumed either way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_WALKER_JS_PORT Tasks 1+2 done, Terminal room-count question flagged

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(disc_walker): ship Terminal's corrected 53-room count via SQL migration, not a binary

User decision 2026-07-11: precision over staleness for display-only data. Terminal's shipped
spatial_structure (43 rooms) predates the door-rescue/door-partition refinements to the
compile-rooms algorithm; re-running today's algorithm (verified byte-identical between
compile_rooms.py and its JS port) gives 53. ROOM008_Terminal_correction_43_to_53.sql applies
the fix via sqlite3, no binary DB commit -- full replace is safe since Terminal's entire
spatial_structure table is synthetic (0 real rows).

witness_room008_terminal_correction.js (W-ROOM008-TERMINAL 4/4): migration-applied result is
byte-identical to room_walker.js computed fresh from the same real source geometry right now,
elements_meta confirmed untouched. This closes ROOM_WALKER_JS_PORT.md Task 3 fully (both bars).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): record ROOM_INJECTION_HYBRID self-heal SQL-patch loader shipped

Ports the Task 4 SQL migrations + MDB001 into bim-ootb modeller/patches/,
wired into str_walker_outliner.js's resident/geoDb open path (W-PATCH-SELFHEAL
43/43) — closes the manual-sqlite3-step gap the prior follow-up left open.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): §W5-RATCHET item 4 — per-room Z offsets mined from real Duplex MEP (11 rows, all guard-allowed families median-exact; M3 two-level verbatim; W5-ZFAM diagnostic; 14/14+7/7)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(disc_walker): ROOM_WALKER_JS_PORT Task 4+5 — wire Rooms Outliner category, retire compile_rooms.py from room-injection duty

Task 4 (browser wiring done in bim-ootb worktree, this commit is the bim-compiler-side fix
the browser witness caught): compileRooms() queried spatial_structure unconditionally for
storey guids, but Python's compile_rooms.py wraps that specific query in try/except because a
truly fresh building has no such table yet. The node-side parity witness never exercised this
path since every real shipped _ARC.db it compared against already had a spatial_structure
table -- only the live browser test (dropping the table entirely to simulate a fresh building)
surfaced it. Fixed with a table-existence check, mirroring Python's guard exactly. Re-verified:
node parity witness still 6/6, browser witness 12/12 (see bim-ootb companion commit).

Task 5: compile_rooms.py is retired from room-injection duty but NOT deleted -- found a real,
unrelated dependency (scripts/witness_geomap_tier3.py imports it directly as a Python baseline-
scoring library). Updated ROOM_INJECTION_HYBRID.md's Task 2 (automation half superseded by the
explicit-trigger Room Walker design, not built as originally specced) and
COMPILE_ROOMS_TYPE_INFERENCE.md's anchor (points future work at room_walker.js, not the now-
superseded Python file) so no future session gets misdirected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): ROOM_WALKER_JS_PORT all 5 tasks DONE

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): §WALL-LIGHT — measured sconce rows swap to wall-anchored WALL_HIGH + mined z (detector: median edge 0.09m vs pendants 0.96-2.28m; W6 0.963→1.000; pendants honestly refused)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(disc_walker): §WALL-SLOT — which-wall slot seam (miner/projection/walker/M3), 0 slots on Duplex BY MEASUREMENT: wall choice is mirror-dependent, absolute MIN/MAX refs refuse honestly (seam proven by falsifier, byte-inert at 0 rows)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(rooms): §7 ROOM WELL-FORMEDNESS — corridor/wall-crossing fix, SUSPECT_* review rows (ROOM009-014)

User visual review on HHS localhost found two algorithmic defects: a corridor accepted
as a room (open non-wall edge) and a room rect crossing through a wall. Root-caused on
real ARC data across all 8 buildings (not HHS-patched):
- §WALL-VERT: IfcCurtainWall parents have NO transform — curtain walls rasterized as
  nothing. Their IfcMember/IfcPlate children join the raster iff bbox_z >= 0.5×median
  real door height (self-scaling; Terminal's 33k flat Metal Deck plates stay out).
- §STOREY-Z: 'Unknown'-storey enclosure/doors (HHS 716, Hospital 3760 rows) reassigned
  to the z-nearest real floor. HHS flood-fill recovers on all 3 levels — door-partition
  (the corridor-blob source) no longer triggers there.
- §RECT-HONESTY: room rect = largest inscribed rectangle expanded to raw walls, replacing
  the region bbox — a rect can no longer paint across a wall into the next room.
- §ROOM-FORM (user doctrine "a room must be well formed, fully enclosed, has door"):
  openM (unsealed perimeter, 3-wide probe) > 2×median door width → SUSPECT_OPEN;
  no adjacent door → SUSPECT_NO_DOOR. Suspects keep '⚠'-marked rows for a future review
  feature, excluded from rel_contained_in_space; never silently dropped.

Both implementations updated in lockstep (compile_rooms.py numpy paths → plain flat
arrays mirroring the JS port operation-for-operation). Witnesses: W-ROOM-WALKER-PARITY
6/6 byte-identical; NEW W-ROOM-WELLFORMED 19/19 (independent-raster falsifiers: zero
wall-crossing non-suspect rects, zero suspect containment, HHS corridor collapse cannot
re-form). ROOM009-014 migrations verified apply-identical to walker output (6/6).
New counts: SC 51(9⚠) HHS 33(2⚠) Clinic 209(26⚠) Garage 5(3⚠) Hospital 213(66⚠)
Terminal 53(10⚠). Spec: ROOM_INJECTION_HYBRID.md §7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(progress): compact room-lane entries to spec-doc pointers (80-line budget)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(rooms): §8 MULTI-RECT — room space as a rectangle set, room_guid grouping (ROOM015-020)

A confirmed room's single §RECT-HONESTY rect under-covered non-rectangular rooms
(measured coverage down to 0.23-0.26 — the user's "doesn't fully form the inner room
space"). Per ROOM_INJECTION_HYBRID.md §8 (user-directed 3-step design):
1. Fill-ratio preprocessor: rooms whose first rect covers >=0.95 of the (seal-band-
   recovered) region stay single-row — the majority, cheapest path.
2. Room space set: below the bar, the region decomposes via repeated CONSTRAINED
   maximal-rectangle scan (both dims >= NOISE_FLOOR_DIM, grid-derived; stop at 0.95
   coverage or 8 rects — measured max used: 7). No wall-crossing by construction;
   curved-wall residue reported honestly, never faked.
3. Shared identity: one spatial_structure row per sub-rect; primary keeps RM_<st>_<k>,
   extras lettered (b, c, ...); NEW room_guid column groups the set; identical
   name/predefined_type; rel_contained_in_space keys LOGICAL guids only (any-rect
   containment). SUSPECT rooms stay single-rect (orthogonal to §ROOM-FORM).

Both ports lockstep; includes the concurrent §DISC-ARC discipline filter (Sonnet,
same working tree — merged, not overwritten). Coverage gains (W-ROOM-FILL, median/
worst): Hospital 0.74→0.86 / 0.32→0.67, Terminal 0.81→0.87 / 0.42→0.69, Clinic
0.78→0.81 / 0.45→0.57, per-room monotone. Witnesses: W-ROOM-WALKER-PARITY 6/6
byte-identical (dump now covers room_guid), W-ROOM-WELLFORMED 19/19 (zero regression,
sub-rects in the wall-crossing oracle), NEW W-ROOM-FILL 18/18, ROOM015-020 migrations
apply-identical 6/6 (supersede ROOM009-014's single-rect data).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(prompts): archive audit 2026-07-11 — 9 stale prompts to prompts/archive/ (evidence-logged)

9 archived (self-declared DONE/DEPRECATED/DRAINED + zero blocking refs), 22 kept live,
6 flagged ambiguous. Full per-file evidence trail in prompts/PROMPTS_ARCHIVE_AUDIT_2026-07-11.md
§Log. docs/*.md swept: nothing to archive (all live mkdocs pages, post-07-03 unified pass).
git mv only — history preserved. CLAUDE.md/PROGRESS.md FLM pointer fixes left uncommitted
(files dirty from concurrent lanes).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(resume): §8E-3 DONE — bim-ootb PR #731, render wiring was already shipped, real gap was substrate

Corrects this doc's own "render wiring not started" framing: _renderDiscChains/_commitDiscChains
(§ROUTER-NNCHAIN, §CAMPAIGN M4/M5) already render routeChains' segments as cylinder tubes. The
actual remaining gap: witness_modeller_router_nnchain.js is RED on bim-ootb main (shipped
Terminal_ARC.db resident is ARC-only, 0 MEP) and __dwPixelProbe's A/B-isolation missed dwChain-
tagged tubes (fixed). New witness_mep_route_render.js proves Terminal PLB 4315 + ACMV 1002 = 5317
and Duplex PLB 358 segs render + paint real isolated pixels, matching W-WALKBACK-MEP's oracle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(resume): note PR #731 was auto-merged by repo bot, not manually

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): ROOM021 — carry 105-row spatial_structure into Viewer's HHS buildings db + §4 execution log

VIEWER_FIND_PANEL_ROOM_ACCURACY.md §2b: buildings/HHS_Office_Federated_extracted.db
(the file the Viewer actually fetches for HHS) still shipped the stale 14-row set;
ROOM021 ports the SAME source-of-truth data as ROOM002 (modeller/HHS_ARC.db @
fable/modeller-lod400-livewire fd7da67, extracted via sqlite3 .mode insert) to the
buildings/ target. Applied+verified locally (§ROOM021-PARITY byte-identical, 109
rows); binary stays uncommitted per the DB-via-SQL-migration rule. §4 appended:
Tasks 1+2 DONE in bim-ootb fix/viewer-room-accuracy @ a995908 (local only, LFS
block) — W-VIEWER-ROOM-HAB 6/6 (Duplex 20 habitable + R301 label:ROOF excluded;
HHS 105/0 leaks), W-VIEWER-TYPE-GROUP (COMPILED:105 -> INTERNAL_DOORPART:105).
No Viewer-side self-heal .sql loader exists (checked; Modeller's is on unmerged
fix/meshdb-selfheal-loader only) — noted as open follow-up, not invented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(rooms): VIEWER_FIND_PANEL_ROOM_ACCURACY §5 — Task 1/2 + §2b shipped, supersedes stuck §4

§4's fix/viewer-room-accuracy worktree was left uncommitted-beyond-local and unpushed, missing its
own named follow-up (no Viewer-side self-heal loader). Rebuilt clean this session: bim-ootb PR #732
ships the habitability filter (Task 1), the Type-toggle COMPILED fallthrough fix (Task 2), and the
HHS buildings/patches/ SQL migration + runtime self-heal loader (§2b) — witness 11/11, pushed with
no LFS stall (corrects §4's over-cautious "no push possible" note). ROOM021_HHS_buildings_extracted_
carry.sql (already committed by §4) cross-validated byte-identical to the new patch's payload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): correct §5 — PR #732 was auto-merge-bot merged, not left open; flag concurrent worktree

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(terminal): root-cause coordinate-frame mismatch + fix deploy DB in place

TERMINAL_COORDINATE_FRAME_MISMATCH.md: bim-ootb's Terminal_ARC.db matches
raw-IFC ground truth (<2cm, verified via ifcopenshell world-bbox-center on
the source .ifc); bim-compiler's deploy/buildings/Terminal_extracted.db was
a carve-out of the multi-building sandbox_1M city demo (extract_per_building.py
reading T0_Terminal_ rows verbatim from build_sandbox_1M.py's tile-placement
output, scripts/build_sandbox_1M.py L216-320) stacked on extractIFCtoDB.py's
S169 centroid-normalize (L1453-1506) — both uncorrected. Delta proven constant
across 12 sampled guids (stdev <1mm): (545.61m, 51.22m, 14.66m).

Fixed deploy/buildings/Terminal_extracted.db (gitignored build artifact, not
committed) in place with the proven-constant offset correction; backed up,
integrity-checked, re-verified against ground truth (<6mm on all axes).

PROGRESS.md: mark item resolved, flag other CBD_BUILDINGS sharing the same
carve-out path as unverified for the same bug class.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): ROOM_INJECTION_HYBRID.md §9 — Room Lens volume-box fix shipped, OCI upload block lifted

Room_guid multi-rect grouping ported into viewer/navigate_find.js's _allRoomVolumes()/
_roomLensOn() (bim-ootb PR #733), witnessed 8/8 (rendered box footprint-area SUM = spatial_
structure's own rect-union area SUM, diff=0.000m2) with zero regression to the existing
habitability-filter witness (11/11). Closes the standing OCI room-data upload blocker.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): harden DB/migration-script rule, PR-merge authority, room-template strategy specs

- CLAUDE.md: DB changes are permanently migration-script+self-heal-loader, not an LFS workaround —
  stop citing LFS as the blocker for DB fixes.
- prompts/MANAGER.md: PR merge is standing Manager scope once independently verified, don't kick
  back an already-answerable merge decision.
- VIEWER_FIND_PANEL_ROOM_ACCURACY.md / UBBL_RULES_GATE.md: MANAGER assignment markers + doc-trail
  corrections from today's dispatched work.
- ROOM_TYPE_TEMPLATE_CLASSIFIER.md: new spec, room-type classification via size/aspect-ratio
  template mined from Duplex's real object_type ground truth, repeat-confirmation methodology.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): push-pause standing mode + Room Intelligence execution plan

CLAUDE.md: local/localhost-only until a named breakthrough, hardened per user directive.
MANAGER.md: synthesized today's strategy discussion into a concrete execution plan —
the competitive bet, what's shipped, what's mid-flight, named next axes (grid, door-access,
disqualifiers, Outliner flywheel).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): §ROOM-TYPE — size+aspect-ratio template classifier, measured from Duplex+SampleHouse

Adds config/room_templates.yaml (7 promoted templates, confidence:measured, N=2-5 each, fit from
Duplex's + SampleHouse's real object_type room labels — the only 2 shipped buildings with genuine
human-authored room-type ground truth) + build/room_type_classifier.js (probabilistic Gaussian
scorer, refuse-to-classify below a z-threshold, §MULTI-RECT-aware area/aspect from a rect-set) +
build/witness_room_type_classifier.js (W-ROOM-TYPE, run over all 8 shipped buildings' compiled
spatial_structure rows, 3/3 checks PASS).

Held-out inference on the other 6 buildings' synthetic COMPILED rooms: 378/602 (62.8%) honestly
unclassified — expected, not a shortfall, per prompts/ROOM_TYPE_TEMPLATE_CLASSIFIER.md's own
discipline against unearned confidence. No `confidence: prior` templates added — the only in-repo
external room-size numbers are the already-flagged-uncorroborated UBBL landmine values (3
conflicting numbers across config/profiles/malaysian_residential.yaml and config/spacetypes.yaml);
reusing them here would be a 4th, so they were deliberately left out.

Scope: config + classifier + witness only, per prompts/ROOM_TYPE_TEMPLATE_CLASSIFIER.md. Modeller
Outliner wiring + user-correction flywheel (Step 4) is a named, separate follow-up, not started.

Local-only commit per coordinator directive (batch-verify before pushing more today) — not pushed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): §DOOR-ACCESS — door-count second signal for room-type classifier

Adds door-count/adjacency as a second discriminating signal alongside the
existing size+aspect-ratio Gaussian scorer (ROOM_TYPE_TEMPLATE_CLASSIFIER.md
follow-up, ROOM_TYPE_DOOR_ACCESS_SIGNAL.md).

- build/room_type_classifier.js: countAdjacentDoors() reuses compile_rooms.py's
  own _door_adjacent() buffer test (extended boolean->count, same
  DOOR_BUFFER_SLACK=0.20m constant); scoreTemplate() gains an optional 3rd
  quadrature dimension, backward-compatible when doorCount isn't supplied.
- build/measure_door_counts.js: measures door_count per room type from
  Duplex+SampleHouse real labeled ground truth (same 2-building anchor, same
  >=2-occurrence promotion bar as area/aspect).
- config/room_templates.yaml: all 7 promoted templates carry a measured
  door_count band; KITCHEN=0 (genuine open-plan finding) and UTILITY's
  buffer-noise caveat both documented honestly.
- build/witness_room_type_classifier.js: computes real door counts across all
  8 buildings, logs every classification the signal flips either way.

Honest witness result (logs/witness_room_type_classifier_door_access_*.log,
4/4 checks pass): 3 genuine real-data wins (2 HALLWAY->KITCHEN corrections on
doorless rooms, 1 false HALLWAY match on SampleHouse's Entrance Hall
correctly refused) but a net regression if blended unconditionally at today's
n=2..5 fitting scale (held-out unclassified 62.8%->84.2%) — reported plainly,
not oversold. classifyRoom() stays backward-compatible: door_count only
applies when a caller opts in by supplying features.doorCount.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): §DOOR-ACCESS — cross-check against the parent task's named miss case

SampleHouse's real Bedroom (the specific example that motivated this task) still
misclassifies as LIVING_ROOM with door_count added — confidence only nudges 75.1%->70.6%.
Confirms the net-regression finding rather than contradicting it.

* docs(manager): self-dispatch reinforcement, note peer-session cross-verification pattern

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(rooms): §PRIMARY-VS-SUPPLEMENTARY tier + BOM wiring to required_spaces

Follow-up to ROOM_TYPE_TEMPLATE_CLASSIFIER.md's "dwelling set" and "bigger
reframing" notes.

1. config/room_templates.yaml: every promoted template gets a
   tier: primary|supplementary field. HALLWAY/FOYER = supplementary
   (measured: highest door_count of all 7 templates, most elongated
   aspect_ratio — real circulation signature). BEDROOM/BATHROOM/KITCHEN/
   LIVING_ROOM = primary. UTILITY (not named by the coordinator) decided via
   the same measured-signal discipline: compact aspect_ratio wins the
   tie-break over its already-flagged-unreliable door_count band.

2. build/check_required_spaces.js: feeds the classifier's PRIMARY-tier room
   counts into config/profiles/malaysian_residential.yaml's dormant
   required_spaces BOM recipe. Reuses the count-vs-minCount-shortfall shape
   already present in DAGCompiler's ProtocolValidatorRegistry.java (different
   data source, same pattern) rather than inventing a new validation style.
   Splits Duplex into its two real dwelling units (A101.."A/B" name prefix,
   a real naming convention in the source IFC) so a per-unit shortfall can't
   hide inside a combined-building total.

Witness (logs/check_required_spaces_202607110959.log, 2/2 mechanism checks
pass): Duplex units A and B each genuinely satisfy required_spaces (2
bedroom/2 bathroom/1 kitchen/1 living each, matching the coordinator's own
expectation, checked for real not assumed). SampleHouse genuinely does NOT
satisfy it — honestly explained, not a classifier bug: its extraction only
carries 3 real labeled rooms total (no real Kitchen/Bathroom label exists to
classify in the first place).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): DISC-walk room-type-awareness + corridor pathway routing specs, dispatched

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(manager): harden abstract/mathematical discipline for room-intelligence lane

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(competitive): prior-art analysis with verified citations

Real web-searched, author-verified references — not training-data recall. Corrected one
overclaim (Revit has no native room classification, but third-party ML plugins do exist).
Found a near-exact academic prior-art match (Buruzs et al 2022, Energies) covering both
today's room-type classifier and room-adjacency graph in one published pipeline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(disc_walker): measure discipline x room-type MEP density on real Duplex data

prompts/DISC_WALK_ROOM_TYPE_AWARE.md: build/measure_disc_room_type_density.js measures real
element density per discipline x classified room-type on the only substrate with both real space
geometry+labels and real MEP fixtures (Duplex — Terminal has 0 real IfcSpace rows, refused as a
substrate). Found real replicated signal for PLB (BATHROOM/UTILITY) and FP (FOYER); no signal for
ELEC (present everywhere) or ACMV (0 real elements). Corridor/supplementary tier explicitly checked
against both. Full table + wiring into bim-ootb disc_walker.js recorded in the prompt doc.

Not pushed (session-wide PUSH PAUSE discipline extended here out of caution; only these two files
staged, other pre-existing working-tree changes left untouched).

* docs(prompts): §7 room-to-room adjacency graph + pathfinding — DONE, witnessed

Records the bim-ootb feat/room-pathfind-graph work (common/room_graph.js, Find panel Room
axis "Path" sub-mode): real door-adjacency graph, Dijkstra pathfinding, hub/leaf pattern
confirmed on real Duplex data (Hallway/Foyer avg degree 2.50 vs Bedroom/Bathroom/Utility
avg 1.20), door-guid-continuity-verified path witness (15/15 node-side + 13/13 browser),
honest disconnected-room reporting. PUSH PAUSE in effect — local commit only, not pushed.

* docs(manager): session closeout — scoreboard doc, flag-on-the-hill mission, standing rules

- New prompts/ROOM_INTELLIGENCE_SCOREBOARD.md: standard scored-table reporting format
  (13-feature verdict table + 8-building coverage table), confirmed by user as the
  expected baseline going forward. Includes the HHS-corridor scale-mismatch finding
  (79 unclassified INTERNAL_DOORPART rooms, several corridor-shaped up to aspect 37:1 —
  real circulation the residential-trained classifier can't yet see).
- MANAGER.md: added the FLAG ON THE HILL section — next session's named mission (expand
  the room/space taxonomy to all building parts: stairways, air wells, ventilation, lift
  shafts, plant rooms — so Find panel, Modeller Outliner, and DISC Walker are all complete).
  Added STANDING RULES (localhost-verify, local-commits-only, migration-script-DB-policy)
  and KEY DOCUMENTS navigation section linking every doc from this session.
- PROGRESS.md: compacted the Room Intelligence block to a scoreboard pointer (was ~70 lines
  of now-superseded detail), added the push-pause status line.
- project_room_intelligence_lane.md memory: was referenced but never created — fixed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(progress): trim redundant UBBL detail, point to scoreboard

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* chore: commit regen artifacts left uncommitted from prior session

build/duplex_rules.db — rule_placement table (16 rows) from
measure_disc_room_type_density.js, companion binary to 680e673ee
(DISC_WALK_ROOM_TYPE_AWARE.md, scoreboard item 12) which only staged the
script+spec, not the regenerated DB.

deploy/dev/navigate_find.js — restores explicit position:fixed+display:none
on #find-panel (self-contained fallback, was dropped in ae1cd738b when the
panel started inheriting from .bim-panel) — same fix as scoreboard item 1
(Find-panel visibility, bim-ootb PR #728), applied to this repo's copy.

* feat(migration): W024 component_dimension_range — Q1 LOD touch-up aggregation

Adds GROUP BY type_id aggregation over component_definitions.local_min/max,
persisting per-class min/max (34 classes, 23887 instances covered). Raw
instance rows already existed (e.g. 129 IfcDoor rows spanning 0.147-1.86m
local width) — only the aggregate was missing, per PARAMETRIC_DEPTH_RECON_FINDINGS.md Q1.

migration/W024_component_dimension_range.sql is the durable append-only record
(per Sacred Files policy — library/*.db is regenerated from migrations, never
committed directly). tools/aggregate_component_dimension_range.py runs the same
SQL directly for local dev/witness convenience and prints the §Q1_AGG evidence.

Witness: §Q1_AGG type=IfcDoor count=129 minWidth=0.147194 maxWidth=1.860000,
§Q1_AGG_CHECK aggCount=129 rawCount=129 expected=129 match=True.

* feat(rooms): §BUILDING-PARTS-TAXONOMY — stairway/lift-shaft/plant-room checklist, first ratchet on FLAG ON THE HILL

Implements prompts/MANAGER.md §🚩 THE FLAG ON THE HILL per the user's own framing: a taxonomy
checklist config walked top-down (does this building-class have every expected part) or bottom-up
(look up each real entity against the same table) — same data, both directions.

config/building_taxonomy.yaml generalizes the existing required_spaces/check_required_spaces.js
BOM-shape (count-vs-minCount, ported from ProtocolValidatorRegistry.java) from habitable-room-types
only to any building part, sourced from whichever signal is real: direct IfcStair/IfcStairFlight
entity query for STAIRWAY, the existing NON_ROOM_DOOR_NAMES lift-keyword list (widened scope, not
re-derived) for LIFT_SHAFT, MEP-keyword density for PLANT_ROOM (Terminal-only, n=1, advisory).

STORAGE and AIR_LIGHT_WELL are deliberately absent — zero real evidence found in any of the 8
shipped buildings (see prompts/BUILDING_PARTS_TAXONOMY.md's recon table) — explicit refusal, not an
invented category.

Found and documented a real data-shape issue while building the witness (§PARENT-NO-TRANSFORM):
assembly parents (IfcStair) often carry no transform of their own, only their IfcStairFlight
children do — a transform-requiring join silently undercounts (Duplex 4 real entities -> 2
positionable, Hospital 60 -> 30). extractParts() now reports both .all (existence) and .positioned
(markerable) counts. Also corrected the initial recon agent's exploratory PLANT_ROOM tally
(117/"Aras 01 R3" 22/117) against this module's own reproducible query (74/"Aras Tanah R11" 10/74)
— the reproducible number is treated as authoritative, per this project's non-invent discipline.

Witness: W-BUILDING-PARTS 13/13 PASS, re-run against all 8 real *_ARC.db files.

Not pushed — session-wide PUSH PAUSE (CLAUDE.md §⏸).

* docs(scoreboard): fold building-parts-taxonomy data into the coverage table

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): SPARSE_WALL_ROOM_INFERENCE.md — the real-world-IFC challenge, dispatched

Phase 0 (data health guard, external idea corrected against real schema+thresholds) +
Phase 1 (signal-fusion inference: grid/door/slab/envelope) to recover room structure when
flood-fill's wall data is genuinely too sparse, per HHS's root-caused 1.06 walls/room finding.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): cross-reference SPARSE_WALL_ROOM_INFERENCE root-cause into taxonomy scoreboard

HHS's Stairway=0 (building_parts_taxonomy) and its wall-flood-fill failure (sparse-wall inference
thread) share one root cause: zero IfcStair/IfcRamp entities + 1.06 walls/room in HHS's federated
IFC — confirmed absence in source data, not an extraction gap on either thread's side. Also logs
the parallel thread in PROGRESS.md's juggled list so it isn't silently lost track of.

* feat(rooms): §PHASE0-HEALTH — Data Health Guard, wall/door + STR-fingerprint + circulation flags

Pre-flood-fill sparsity check per SPARSE_WALL_ROOM_INFERENCE.md Phase 0. Real-schema queries
(elements_meta.ifc_class/discipline, verified live). Thresholds derived from Hospital/Clinic/HHS's
own measured wall/door ratios and STR-discipline shares, not asserted round numbers. Uses wall/DOOR
ratio (not wall/space) since IfcSpace is absent from all 3 raw extracts (0 rows, confirmed) — using
flood-fill's own output as denominator would be circular and provably unstable (HHS's room count
moved from failing to 71 honest rooms via a same-day unrelated commit, §WALL-VERT 7133bbe06).

Witnessed: Hospital OK (3.27 ratio, 4.5% STR), Clinic OK (4.25 ratio, 10.1% STR), HHS FLAGGED
(1.20 ratio < 2.235 threshold, 24.8% STR > 17.4% threshold) — zero regression on wall-rich
buildings, correct flag on the sparse one. Guard informs only, never blocks — flood-fill still
runs on every building regardless of flag state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): Find-panel Parts axis landed (bim-ootb d04ddd5), MANAGER-verified

Independently checked the dispatched worker's diff (not just its report) and one real
discrepancy (Duplex Stairway=2 vs this repo's witness=4): confirmed a genuine DB-variant
divergence (bim-ootb's served Duplex_extracted.db lacks the parent IfcStair rows that
Duplex_ARC.db has), not a bug in the ported query. Documented so it isn't mistaken for a
regression later. Scoreboard row 15 bumped 7->8; Outliner wiring (the other VISION-LOCK
sentence-5 half) still open.

* docs(rooms): SPARSE_WALL_ROOM_INFERENCE checkpoint — Phase 0 done+witnessed, Phase 1 scoped as follow-up

Records: two stale premises found on re-verification (HHS no longer 105/105 DOORPART — a same-day
unrelated commit §WALL-VERT already fixed it via curtain-wall glazing evidence; HHS does have real
stair data, 20 rows, not zero as originally diagnosed). Phase 0 witness numbers, threshold
derivations, and a concrete 4-step Phase 1 follow-up spec for a fresh session to pick up cleanly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): correct HHS Stairway=0 — DB-snapshot divergence, not real absence (2nd confirmed instance, memory saved)

* docs(progress): log Outliner wiring dispatch (Building Parts Taxonomy → Modeller)

* docs(rooms): Modeller Outliner wiring landed (bim-ootb f10c5295), MANAGER-verified — both VISION-LOCK sentence-5 UI halves done

Independently checked the diff: new modeller/building_parts_outliner.js mirrors the existing
dw_instances_outliner.js extension-seam pattern correctly, bonsai_outliner.js untouched, real
leaf-id bug caught+fixed during verification (compound id broke the existing click-to-frame path).
Third Duplex Stairway data point (4, matching bim-compiler's own witness) narrows the earlier
DB-divergence finding to the Viewer's specific served copy being the outlier, not a universal
disagreement. Scoreboard row 15 bumped 8->9.

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — spec for a fresh Sonnet session

User's own live review of today's Modeller work: LOD confirmed no longer bad, but material
rendering still wrong (glass walls/windows not see-through, unlike the Viewer). Blocks adding
today's Building Parts Outliner screenshot to docs/ModellerGuide.md — "not fitting for the guide."
Also folds in a named UI quirk (Outliner panel collapse control not discoverable) per user request,
tracked rather than dropped. Delegated as a written spec, not fire-fought reactively mid-session.

* docs(manager): harden anti-ad-hoc-debugging conduct rule + write the missing Viewer-side spec

User caught it live twice in one session: material-parity got a proper prompts/# after the first
correction, but the Find-panel screenshot chase (3 failed attempts to find the panel-open
mechanism) was still ad-hoc debugging inline in the MANAGER turn, not delegated. Hardened
prompts/MANAGER.md with the rule (stop after a second failed quick-check, write the spec instead
of continuing to guess) and wrote prompts/VIEWER_FIND_PANEL_PARTS_VERIFICATION.md so a dispatched
session picks this up with the 3 known dead-ends already named, not repeated.

* docs(progress): session closeout — compact juggled-list, close building-parts+disc-walk threads, note guide-blocker specs

* docs(rooms): READ FIRST anti-drift pointer — taxonomy is CLOSED, don't re-open without new cause

* docs(prompts): VIEWER_FIND_PANEL_PARTS_VERIFICATION.md RESULT — panel-open blocker solved + real bug found

Root cause of MANAGER's 3 failed guesses: window.A never existed, A is a local closure
parameter aliasing window.APP. window.APP.openFindPanel('') works; so does the real-user
path (press 'f', per scene.js's own keyboard shortcut). Live-driven evidence captured
(2 screenshots, §-tagged console logs) confirming the Parts axis renders real Stairway(4)/
Plant Room(6) counts on Duplex from a fresh page load.

Byproduct finding, not fixed (out of this file's verification-only scope): PLANT_KEYWORDS'
bare 'vent' substring match false-positives on "Backflow Preventer" (4 of 6 Duplex "Plant
Room" hits are false positives) and the live Parts axis has no class gate, unlike
checklistReport()'s class-gated report. Also a 4th confirmed instance of the DB-snapshot
divergence landmine (root buildings/Duplex_extracted.db vs the actually-served
viewer/buildings/Duplex_extracted.db disagree on Stairway count, 2 vs 4).

PUSH PAUSE in effect — commit local-only, no push, no PR.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — Task 1+2 findings, both DONE

bim-ootb fix/modeller-render-material-parity @ 2fc3964 (local, unpushed —
push pause in effect): glass/window transparency threaded through from
elements_meta.material_rgba alpha (mirrors viewer/streaming.js's own
opacity gate), and the Outliner collapse button's discoverability fixed
(was functionally correct, just zero visual weight at rest). Both verified
in real headless Chrome against the real Duplex resident, no regressions
in existing suites. Guide unblocked.

* docs(viewer): add Find panel section to BIMUserGuide.md

Cherry-picked from agent worktree (40d0c2444) to consolidate onto this
branch. Documents the Find panel's open path, search/voice query box,
and all six axes incl. the new Parts axis. Screenshot placeholders only
(img/viewer/*.png), no images captured yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(rooms): scoreboard — file PLANT_KEYWORDS false-positive + missing class-gate finding

From VIEWER_FIND_PANEL_PARTS_VERIFICATION.md's byproduct bug (found, not fixed there).
Row 15 now names both the substring-collision fix and the live-query class-gate fix
so they aren't lost before the follow-up session picks them up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): FIND_PANEL_PLANT_ROOM_GATE_FIX.md — spec the 2 named Find-panel bugs

Bounded follow-up to VIEWER_FIND_PANEL_PARTS_VERIFICATION.md's byproduct findings
(substring false-positive + missing class-gate), ready to dispatch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — PR #735 merged, localhost-gap root cause logged

Session's own working file, not memory, per user's steer this turn.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — deployment landmine + collapse-all button + Find-panel-highlight proposal

Follow-up to the earlier findings entry: the fix wasn't reaching the
user's actual test server (worktree vs shared checkout + stale SW
precache, both now fixed and merged into ~/bim-ootb). Added a real
Collapse All button. Documented 3 ranked options for the open "click a
higher-level row to highlight the section" question — not yet
implemented, needs user's pick given a real collision risk with the
existing disc-walk-on-click wiring.

* docs(manager): scope narrowed — user guides + git/localhost admin only

Lane sessions now self-review and administer their own follow-up prompts.
User's own words captured verbatim so this doesn't drift back silently.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): MODELLER_RENDER_MATERIAL_PARITY.md — option 1 shipped + verified live

Documents the select-then-collapse conflict found and resolved (auto-
expand-on-pick vs manual collapse-toggle, can't coexist on one click),
the final select-only design, and live verification against the user's
actual port-8080 server.

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — scope for Fable, corrects stale marathon framing

Investigated "the DiscWalk task" per user request. Found the 2026-07-10
marathon memory's framing is stale: the Z-datum bug it called "the actual
next real gap" is fully done and merged in BOTH repos (bim-compiler PR
#40, bim-ootb PR #726 squash 3d09ad6 — confirmed already an ancestor of
local main, correcting PROGRESS.md's "open, not merged" note) — as is
fix/dw-rot-units (PR #723). Only 3 small, already-verified, no-conflict
branches remain genuinely unmerged (PRs #722/#724/#725), plus one real
open question: the guide-screenshot camera bug from the same marathon,
never diagnosed. Scoped a Fable session: re-verify the 3 branches fresh
(no merge/push — Sonnet reviews before any of that), then chase the
screenshot bug's root cause. Named the stale-radians migration question
as explicitly out of scope (separate, harder design task).

* fix(rooms): word-boundary keyword match for PLANT_KEYWORDS/LIFT_KEYWORDS

prompts/FIND_PANEL_PLANT_ROOM_GATE_FIX.md Bug 1 (bim-ootb port ported byte-identical
to viewer/navigate_find.js + modeller/building_parts_outliner.js, same session).

build/building_parts_taxonomy.js's checklistReport() already class-gated PLANT_ROOM
correctly via config/building_taxonomy.yaml (Bug 2 doesn't apply here) — only the
bare LIKE '%vent%' substring match needed fixing. Real-data-driven: surveyed 59
distinct element_name templates across 5 buildings before picking the fix (token
split on delimiters + camelCase, keyword-as-token-prefix match).

Verified: Clinic 1890->1881 (9 "Backflow Preventer" false positives dropped, all
real duct/fan/pump/chiller/vent rows kept). Terminal 74->74 unchanged (no
true-positive regression). witness_building_parts_taxonomy.js 13/13 PASS, unchanged.

PUSH PAUSE stands in this repo per CLAUDE.md standing directive — local commit only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(viewer,modeller): real screenshots for Find panel + new Building Parts/glass section

Cherry-picked from agent worktree (a77fcc2b0). Replaces the 5 Find-panel placeholders
with real Playwright captures off bim-ootb main (f0f0994), corrects two prose details
the source-only draft got wrong (search placeholder text, Navigate drawer row name).
Adds ModellerGuide.md coverage for Building Parts Outliner + glass transparency, both
previously undocumented. Two new findings flagged in-doc: NL-query hint never renders
live (CSS gating bug), Parts axis Plant Room false-positive (tracked in
FIND_PANEL_PLANT_ROOM_GATE_FIX.md, not duplicated here).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — verification worktrees already built, only the witness re-run + report remain

Found /tmp/wt-verify-{grid-tilt,oracle,dwprobe} already exist with the
target branches merged into fresh checkouts off current main (dwprobe hit
a real conflict since my last check, resolved KEEP-BOTH). None have a
logged witness re-run yet — that's the only remaining step before a
Manager-scoped session can make the merge call. Noted so the next
dispatch doesn't redo the merge work.

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — 2026-07-11 findings appended (3 PRs re-verified, guide-shot bug diagnosed+fixed)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — Manager verification result, 2 merged 1 held

#722 and #725 (as #741) merged after fresh re-verification. #724 held — real regression
in the KEEP-BOTH conflict resolution (SampleCastle MEP disc node now absent from UI,
was 8/8 historically, now 6/8), needs a fix, not Manager's to patch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): Sonnet verification clears #724 (not a regression) + dispatch WITNESS_SAMPLECASTLE_MEP_STALE.md

Independently verified Manager's flagged "regression" on fable/dwprobe-dedup
(#724): ran witness_modeller_disc_walk.js directly against pristine
origin/main (9b62c4f, zero relation to the branch) and reproduced the
IDENTICAL B5/B6 failure. Conclusive — the branch/merge isn't the cause.
Root cause: SampleCastle_ARC.db is ARC-only (0 MEP rows, confirmed via
direct SQL), a data-vs-witness staleness, not a code regression. #724
is clear to merge on the same terms as #722/#725. Scoped the actual fix
(retarget or honestly skip B5/B6, fix the uncaught-rejection crash path)
as its own small follow-up rather than blocking the branch verification
task on it.

* docs(prompts): DISC_WALKER_BRANCH_CLOSEOUT.md — correct #724 verdict, merged

My earlier "real regression" call was wrong — independently re-verified Sonnet 1's
counter-finding (pristine main reproduces the same failure, unrelated to the branch)
before merging. Root cause was stale SampleCastle_ARC.db data, not the KEEP-BOTH merge.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): WITNESS_SAMPLECASTLE_MEP_STALE — findings appended, B5/B6 retargeted to Clinic, 8/8 green (local-only per push pause)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(viewer): swap Parts-axis screenshot to HHS (real institutional data, post-fix)

The Duplex screenshot predated bim-ootb PR #740/#742 (word-boundary + class-gate
fix) and showed the pre-fix false-positive behavior. Replaced with a real capture
on HHS Office (complex-class): Stairway(20), Lift Shaft(3), Plant Room(1769) all
visible at once, and updated the caveat note now that the fix is landed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): DISCWALK_PLANT_ROOM_INDUSTRIAL_TAXONOMY.md — Fable-scoped next mission

DiscWalk-strengthening + Plant Room industrial taxonomy expansion, next step on
MANAGER.md's own "Flag on the Hill" mission. Grounded in live HHS Find-panel
verification this session (real 1769-match Plant Room evidence, class-checked
not just LIKE-counted). Terminal named explicitly as the calibration anchor
(real professional project, not public-sourced like the other buildings).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs(prompts): WALKER_FIXTURE_RENDER_MATERIAL_AND_GEOMETRY_CHECK.md — investigation only

User spotted geometry chaos + no material/LOD400 on the live ModellerGuide's
walker-fixtures screenshot. Traced to _renderDiscWalk in modeller.html (confirmed
a separate, flat disc-tinted material path from today's ARC-seed glass fix, and
confirmed placement x/y/z comes straight from disc_walker.js with no clamping in
the renderer) before writing the spec, so the dispatched session isn't starting
from a guess. Explicitly investigation-only, gates whether this is a render bug,
a disc_walker placement-data defect, or a screenshot framing illusion, and
whether it's ELEC-specific or a systemic …
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.

1 participant