sweep_schedule_row
Mints a condition from a schedule row's tag and sweeps every plan sheet for matching markers, counting only where geometry and the row's tag agree on the same bubble.
Instructions
Take off a schedule row's mark from the row itself — the estimator's own gesture: a transition type sometimes exists only as a schedule row plus tag markers scattered across the plan sheets, and this tool mints the condition FROM the row and finds every occurrence. Pass the row's key (e.g. 'T1') and the tool (1) reads the row from the set's schedule tables (the sheet_graph/find_schedule machinery — the row is the condition's cited source), (2) anchors a geometric fingerprint on the marker the tag is DRAWN as on a plan sheet (a deterministic pad ladder around the tag text; where the tag occurs more than once the fingerprint must recur at a second occurrence before it is trusted — anchor.corroborated), and (3) sweeps every PLAN-role sheet for it. The count is geometry AND text agreeing: drafting reuses one bubble shape across many marks, so a match counts ONLY when the row's own tag sits within the marker footprint (its bbox rides the match as tag_at evidence); a match labeled with a SIBLING row's tag is excluded and says whose it is, an unlabeled match is withheld as a question, and a tag drawn with no matching marker is disclosed as text_only. REFUSAL over guessing, with the reason and the fix: no such row; the same key in two tables (ambiguous); a tag drawn on no plan sheet; no repeatable marker linework around the tag — a fingerprint is never guessed from text alone (the fallback is always: marquee one instance with symbol_sweep). commit: true commits the counted matches as EA markers under the row's own key — one undo step for the whole set-wide sweep, every marker carrying origin.assignment {source: "schedule"} plus the anchor and row citation on origin.symbol.seed. The COUNT is scale-free (EA), but matching is not: where the anchor sheet and a target sheet both carry a scale, the marker is resized by their exact ratio before matching (scaled per sheet), and where one does not, the sweep runs at 1:1 and discloses it (scale_assumed) rather than reporting a confident zero. After committing, LOOK: view_sheet {overlay: true} over each swept sheet. Coordinates are image px at render scale 2.0: PDF pt × 2, origin top-left, y down (the browser canvas's native space). Sheet payloads carry dims in both px and pt. LABEL-FIRST for devices (any trade): when the marker cannot be fingerprinted or does not reach a drawn tag amid linework — a heater bar or fan drawn to its own size, tagged by a leader — every such tag on a plan sheet counts as ONE instance BY LABEL, disclosed in found_by_label / label_only / counted_by; a bare mention in a note (no linework near it) is text_only, never a count. Rows come from every schedule family the sheet graph reads: room-finish, finish/material, and equipment (mechanical, electrical, plumbing, fire).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | The schedule row's key exactly as drawn, e.g. 'T1', 'TR-2' — it becomes the condition tag on commit | |
| commit | No | Commit every counted match as one EA count marker (excluded/withheld/text_only never commit) | |
| mirror | No | Also match mirrored markers | |
| rotations | No | Also match 90/180/270-rotated markers | |
| tolerance_px | No | Endpoint match tolerance in image px (default 2 — CAD jitter, not drift) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| row | Yes | The schedule row the sweep was seeded from — the condition's source | |
| tag | Yes | The row key as normalized (the tag as drawn) | |
| note | No | ||
| found | Yes | Instances counted across every plan sheet: geometry matches carrying the row's own tag PLUS drawn tags counted by label — see counted_by | |
| anchor | Yes | null when the sweep counted BY LABEL: no repeatable marker geometry sits around the drawn tag (the equipment convention — a device drawn to its own size, tagged by a leader), so nothing was fingerprinted | |
| sheets | Yes | One entry per swept PLAN-role sheet, load order | |
| skipped | Yes | Sheets excluded from counting (schedule/detail/legend/unknown), each with its reason | |
| warning | No | Present when the per-sheet work cap dropped candidates | |
| complete | Yes | True when every proposed placement was scored on every swept sheet — false means at least one sheet's count is a FLOOR, not a total (#261) | |
| ea_total | No | ||
| committed | No | commit mode: count shapes committed — one per counted match, the whole sweep ONE undo step | |
| condition | No | commit mode: the condition minted FROM the row — its key is the tag | |
| shape_ids | No | ||
| counted_by | Yes | How the count was made — "label" means no marker geometry was matched at all; look at each label_only placement before pricing | |
| found_by_label | Yes | …of which drawn tags amid linework the fingerprint did not (or could not) reach — an installed instance by the equipment convention, disclosed as label-counted | |
| found_by_geometry | Yes | …of which marker-fingerprint matches corroborated by the tag |