WillTools: precast shop-ticket QC and panel handling tools
ci / test (push) Has been cancelled

Public demo snapshot of an in-house pyRevit extension for precast concrete
shop-ticket QC (37 checks / 46 checklist rows) and a standalone panel
handling solver (PCI Chapter 8).

- No client, job, plant or product data: knowledge layers ship as
  structural templates only.
- Ticket QC's model-read escalation targets a LAN model server endpoint
  (configurable), not a cloud provider.
- Built from the private development repo via tools/make_dist.py.
This commit is contained in:
2026-09-03 16:33:47 -05:00
commit 52d94303bc
281 changed files with 155656 additions and 0 deletions
+570
View File
@@ -0,0 +1,570 @@
# ============================================================================
# knowledge/catalogue.yaml -- DISTRIBUTION CARVE-OUT, not the real file
# ============================================================================
# Written by tools/make_dist.py's build_catalogue_carveout(), which reads
# the owner's real knowledge/catalogue.yaml and re-emits ONLY the branches
# below -- parsed and re-dumped from the real file, never hand-typed, so
# this cannot drift out of step with what the real file actually publishes.
# The real file itself never leaves the private checkout. See
# knowledge/README.md and CONTRIBUTING.md for the full accounting.
#
# SHIPPED, AND WHY EACH PIECE IS SAFE TO:
#
# face_designations trade abbreviations (N.F., F.F., T.I.F., ...)
# printed on shop tickets everywhere. The real file's
# own header already calls this branch public --
# identifies no client, job, or plant.
# orientation.up_end a fact about precast assemblies IN GENERAL (which
# Revit axis is "up" once an assembly's origin is
# correctly configured), not one plant's naming
# convention -- the owner's own ruling for keeping it
# in the public layer rather than a plant file.
# catalogue.rebar ASTM A706 / A615 grade tables -- a published
# national standard, not a manufacturer's rating.
# catalogue.safety_factors both null, by design -- see the note inline.
# checklist.master the shop-ticket QC checklist's SKELETON: row ids,
# names, grades, and which check function answers
# each one. This tool's own built-in configuration,
# not knowledge about any job -- identifies nobody.
#
# NOT SHIPPED:
#
# catalogue.inserts real lifting-insert capacities (ALP catalog,
# 02/2024), cited to a page and a date. EMPTY here.
# catalogue.slotted_inserts real JVI slotted-insert capacities. Omitted
# entirely (nothing in this distribution's
# tests needs its structure present at all).
# connectors.products real sandwich-wall tie capacities. EMPTY here.
#
# A handful of tests read those omitted tables directly and assert the
# owner's real published numbers. They are excluded from this
# distribution's test run, by name, with that reason -- see
# tools/make_dist.py's append_test_exclusions() and CONTRIBUTING.md.
# ============================================================================
face_designations:
frames:
view:
means: Relative to the viewing direction of the drawing. It flips when the view flips, so resolving
one of these tokens requires knowing which way the elevation looks at the piece.
sides:
- near
- far
- both
form:
means: Relative to the casting bed -- how the piece lies while it is poured. Absolute for the piece;
a flipped view does not change it.
sides:
- top
- bottom
- side
- both
vocabularies:
near_far:
frame: view
measured_from: the direction the elevation looks at the piece
tokens:
- token: N.F.
means: near face
side: near
- token: F.F.
means: far face
side: far
- token: E.L.
means: each layer
side: both
in_form:
frame: form
measured_from: the casting bed the piece is poured on
tokens:
- token: T.I.F.
means: top in form
side: top
- token: B.I.F.
means: bottom in form
side: bottom
- token: S.I.F.
means: side in form
side: side
orientation:
up_end:
source: assembly_origin
also_called: TOT
stated_by: Will
stated_on: '2026-08-30'
means: Which end of a precast piece is up once it is erected is a property of the assembly's origin,
which is placed with the assembly and carries an up end. It is not derived from where the piece
happens to sit in the model, and it is not a producer's convention.
origin_up: BasisY
origin_up_as_stated: '"assembly origin 里面有一个朝上的头" -- the assembly origin itself carries an up end.'
origin_up_verified: true
origin_up_verified_by: the bridge holder, against 282 assemblies
origin_up_verified_on: '2026-08-30'
also_seen_as:
horizontal_panels:
stated_by: Will
stated_on: '2026-08-30'
status: confirmed against 282 assemblies -- see origin_up above
green:
axis: BasisY
means: the erected up direction
purple:
axis: BasisZ
means: top-in-form
red:
axis: BasisX
means: the long direction
note: The API exposes no colour at all; this three-arrow mapping is a reading of the owner's words
(green / purple / red), and it is CONFIRMED because the measurement behind origin_up above --
BasisY exactly global (0,0,1) on 281 of 282 assemblies, BasisZ the smallest extent on 25 of
26 sampled, BasisX the longest on 23 of 26 -- is the same measurement that stands the colours
up.
vertical_wall_panels:
stated_by: Will
stated_on: '2026-09-01'
status: ONE of three arrows confirmed. Do not treat this frame as complete and do not borrow purple
or red from horizontal_panels above -- the owner's own words are that the arrows are different
between the two frames to begin with, so nothing here may be assumed from there.
green:
axis: BasisY
means: world up (world Z+) when the panel is correctly configured
confirmed: true
stated_as: '"vertical wall panel里面,世界的上方应该是绿色箭头" -- in a vertical wall panel, world up should
be the green arrow.'
purple:
axis: null
means: null
confirmed: false
open_question: Not yet stated. A vertical wall panel's casting orientation (top-in-form) is
not necessarily on the same axis as a horizontal panel's -- do not infer BasisZ here. Asked
of the owner 2026-09-01; record the answer here, cited and dated, the day it arrives.
red:
axis: null
means: null
confirmed: false
open_question: Not yet stated. Do not infer BasisX (the horizontal frame's "long direction")
here -- on a vertical wall panel BasisY already carries a different meaning (world up) from
the horizontal frame's (erected up when stood on end), so nothing about red follows from the
horizontal row either. Asked of the owner 2026-09-01; record the answer here, cited and dated,
the day it arrives.
applies_to: horizontal_panels
up_tolerance: 0.99
near_square_ratio: 1.25
declines_because: A piece whose origin does not agree with its geometry, a vertical panel whose frame
nobody has explained yet, and a near-square piece that could be either are three different reasons
to have no answer. All three are answers; none of them is a default.
wp401_2026_09_01: 'WP401 is NOT an instance of applies_to declining -- it never reaches that third
check. Its measured basis_up is (0, 1, 0), so up_end_from_origin()''s FIRST refusal (the up basis
must actually be world up, within up_tolerance) fires before up_axis or applies_to are ever read;
the report''s fallback-to-global-elevation notice on WP401 is that first refusal, not the third.
Under the green-arrow rule above (vertical_wall_panels), a correctly configured vertical wall panel''s
BasisY IS world up -- so WP401''s (0, 1, 0) is a real defect on that assembly''s origin (TOT), not
merely an unconfirmed frame; the report''s red line follows from this fact, not from applies_to.
Consequence for the code, worked out and not acted on: widening applies_to to admit vertical_wall_panels
would NOT change WP401''s verdict -- refusal #1 still fires first on it regardless. It WOULD change
any piece whose origin genuinely has BasisY at world up AND whose up_axis is not ''width'': such
a piece currently declines at refusal #3 (fallback to global elevation, disclosed) and would start
being read off the origin instead (the ruled mechanism, undisclosed because it is no longer a fallback).
No such piece has been surveyed. That survey, and the decision whether to widen applies_to on the
strength of it, is the owner''s, not made here.'
origin_point_meaning: null
origin_point_unverified_because: Nobody has measured where Transform.Origin sits relative to the piece,
and nobody has asked whether the owner's "up end" means the point or the direction. Until one of
those happens the point is not read at all.
catalogue:
safety_factors:
tension_fos: null
shear_fos: null
unknown_because: There is no trade-wide safety factor on a lifting insert to publish here. A factor
belongs to the part that was tested, so it is written inside each `inserts:` entry against the page
that publishes it. The 2.67 that used to sit here had no source and the manufacturer's own page
gives 4:1 in shear for the parts it covers; see the block above. A part with no entry of its own
is NOT judged on an ultimate rating -- it is named as unjudged, because inheriting one manufacturer's
factor is exactly the failure this null exists to prevent.
inserts: {}
rebar:
stock_length_ft: 40.0
astm_grades:
A706:
grades_ksi:
- 60
- 80
default_fy_ksi: 60
default_declared_by: Will
default_declared_on: '2026-08-30'
note: Grade 60 is the default, not the definition -- A706 Grade 80 exists.
A615:
grades_ksi:
- 60
- 80
- 100
default_fy_ksi: null
note: the designation alone does not give a grade -- ask, do not assume.
connectors:
what_it_is: The part that crosses the insulation of a sandwich (insulated) wall panel and ties the two
concrete wythes together. Declared by the owner 2026-08-31.
products: {}
checklist:
master:
- id: '1.1'
name: Sheet name equals the piece mark
grade: A
owner_codes:
- SHEET-NAME
not_run_reason: null
checks: check_sheet_name
- id: '1.2'
name: Sheet design-number reduces to the piece design
grade: A
owner_codes:
- DSN-MATCH
- DSN-SUFFIX
- DSN-PREFIX
not_run_reason: null
checks: null
- id: '1.3'
name: Exactly one ticket set per piece
grade: A
owner_codes:
- TICKET-SET
not_run_reason: null
checks: check_ticket_set
- id: '1.4'
name: Every placed view name refers to this design
grade: B
owner_codes:
- VIEW-DSN
not_run_reason: null
checks: check_view_name_design
- id: '1.5'
name: Printed call-outs do not overlap each other
grade: C
owner_codes:
- CALLOUT-OVERLAP
not_run_reason: null
checks: check_callout_overlap
- id: '2.1'
name: Printed length/width/depth vs modelled
grade: B
owner_codes:
- SIZE-LENGTH
- SIZE-WIDTH
- SIZE-MAX-
- SIZE-MIN-
not_run_reason: null
checks: null
- id: '2.2'
name: Weight three ways agree, and which one is odd is named
grade: A
owner_codes:
- WGT-
not_run_reason: null
checks: check_weight_three_way
- id: '2.3'
name: Unit weight ticket vs design summary
grade: A
owner_codes:
- PCF-NOTE
- PCF-MODEL
not_run_reason: null
checks: null
- id: '2.4'
name: Cast extras (a ledge is its own family) counted in the weight
grade: A
owner_codes:
- CAST-EXTRA
not_run_reason: null
checks: check_cast_extras
- id: '3.1'
name: f'c ticket vs summary
grade: A
owner_codes:
- FC
not_run_reason: null
checks: null
- id: '3.2'
name: f'ci ticket vs summary
grade: A
owner_codes:
- FCI
not_run_reason: null
checks: null
- id: '3.3'
name: f'ci/f'c release ratio in band
grade: B
owner_codes:
- FCI-RATIO
not_run_reason: null
checks: check_release_ratio
- id: '4.1'
name: Printed strand count vs modelled
grade: B
owner_codes:
- STR-QTY
not_run_reason: null
checks: null
- id: '4.2'
name: Strand diameter & grade vs design
grade: A
owner_codes:
- STR-DIA
- STR-DIA-EXTRA
not_run_reason: null
checks: null
- id: '4.3'
name: Jacking force on ticket vs design
grade: A
owner_codes:
- JACK-FORCE
not_run_reason: null
checks: check_jacking_force
- id: '4.4'
name: Strand positions vs design chain from stated rail
grade: B
owner_codes:
- STRAND-POS
not_run_reason: null
checks: check_strand_layout
- id: '4.5'
name: Debonded strands called out where the design debonds
grade: C
owner_codes:
- STRAND-CALLOUT
not_run_reason: null
checks: check_debond_callout
- id: '4.6'
name: Row count & spacing plausible
grade: A
owner_codes:
- STRAND-SPACING
- STRAND-ROWS
- STRAND-GRID
- BED-WIDTH
- BED-OFFSET
not_run_reason: null
checks: check_strand_layout
- id: '4.7'
name: Strand debonded wherever the concrete runs short
grade: B
owner_codes:
- STRAND-DEBOND
not_run_reason: null
checks: check_strand_debond
- id: '4.8'
name: BOM strand row agrees with the section print and the model
grade: A
owner_codes:
- BOM-STRAND
not_run_reason: null
checks: check_bom_strand_count
- id: '5.1'
name: BED PLAN callout embed exists in model
grade: A
owner_codes:
- BOM-MEMBERS
- DETAIL-CALLOUT
not_run_reason: null
checks:
- check_bom_members
- check_detail_callouts
- id: '5.2'
name: Embed in model appears on ticket
grade: A
owner_codes:
- BED-REVERSE
not_run_reason: null
checks: check_bed_plan_reverse
- id: '5.3'
name: Face designations consistent with model side
grade: C
owner_codes: null
not_run_reason: 'grade C: a person reads the face designations against the model side -- by design
no check computes this row, so it is a prompt to look and never a verdict'
checks: null
- id: '5.4'
name: Mesh / WWF designation vs design
grade: A
owner_codes:
- WWF
not_run_reason: null
checks: check_wwf_designation
- id: '5.5'
name: Bar marks legible on the drawing
grade: D
owner_codes: null
not_run_reason: 'grade D: a person reads the drawing; code only guarantees the question was asked'
checks: null
- id: '5.6'
name: Bar marks unique, and model and print name the same bars
grade: B
owner_codes:
- BARMARK-UNIQUE
not_run_reason: null
checks: check_bar_mark_uniqueness
- id: '5.7'
name: No bar longer than the stock it is cut from
grade: B
owner_codes:
- BAR-LENGTH
not_run_reason: null
checks: check_bar_stock_length
- id: '5.8'
name: Connectors present on an insulated panel
grade: B
owner_codes:
- CONNECTOR-EXIST
not_run_reason: null
checks: check_connectors_exist
- id: '5.9'
name: Enough connectors for what the design calls for
grade: B
owner_codes:
- CONNECTOR-COUNT
not_run_reason: null
checks: check_connectors_sufficient
- id: '5.10'
name: Connector edge distances
grade: B
owner_codes:
- CONNECTOR-EDGE
not_run_reason: null
checks: check_connector_edge_distance
- id: '5.11'
name: Every lifter's solid zone is a member of the assembly
grade: B
owner_codes:
- SOLID-ZONE-ASM
- SOLID-ZONE-ABSENT
not_run_reason: null
checks: check_solid_zone_members
- id: '5.12'
name: Solid zones appear on the ticket's insulation layout
grade: B
owner_codes:
- SOLID-ZONE-TICKET
not_run_reason: null
checks: check_solid_zone_on_ticket
- id: '5.13'
name: Solid zone hatch matches the legend swatch
grade: B
owner_codes:
- SOLID-ZONE-HATCH
not_run_reason: null
checks: check_solid_zone_hatch
- id: '5.14'
name: Insulation recess regions present where the design calls for them
grade: C
owner_codes:
- RECESS-PRESENT
not_run_reason: null
checks: check_recess_regions
- id: '5.15'
name: Recess region hatch matches the legend swatch
grade: B
owner_codes:
- RECESS-HATCH
not_run_reason: null
checks: check_recess_hatch
- id: '6.1'
name: Insert capacity vs load
grade: A
owner_codes:
- LIFT-CAPACITY
not_run_reason: null
checks: check_lifter_capacity
- id: '6.2'
name: Insert edge distances
grade: A
owner_codes:
- LIFT-EDGE
not_run_reason: null
checks: check_lifter_edge_distance
- id: '6.3'
name: Current handling result exists & passes
grade: A
owner_codes:
- HANDLE-
not_run_reason: null
checks: check_handling_result
- id: '6.4'
name: Dunnage not under an opening
grade: A
owner_codes:
- DUN-OPENING
not_run_reason: null
checks: check_dunnage_openings
- id: '6.5'
name: DUNNAGE / ERECTION / PICKING notes say something
grade: B
owner_codes:
- NOTE-CONTENT
not_run_reason: null
checks: check_note_views
- id: '6.6'
name: Odd part count carries the BED PLAN note it requires
grade: B
owner_codes:
- PARITY-NOTE
not_run_reason: null
checks: check_parity_note
- id: '6.7'
name: Minimum spacing between lifting anchors
grade: A
owner_codes:
- LIFT-SPACING
not_run_reason: null
checks: check_lifter_anchor_spacing
- id: '6.8'
name: Printed picking stations match the modelled picking inserts
grade: B
owner_codes:
- PICK-STATIONS
- PICK-UNREADABLE
not_run_reason: null
checks: check_picking_match
- id: '6.9'
name: Lifting-point count vs panel length (MC)
grade: A
owner_codes:
- LIFT-POINTS
- LIFT-POINTS-UNREAD
not_run_reason: null
checks: check_lifting_points
- id: '6.10'
name: Lifting-point position vs PCI recommendation (MC)
grade: A
owner_codes:
- LIFT-POS
- LIFT-POS-UNREAD
not_run_reason: null
checks: check_lift_positions
- id: '6.11'
name: Dunnage-point count vs stripping-point count (MC)
grade: A
owner_codes:
- DUN-STRIP
- DUN-STRIP-UNREAD
not_run_reason: null
checks: check_dunnage_stripping_match
- id: '7.1'
name: Interference check
grade: B
owner_codes:
- CLASH
- CLASH-UNREADABLE
not_run_reason: null
checks: check_member_interference
- id: '8.1'
name: No unresolved design-summary lines
grade: C
owner_codes:
- SPEC-UNRESOLVED
not_run_reason: null
checks: check_spec_unresolved
- id: '8.2'
name: No invisible characters in ticket text
grade: A
owner_codes:
- INVISIBLE
not_run_reason: null
checks: check_invisible