Skip to content

sheetgraph: read what real sets actually draw (#87 phase 3b) - #266

Merged
QuisutDeus1 merged 1 commit into
mainfrom
fix/sheetgraph-right-band
Aug 16, 2026
Merged

sheetgraph: read what real sets actually draw (#87 phase 3b)#266
QuisutDeus1 merged 1 commit into
mainfrom
fix/sheetgraph-right-band

Conversation

@QuisutDeus1

Copy link
Copy Markdown
Member

Five real bid sets across five general contractors, run through scripts/graph-audit.mjs. Every fix ships with a fixture reproducing the real failure — none of these were reachable from synthetic tests, which is the point of the field harness.

The one that would have cost money

Two-tier headers. WALLS (PLAN DIRECTION) is a merged parent over N | E | S | W. The sub-labels are single letters, not vocabulary words, so they anchored nothing and every wall column banded to whichever neighbour was nearest — N and E into BASE, S and W into CEILING. BASE read VWB-1 - FRP-1, FRP-1A, PT instead of VWB-1. A polluted base column is a wrong number in the bid.

A run of ≥2 adjacent non-vocabulary tokens inside the header's own span is now a sub-tier; the parent is the span above that actually covers the run; sub-anchors are labelled WALLS N so the column keeps both halves of its meaning. Crucially they carry real bounds, not centers — sub-columns under a merged parent are equal-width by drafting convention, and a bounded anchor claims only what falls inside it. Center-based banding was not enough: a wall code left-aligned at its rule line still sat nearer the narrow BASE header. No parent above the run, no sub-tier.

The one that would have been confidently wrong

A DOOR SCHEDULE is not a finish schedule. Those tables carry a MARK column, so the finish hunt indexed one as 54 finish rows on a real grocery set — and a finish code colliding with a door mark chains to a door. Refused by title, only when the title doesn't also say FINISH or MATERIAL (when in doubt, keep), drop named in graph.notes. The test asserts the collision case directly: a DOOR SCHEDULE loaded first with a mark CPT-1, and room 101's floor still chains to Shaw carpet tile.

The rest

  • Legend bleed — the generous right band edge (correct for wide REMARKS) swallowed a finish legend 300 px away; every CEILING cell read SC-1 TL-3 CERAMIC TILE. Generous only for prose-shaped last columns now.
  • SYMBOL-headed finish tables — a set headed SYMBOL | MATERIAL DESCRIPTION | MANUFACTURER | PRODUCT extracted nothing and chained zero definitions. Now chains 165 of 273 finish cells.
  • Apostrophe room namesKID'S CRUNCH reads as a name again.

Numbers

Scored fixtures unchanged at 1.000/1.000 across all three phases (9/9, 33/33, 18/18); 26 lib tests, 166 MCP tests green. On the gym set that drove this: 39/43 rooms resolved, 273 finish cells, 165 chained to a product definition, 4 refusals all correctly named.

Named, not papered over

Keynote and detail bubbles still read as room tags — bare 2-digit numbers (1123 on one set, 1027 on another) come back refusing with "no schedule row". The refusal is honest but the tag was never a room. Distinguishing them needs the bubble's geometry, not its text; staying on #87.

Ships as opentakeoff-mcp 0.9.45.

🤖 Generated with Claude Code

Five bid sets across five GCs, run through scripts/graph-audit.mjs.
Every fix here ships with a fixture reproducing the real failure; none
was reachable from synthetic tests.

- Two-tier headers: WALLS (PLAN DIRECTION) over N|E|S|W. Sub-labels are
  single letters, not vocabulary, so they anchored nothing and the wall
  columns banded to whichever neighbour was nearest -- N/E into BASE,
  S/W into CEILING. BASE read 'VWB-1 - FRP-1, FRP-1A, PT' instead of
  'VWB-1'; a polluted base column is a wrong number in the bid. A run of
  >=2 adjacent non-vocab tokens inside the header span is a sub-tier,
  the parent is the span above that covers the run, and sub-anchors
  carry real BOUNDS (equal-width by drafting convention) rather than
  centers -- a bounded anchor claims only what falls inside it. No
  parent, no sub-tier.
- DOOR/WINDOW/PARTITION schedules are refused as finish tables by title
  (they carry MARK too, and a finish code chaining to a door mark is a
  confidently wrong product). Kept when the title also says FINISH or
  MATERIAL; the drop is named in graph.notes.
- The right band edge is generous only for prose-shaped last columns; a
  legend 300px away no longer bleeds into CEILING.
- SYMBOL/COMMENTS join the finish vocabulary -- a set headed SYMBOL |
  MATERIAL DESCRIPTION | MANUFACTURER extracted nothing and chained
  zero definitions; it now chains 165 of 273 finish cells.
- Room names with apostrophes (KID'S CRUNCH) read as names again.

Named, not papered over: keynote bubbles still read as room tags and
refuse with 'no schedule row' -- honest, but the tag was never a room.
That needs the bubble's geometry; tracked on #87.

opentakeoff-mcp 0.9.45.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@netlify

netlify Bot commented Aug 16, 2026

Copy link
Copy Markdown

Deploy Preview for opentakeoff ready!

Name Link
🔨 Latest commit a1579cc
🔍 Latest deploy log https://app.netlify.com/projects/opentakeoff/deploys/6a81c5a5e5627500080aaa99
😎 Deploy Preview https://deploy-preview-266--opentakeoff.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@QuisutDeus1
QuisutDeus1 merged commit dc5b318 into main Aug 16, 2026
12 checks passed
@QuisutDeus1
QuisutDeus1 deleted the fix/sheetgraph-right-band branch August 16, 2026 14:16
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