Files
willtools-demo/docs/ticket-knowledge-deltas.md
T
will 25592fa6c2
ci / test (push) Successful in 6m14s
WillTools 2026-09-09 -- clean snapshot of the development repo for review
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.
2026-09-09 08:35:15 -05:00

157 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
- `thickness` is returned in **feet** (0.667) under a name that reads as inches.
- ~~`lifters` come back with `x` and `y` as `None`~~ — **retracted, this was my
error.** Each lifter carries `local`, an `(X, Y, Z)` tuple in the panel's own
frame; there are no `x`/`y` keys, and my probe asked for the ones that do not
exist. `local[0]` is measured from the panel **centre**, so
`station = length / 2 + local[0]`. Verified: WP200's four P136 sit at
`local[0] = ±7.208` on a 22.917 ft piece, giving 4.25 ft from the end, and
the ticket's PICKING/STRIPPING diagram prints `4'-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. A
`station_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:
1. **Render the page and look at it.** Extracting a drawing's text stream drops
dimensions without saying so, and produces confident wrong findings.
2. **Both values and both sources, or it is not a finding.**
3. **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.
4. **One root cause is one finding**, however many codes it fans into.
5. **A repeated family pair is one pattern**, not one defect per piece.
6. **Arithmetic before alarm.** 321 against 14 looks like a 23x error until you
divide by the panel length.