History-free snapshot of the private development repository at 77a82eb. Code, docs and the public catalogue only: no plant or job knowledge layers, no client, job or producer names (tools/scrub.py clean against the widened term list; a second word-level grep clean). The intro deck is left out because its slide images cannot be checked for job drawings.
7.3 KiB
What this audit learned, sorted by where it belongs
Three scales. The test for which scale a lesson belongs to is: who would have to change for this to stop being true?
- Plant — a different plant would answer differently. Goes in the knowledge file, never in code. Nothing here should be defaulted, because a wrong default reads as a missing value and the check then quietly does not run.
- Tool — the code has the wrong model of the world. Goes in the repo.
- Method — how to go about looking at all. Goes in the skill.
Plant — entries for the knowledge file
Each is stated with the evidence, because a plant setting nobody can trace back is one nobody dares change.
legend.printed_strand_count_is_per_piece — already false, and correctly so
The design summary for WP1 says (14) 1/2" 270K @ 28,920. The pieces print
their own counts: WP210's section A-A prints (10), WP200's (6), WP199's
(14). The 14 is the design family's figure.
I first wrote this up as a setting to change. It is already false, set at the
job layer — checked against the merged config. So the five STR-QTY entries
are not a misconfiguration: with the flag false the check reports them as WARN
rather than FAIL, which is the intended soft signal that a piece carries fewer
strands than its design family's maximum. Reading a WARN as a defect was my
error, not the tool's.
legend.pattern_prefixes — the concept does not apply here
No sheet in this model carries a view named STRAND PATTERN… or
REINFORCING PATTERN…. 0 of 204. The reinforcing schedule is the bill of
materials table on sheet 1, and the per-piece strand count is inside section
A-A. Until the check is repointed, LGD-MISSING fires on every WP ticket in the
job and takes FC, FCI, PCF-NOTE and STR-NOTE down with it.
The BOM's strand row is linear feet
321 | 0010001 | M392 - 1/2" 270ksi Low Lax Strand on a 22'-11" piece is a
length. Verified on two pieces:
| piece | BOM | panel | BOM / length | section prints |
|---|---|---|---|---|
| WP199 | 321 | 22.9167 ft | 14.007 | (14) |
| WP210 | 249 | 24.9167 ft | 9.993 | (10) |
A checker that reads that row as a quantity reports a 23x error on a correct ticket. This needs to be stated somewhere the tool can read it, because nothing in the row's text says "feet".
interference — P136 is exempt from everything, and a plant group went missing
Decided and applied. exempt_families: [P136] is now in the plant knowledge
file. The reason, in Will's words: the disk anchor is placed to a nominal
position and the crew rotates it on the form to suit, so the modelled
orientation is a starting point rather than the built one. Anything it overlaps
in the model is a consequence of that freedom, not a defect. This is separate
from insert_bars, which exempts the bars belonging to a P136 — that entry
already existed and is correct, and it works by symmetry rather than distance.
But the edit does not take effect yet, and the reason matters more than the
edit. The generated project config is the last layer and it writes out every
key at its merged-at-generation-time value, including exempt_families: []. So
it freezes the past and overrides any later change made upstream. A plant edit
is invisible until the project config is regenerated. Regenerating is Will's to
do, from Revit.
The same mechanism has already lost something: the plant file defines
component_groups:
- name: EMBED P76
families: [SAMPLE_CLIENT_EMBED_P76, SR5602, SR6999]
interferes: within_group
and the merged config carries only the job layer's CONNX TOP OF PANEL TO COLUMN
group. Lists replace rather than merge, so the job layer's single entry deleted
the plant's. The generated config even prints the substitution in its own header
comments — the tool knows, and says so where nobody reads it.
Worth deciding separately: whether component_groups should merge by name
instead of replacing wholesale. As it stands, any layer that wants to add one
group silently discards every group defined above it.
interference.tolerance_in / min_thickness_in
Currently 0.125" with min_thickness_in unset, so thickness defaults to the
same. The recurring overlap is 0.21–0.23". Whether that is acceptance or defect
is a plant answer, and it decides nine findings.
Tool — the code has the wrong model
A ticket is more than one sheet
97 of the tickets in this job are 1 OF 2 + 2 OF 2 under the same sheet name;
9 are 1 OF 1. collect_context resolves a mark to a single sheet and returns
whichever wins. Every ticket read this way is half a ticket, and everything on
the other sheet is reported as missing. On twelve pieces this produced sixty
findings from one cause; across the job it would produce roughly a thousand.
Fix: collect every sheet whose name equals the mark and treat the union as the ticket.
ValueString is not what prints
The handling dimensions carry ValueOverride = U+200E and still print their
value. Any check that decides what the ticket says by reading ValueString, or
by reading ValueOverride and finding it blank, will be wrong in one direction
or the other. What the override is for is not established.
read_ticket field problems
thicknessis returned in feet (0.667) under a name that reads as inches.— retracted, this was my error. Each lifter carrieslifterscome back withxandyasNonelocal, an(X, Y, Z)tuple in the panel's own frame; there are nox/ykeys, and my probe asked for the ones that do not exist.local[0]is measured from the panel centre, sostation = length / 2 + local[0]. Verified: WP200's four P136 sit atlocal[0] = ±7.208on a 22.917 ft piece, giving 4.25 ft from the end, and the ticket's PICKING/STRIPPING diagram prints4'-3". They agree exactly. The comparison that finds real defects was available the whole time.- What is genuinely missing is a named accessor:
local[0]plus an undocumented centre-origin convention is how this went wrong. Astation_ft(lifter, panel)helper would have made the mistake impossible.
tools/rvt.py crashes on hidden characters
Printing a result containing U+200E raises UnicodeEncodeError on a cp1252
console. Force UTF-8 on stdout in the tool rather than making every caller set
PYTHONIOENCODING.
The scrub cannot read a PDF
Exported tickets carry the job name and the client's name in the title block,
and scrub.py scans text. sample data/ and *.pdf are now gitignored, which
is the containment, but the gate itself is blind to them.
Method — how to look
These are in docs/ticket-check.skill.md in full. In short:
- Render the page and look at it. Extracting a drawing's text stream drops dimensions without saying so, and produces confident wrong findings.
- Both values and both sources, or it is not a finding.
- Separate "they disagree" from "I could not find it" — and do not pad the second list. Three items reported as uncheckable were printed on sheet 1.
- One root cause is one finding, however many codes it fans into.
- A repeated family pair is one pattern, not one defect per piece.
- Arithmetic before alarm. 321 against 14 looks like a 23x error until you divide by the panel length.