8e6ee31596
ci / test (push) Successful in 6m18s
History-free snapshot of the private development repository at cbe45c5 (2026-09-09). Code, docs and public catalogue only; no plant or job knowledge layers, no client or job names (tools/scrub.py clean). The intro deck is left out of this snapshot because its slide images could not be checked for job drawings.
3206 lines
147 KiB
YAML
3206 lines
147 KiB
YAML
# Published hardware data. THE PUBLIC LAYER.
|
||
#
|
||
# This file IS part of the repository, and it is the only knowledge layer that
|
||
# is. Nothing here identifies a client, a job or a plant: it is manufacturers'
|
||
# catalogue data, the same for everyone who buys the part.
|
||
#
|
||
# It is still data rather than code. A rated load written into a .py file is a
|
||
# number nobody can correct without a release, and it will be wrong eventually.
|
||
#
|
||
# Read FIRST, before the plant file and the job file, so either can override an
|
||
# entry -- for a part tested differently, or a rating an engineer will not
|
||
# accept.
|
||
#
|
||
# The plant layer says which catalogue part its own part number means:
|
||
#
|
||
# family in the model -> lifters.catalogue_alias -> catalogue.inserts
|
||
# (plant knowledge) (here)
|
||
|
||
# ==========================================================================
|
||
# FACE DESIGNATIONS -- the parenthetical suffix on a bar or embed call-out.
|
||
# ==========================================================================
|
||
#
|
||
# A ticket calls a bar out as `SR324 (F.F.)`, `SR310 (E.L.)`,
|
||
# `P76 W/ SR5602 (S.I.F.)`. The suffix says WHICH FACE of the piece the part
|
||
# goes on. Checklist 5.3 asks whether it agrees with the side the model
|
||
# actually puts the part on.
|
||
#
|
||
# WHY THESE ARE PUBLIC. They are the trade's abbreviations, printed on
|
||
# tickets everywhere, and they identify no client, no job and no producer --
|
||
# which is the whole test for what belongs in this file. What is NOT public
|
||
# is WHICH SET a given producer uses: that is a house habit, so the plant
|
||
# layer SELECTS from here by id (`face_designations.use: [near_far, in_form]`)
|
||
# and never copies the tokens down.
|
||
#
|
||
# A producer using a token nobody published states its own vocabulary in its
|
||
# own plant file -- `vocabularies` is a MAP, so it deep-merges and a new
|
||
# vocabulary is an addition, not an edit to these.
|
||
#
|
||
#
|
||
# THE ONE THING THIS SHAPE EXISTS TO PRESERVE
|
||
# -------------------------------------------
|
||
# The two families below are measured FROM DIFFERENT THINGS and are not
|
||
# interchangeable:
|
||
#
|
||
# near / far measured from the VIEWING DIRECTION. It flips when
|
||
# the view flips. If an elevation looks at the panel
|
||
# from the opposite side than was assumed, every
|
||
# N.F./F.F. on that sheet is backwards -- and each one
|
||
# individually still reads perfectly normal.
|
||
#
|
||
# top / bottom in form
|
||
# measured from the CASTING BED. Absolute for the
|
||
# piece. A flipped view does not touch it.
|
||
#
|
||
# Flattening both into one token -> meaning map would throw away exactly the
|
||
# distinction that makes 5.3 decidable, so every vocabulary DECLARES ITS
|
||
# FRAME and a reader resolves a token against that frame's evidence.
|
||
#
|
||
#
|
||
# SHAPE
|
||
# -----
|
||
# frames: the closed set of frames of reference. A vocabulary
|
||
# naming a frame that is not here is a mistake, and a
|
||
# loud one -- see knowledge.config_problems.
|
||
# vocabularies: id -> { frame, measured_from, tokens }
|
||
# tokens: a LIST of { token, means, side }.
|
||
# `token` exactly as printed, dots and all.
|
||
# `means` what it is short for, in words, so a
|
||
# report can print it to a reader who has
|
||
# never seen the abbreviation.
|
||
# `side` the normalised symbol a check compares on,
|
||
# read WITHIN this vocabulary's frame. Never
|
||
# compare a `side` from one frame against a
|
||
# `side` from another.
|
||
#
|
||
# A LIST rather than a map, on purpose: a token is written `N.F.` and a
|
||
# dotted key cannot be reached by `knowledge.get(know, 'a.b.c')` at all.
|
||
# It also makes a published vocabulary ATOMIC -- lists replace, so nobody
|
||
# half-edits one of these; they declare their own instead.
|
||
#
|
||
# Adding a third vocabulary is a new entry under `vocabularies`. No schema
|
||
# change, no code change.
|
||
#
|
||
#
|
||
# THE MODEL-SIDE HALF (shape only -- every value below is plant knowledge)
|
||
# -----------------------------------------------------------------------
|
||
# A face designation is printed on a ticket AND recorded on the element, and
|
||
# 5.3 asks whether the two agree. The keys a plant states for the second one,
|
||
# all of them siblings of `use` and `vocabularies`:
|
||
#
|
||
# model_tokens what the element's field holds -> the printed
|
||
# designation. A MAP, so it deep-merges. SEPARATE from the
|
||
# vocabularies rather than an alias on a token, because
|
||
# `tokens` is a list and lists replace -- a plant aliasing
|
||
# a published token would replace the whole published
|
||
# vocabulary.
|
||
# read_from where that field is read. `[instance]`, and NOT
|
||
# `[instance, type]` the way the reinforcing rule is:
|
||
# measured over a real ticket corpus, the same part code
|
||
# carries different face tokens on different sheets, so
|
||
# the face is a property of the PLACEMENT. A type read
|
||
# collapses distinct facts onto one answer and looks
|
||
# clean doing it.
|
||
# modifiers tokens that STACK AFTER a face token in the same
|
||
# call-out -- `P106 (S.I.F.) (E.S.)` -- and say something
|
||
# other than which face. A modifier is orthogonal to the
|
||
# face axis, so it has no (frame, side) and cannot be a
|
||
# vocabulary entry; a reader strips it and resolves the
|
||
# face underneath. A reader expecting exactly one
|
||
# parenthesised group mis-parses the pair, which is the
|
||
# whole reason this key exists.
|
||
# not_face_tokens groups that pattern-match a face designation and are
|
||
# not one. The negative has to be written down or it
|
||
# returns as a false positive.
|
||
# attaches_to token -> the member kinds it may attach to ('embed',
|
||
# 'bar'). Real grammar, measured, and a check waiting to
|
||
# be written; DATA rather than a rule buried in one.
|
||
# recorded_on the member kinds whose elements record a face at all.
|
||
# Empty means NOBODY HAS SAID -- never "none". It is what
|
||
# tells a blank on a kind that does record faces
|
||
# (unknown) from a blank on a kind that never does (does
|
||
# not apply).
|
||
# top_in_form the LABEL under which a piece states which building
|
||
# face ends up on top in the form. That value is PER
|
||
# PIECE and it varies, so a form-anchored token cannot be
|
||
# resolved to a building face without reading it --
|
||
# `knowledge.building_face_of()` refuses instead of
|
||
# assuming a handedness, because assuming one is not
|
||
# slightly wrong, it is inverted on half a job.
|
||
#
|
||
# NOTHING HERE EVER READS ABSENCE AS A VALUE, and no key may be added that
|
||
# does. An unmarked call-out is annotation that was not repeated; a blank
|
||
# field is a kind that does not use it. `same_face()` answering None rather
|
||
# than False is the instrument for that.
|
||
#
|
||
# This section sits ABOVE `catalogue:` because `vibe.yamlkit` -- the host-side
|
||
# reader the test suite uses -- used to stop at the first folded scalar (`>-`),
|
||
# and there is one under `inserts`, so everything below it was invisible to
|
||
# every test that read this file. That is fixed (yamlkit now reads block
|
||
# scalars) and the section stays here anyway: face designations are not
|
||
# hardware, and the file reads better with them beside `catalogue:` rather
|
||
# than buried under it.
|
||
|
||
face_designations:
|
||
|
||
# -> rationale.md § face_designations.frames
|
||
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:
|
||
|
||
# -> rationale.md § face_designations.vocabularies.near_far
|
||
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
|
||
|
||
# ------------------------------------------------------------------
|
||
# CASTING ORIENTATION, seen from the bed. T.I.F. / B.I.F. are as common
|
||
# at other producers as N.F. / F.F. are here, and S.I.F. turns up
|
||
# alongside the near/far set on the same ticket -- which is exactly why
|
||
# a plant may select two vocabularies at once.
|
||
# ------------------------------------------------------------------
|
||
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
|
||
|
||
|
||
# sources: 2026-08-30
|
||
# -> rationale.md § orientation
|
||
|
||
orientation:
|
||
|
||
up_end:
|
||
|
||
# THE RULE. `assembly_origin` is the only value this reads today; another
|
||
# string reads as "somebody wrote a mechanism nobody implemented", and
|
||
# `up_end_rule()` stands down and quotes it back rather than guessing.
|
||
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.
|
||
|
||
# -> rationale.md § orientation.up_end.origin_up
|
||
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'
|
||
|
||
# -> rationale.md § orientation.up_end.also_seen_as
|
||
# TWO DISTINCT FRAMES, not one rule with wider coverage. Owner,
|
||
# 2026-09-01, on being shown this file: "分开,horizontal panel跟
|
||
# vertical panel,三个箭头的方向本来就是不一样的。这个应该进世界知识。"
|
||
# -- separate them; horizontal and vertical panels have different
|
||
# meanings for all three arrows to begin with; this belongs in world
|
||
# knowledge. So: this key used to be one string covering one (inferred)
|
||
# mapping. It is now a mapping of TWO frames, each with its own three
|
||
# arrows, each fact cited to who said it and when, and NEITHER frame may
|
||
# borrow a colour's meaning from the other -- that borrowing is exactly
|
||
# the mistake this restructure exists to prevent.
|
||
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.
|
||
|
||
# -> rationale.md § orientation.up_end.applies_to
|
||
# CODE READS THIS FIELD VERBATIM -- up_end_from_origin() in
|
||
# WillTools.extension/lib/vibe/knowledge.py (~line 3269) declines its
|
||
# THIRD check when applies_to == 'horizontal_panels' and the piece's
|
||
# up_axis is not 'width' (i.e. the piece is not lying/erected horizontal).
|
||
# LEFT UNCHANGED here on purpose. also_seen_as above is DATA about what
|
||
# the three arrows mean on each frame; it is not a claim that the ruled
|
||
# mechanism is now confirmed to run on a vertical panel, and widening
|
||
# this value would make up_end_from_origin() stop declining there -- a
|
||
# change to real verdicts on real pieces, and the owner's to make, not
|
||
# this landing's. See wp401_2026_09_01 below for the one real piece this
|
||
# was checked against and what widening would and would not change on it.
|
||
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.
|
||
|
||
# -> rationale.md § orientation.up_end.wp401_2026_09_01
|
||
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.
|
||
|
||
# -> rationale.md § orientation.up_end.origin_point_meaning
|
||
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:
|
||
|
||
# * 2.67 HAD NO SOURCE. Nothing published it, nobody typed it, and no
|
||
# sources: p53; 2026-08-30 2026-08-31
|
||
# -> rationale.md § catalogue.safety_factors
|
||
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:
|
||
|
||
# sources: p53
|
||
# -> rationale.md § catalogue.inserts.QLPD2T3WG
|
||
|
||
QLPD2T3WG:
|
||
working_load_lb: 4000
|
||
shear_load_lb: 4000
|
||
ultimate_tension_lb: 16000
|
||
min_edge_distance_in: 6
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP catalog p53, 02/2024 -- "Capacity in Concrete 4:1
|
||
SWL", the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP catalog p53, 02/2024 -- footnote, "Minimum anchor
|
||
spacing is 2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
lifting_wythe_in: 3
|
||
clutch: QL001 (2T-3T)
|
||
|
||
QLPD4T3WG:
|
||
working_load_lb: 6257
|
||
shear_load_lb: 6257
|
||
ultimate_tension_lb: 32000
|
||
min_edge_distance_in: 6
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP catalog p53, 02/2024 -- "Capacity in Concrete 4:1
|
||
SWL", the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP catalog p53, 02/2024 -- footnote, "Minimum anchor
|
||
spacing is 2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
lifting_wythe_in: 3
|
||
clutch: QL002 (4T-6T)
|
||
|
||
QLPD4T4WG:
|
||
working_load_lb: 7200
|
||
shear_load_lb: 7200
|
||
ultimate_tension_lb: 32000
|
||
min_edge_distance_in: 7.5
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP catalog p53, 02/2024 -- "Capacity in Concrete 4:1
|
||
SWL", the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP catalog p53, 02/2024 -- footnote, "Minimum anchor
|
||
spacing is 2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
lifting_wythe_in: 4
|
||
clutch: QL002 (4T-6T)
|
||
|
||
QLPD4T5WG:
|
||
working_load_lb: 8000
|
||
shear_load_lb: 8000
|
||
ultimate_tension_lb: 32000
|
||
min_edge_distance_in: 9
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP catalog p53, 02/2024 -- "Capacity in Concrete 4:1
|
||
SWL", the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP catalog p53, 02/2024 -- footnote, "Minimum anchor
|
||
spacing is 2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
lifting_wythe_in: 5
|
||
clutch: QL002 (4T-6T)
|
||
note: >-
|
||
shear must act perpendicular to the anchor face and the centreline of
|
||
the recess; pulling in shear parallel to the face can spall the
|
||
concrete and overload the anchor
|
||
|
||
QLPD8T6WG:
|
||
working_load_lb: 11019
|
||
shear_load_lb: 11019
|
||
ultimate_tension_lb: 64000
|
||
min_edge_distance_in: 11
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP catalog p53, 02/2024 -- "Capacity in Concrete 4:1
|
||
SWL", the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP catalog p53, 02/2024 -- footnote, "Minimum anchor
|
||
spacing is 2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
lifting_wythe_in: 6
|
||
clutch: QL003 (8T-12T)
|
||
|
||
QLPD8T7WG:
|
||
working_load_lb: 14640
|
||
shear_load_lb: 14640
|
||
ultimate_tension_lb: 64000
|
||
min_edge_distance_in: 12.5
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP catalog p53, 02/2024 -- "Capacity in Concrete 4:1
|
||
SWL", the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP catalog p53, 02/2024 -- footnote, "Minimum anchor
|
||
spacing is 2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
lifting_wythe_in: 7
|
||
clutch: QL003 (8T-12T)
|
||
|
||
QLPD8T8WG:
|
||
working_load_lb: 16000
|
||
shear_load_lb: 16000
|
||
ultimate_tension_lb: 64000
|
||
min_edge_distance_in: 14
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP catalog p53, 02/2024 -- "Capacity in Concrete 4:1
|
||
SWL", the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP catalog p53, 02/2024 -- footnote, "Minimum anchor
|
||
spacing is 2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
lifting_wythe_in: 8
|
||
clutch: QL003 (8T-12T)
|
||
|
||
# sources: p16-18 (LIFTING PIN SYSTEM, "ALP Lifting Pin Anchors" /
|
||
# "ALP Lifting Pin Anchors capacity in concrete"); 2026-09-07
|
||
# -> rationale.md § catalogue.inserts.LPA4T512G
|
||
LPA4T512G:
|
||
manufacturer: ALP
|
||
ton: 4T
|
||
clutch: QL002 (4T-6T)
|
||
dimensions_in: {L: 5.5, HD: 1.4375, RD: 0.75, FD: 2}
|
||
ultimate_mechanical_tension_lb: 32000
|
||
weight_lb: 1.05
|
||
qty_per_bag: 50
|
||
qty_per_crate: 2000
|
||
head_marking: ALP 4T 512
|
||
# NOT one basis + sqrt(f'c) -- published at FOUR discrete concrete
|
||
# strengths, and capacity keeps RISING past 3,500 psi (6,950 lb at
|
||
# 3,500 -> 8,000 lb at 5,000, +15%), which concrete_derate()'s "no
|
||
# gain above basis" rule would silently cap at 6,950. So no
|
||
# working_load_lb / basis_fc_psi is set on this entry -- that would
|
||
# invite the generic derate formula to run on a table it does not
|
||
# fit -- and the four points land as their own table instead.
|
||
working_load_lb: null
|
||
basis_fc_psi: null
|
||
unrated_because: >-
|
||
rated at four discrete concrete strengths (by_fc_psi below), not a
|
||
single basis + sqrt(f'c) -- see the comment above this entry
|
||
by_fc_psi:
|
||
- {fc_psi: 1500, tension_lb: 4550}
|
||
- {fc_psi: 2500, tension_lb: 5850}
|
||
- {fc_psi: 3500, tension_lb: 6950}
|
||
- {fc_psi: 5000, tension_lb: 8000}
|
||
# TENSION edge distance -- what lifter_edge_distance() reads.
|
||
min_edge_distance_in: 11
|
||
# SHEAR edge distance is larger and is its own field on purpose: the
|
||
# page prints two DIFFERENT minimums (11in tension / 17in shear) and
|
||
# folding them into one number would either overstate the tension
|
||
# case or understate the shear one. No reader consumes this scalar
|
||
# yet -- lifter_edge_distance() is single-valued and reads the
|
||
# tension figure above.
|
||
min_edge_distance_shear_in: 17
|
||
# No published shear LOAD for this part -- p18's SWL columns are
|
||
# TENSION only (headed "Capacity in Concrete, 4:1 SWL", four PSI
|
||
# columns); shear appears only as the larger minimum edge distance
|
||
# above, never as a rated load. Naming it unjudged rather than
|
||
# borrowing another product's shear or guessing a factor.
|
||
shear_load_lb: null
|
||
shear_unknown_because: >-
|
||
ALP Catalog 2024 p18 tabulates tension by concrete strength only
|
||
for the LPA series; it publishes a minimum shear EDGE DISTANCE
|
||
(17in) for this part but no shear LOAD anywhere on the page.
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: null
|
||
source: 'ALP Catalog 2024 p18, "Capacity in Concrete, 4:1 SWL" --
|
||
the table heading. No shear factor is published for this part;
|
||
see shear_unknown_because.'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP Catalog 2024 p18 footnote, "Minimum anchor spacing is
|
||
2x the published edge distance"'
|
||
source: 'ALP Catalog 2024 p16-17 (pdf p17-18, "ALP Lifting Pin
|
||
Anchors" -- dimensions, ultimate mechanical tension, weight;
|
||
Revised 04/30/25), p18 (pdf p18, "ALP Lifting Pin Anchors capacity
|
||
in concrete" -- SWL by concrete strength, edge distances; Revised
|
||
03/28/2024). Read 2026-09-07, PDF text layer. This is the
|
||
LPA4T512G row only -- the same two pages publish the full LPA
|
||
family (1T through 20T, 30 rows); only the one row this job
|
||
actually models is landed.'
|
||
|
||
# sources: p35; 2026-09-01
|
||
# -> rationale.md § catalogue.inserts.QL589SPG
|
||
QL589SPG:
|
||
working_load_lb: 16000
|
||
shear_load_lb: 4010
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
clutch: QL003 (8T-12T)
|
||
# p35 publishes a 'Min. Corner Distance', which is NOT an edge
|
||
# distance -- a corner is two free edges at once and the two numbers
|
||
# are not interchangeable. It is recorded under its own name; this
|
||
# entry still has no published edge distance, and
|
||
# `lifter_spacing_minimum` is right to say it has nothing to double.
|
||
min_corner_distance_in: 18
|
||
requires_tension_bar_for_rating: true
|
||
tension_without_tension_bar_lb: 7690 # the 8 in row, for contrast
|
||
source: 'ALP Catalog 2024 p35, QuikLift Tech Erection Anchor capacity
|
||
table -- "Capacity in Concrete", columns "4:1 SWL Tension w/o Tension
|
||
Bar" and "4:1 SWL Tension w/ Tension Bar". Table basis 3,500 psi and
|
||
145 PCF. Read 2026-09-01; which column applies is chosen by the
|
||
plant layer, not here'
|
||
# A list of records, not a mapping keyed by thickness -- 2026-09-01, a
|
||
# bare float key here (`7.5:`) broke `json.dumps(..., sort_keys=True)`
|
||
# on the whole document with `TypeError: '<' not supported between
|
||
# instances of 'float' and 'str'` the moment any other section had a
|
||
# string key, and a float is a poor key for a reader doing a lookup
|
||
# with measured-thickness noise anyway (a string key sidesteps the
|
||
# TypeError but is still matched against float noise by whoever reads
|
||
# it). Six rows, each thickness explicit as its own field.
|
||
by_panel_thickness_in:
|
||
- {thickness_in: 7.5, shear_266_lb: 6032, shear_41_lb: 4010, tension_no_bar_lb: 7220, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 8.0, shear_266_lb: 6032, shear_41_lb: 4010, tension_no_bar_lb: 7690, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 9.0, shear_266_lb: 6195, shear_41_lb: 4120, tension_no_bar_lb: 8640, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 10.0, shear_266_lb: 6436, shear_41_lb: 4280, tension_no_bar_lb: 9580, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 11.0, shear_266_lb: 6647, shear_41_lb: 4420, tension_no_bar_lb: 10610, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 12.0, shear_266_lb: 6842, shear_41_lb: 4550, tension_no_bar_lb: 11680, tension_with_bar_lb: 16000}
|
||
note: >-
|
||
used on edge at the top of a wall panel to stand it up, so shear is
|
||
the rating that governs while the piece is tilting and tension is the
|
||
one that governs once it hangs plumb. The 2.66:1 shear column is
|
||
available "at the discretion of the engineer for one-time lifts"
|
||
(p35 footnote) and is deliberately NOT the one carried as
|
||
shear_load_lb -- a one-time-lift allowance is the engineer's call,
|
||
not the checker's
|
||
|
||
# sources: p35; 2026-09-07
|
||
# -> rationale.md § catalogue.inserts.QL589G
|
||
QL589G:
|
||
# THE BASE ANCHOR -- no shear plate, no SPW/SPL/SPT dimensions,
|
||
# lighter and packed 250/crate against QL589SPG's 200/crate. Same
|
||
# ring clutch (QL003, 8T-12T), same page family (QL527G / QL548G /
|
||
# QL589G), a DIFFERENT physical part from QL589SPG above -- see the
|
||
# rationale note for why the two must not be read as one product.
|
||
working_load_lb: 16000
|
||
shear_load_lb: 4010
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
clutch: QL003 (8T-12T)
|
||
dimensions_in: {W: 3.75, L: 13.5, T: 0.75, HD: 1, A: 1, B: 3.625, N: 3.125}
|
||
ultimate_mechanical_tension_lb: 64000
|
||
weight_lb: 8.44
|
||
qty_per_crate: 250
|
||
min_corner_distance_in: 18
|
||
requires_tension_bar_for_rating: true
|
||
tension_without_tension_bar_lb: 7690 # the 8 in row, for contrast
|
||
source: 'ALP Catalog 2024 p35 (pdf p35, "QuikLift Tech Erection
|
||
Anchor" -- QL527G / QL548G / QL589G table, footer "34 QUIKLIFT
|
||
SYSTEM 02/2024"). Read 2026-09-07 off the PDF text layer,
|
||
cross-checked at 8x zoom against the rendered page image.'
|
||
by_panel_thickness_in:
|
||
- {thickness_in: 7.5, shear_266_lb: 6032, shear_41_lb: 4010, tension_no_bar_lb: 7220, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 8.0, shear_266_lb: 6032, shear_41_lb: 4010, tension_no_bar_lb: 7690, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 9.0, shear_266_lb: 6195, shear_41_lb: 4120, tension_no_bar_lb: 8640, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 10.0, shear_266_lb: 6436, shear_41_lb: 4280, tension_no_bar_lb: 9580, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 11.0, shear_266_lb: 6647, shear_41_lb: 4420, tension_no_bar_lb: 10610, tension_with_bar_lb: 16000}
|
||
- {thickness_in: 12.0, shear_266_lb: 6842, shear_41_lb: 4550, tension_no_bar_lb: 11680, tension_with_bar_lb: 16000}
|
||
note: >-
|
||
used on edge at the top of a wall panel to stand it up, so shear is
|
||
the rating that governs while the piece is tilting and tension is the
|
||
one that governs once it hangs plumb. The 2.66:1 shear column is
|
||
available "at the discretion of the engineer for one-time lifts"
|
||
(p35 footnote) and is deliberately NOT the one carried as
|
||
shear_load_lb -- a one-time-lift allowance is the engineer's call,
|
||
not the checker's
|
||
|
||
# sources: p48 p49; 2026-09-01
|
||
# -> rationale.md § catalogue.inserts.QL184G
|
||
QL184G:
|
||
manufacturer: ALP
|
||
ton: 8T
|
||
clutch: QL003 (8T-12T)
|
||
dimensions_in:
|
||
W: 6
|
||
L: 4.75
|
||
T: 0.75
|
||
A: 3.5
|
||
B: 4.375
|
||
# Ultimate, not SWL -- see the capacity matrix below for the SWL
|
||
# values this anchor is actually rigged to. Provenance for the
|
||
# `reinforced_tension_4_1_lb` identity check on the shaded rows, not
|
||
# an input to a working-load check by itself.
|
||
ultimate_mechanical_tension_lb: 64000
|
||
weight_lb: 5.62
|
||
qty_per_crate: 350
|
||
# SOURCE: ALP Catalog 2024 p.48-49 (pdf p49-50), judge-verified 2026-09-01
|
||
|
||
QL184SPG:
|
||
manufacturer: ALP
|
||
ton: 8T
|
||
clutch: QL003 (8T-12T)
|
||
dimensions_in:
|
||
W: 6
|
||
L: 4.75
|
||
T: 0.75
|
||
A: 3.5
|
||
B: 4.375
|
||
SPW: 3.5
|
||
SPL: 3
|
||
SPT: 0.375
|
||
ultimate_mechanical_tension_lb: 64000
|
||
weight_lb: 6.84
|
||
qty_per_crate: 350
|
||
# SOURCE: ALP Catalog 2024 p.48-49 (pdf p49-50), judge-verified 2026-09-01
|
||
|
||
# ---- QuikLift Plate Anchors -- ALP Catalog 2024 p52 (pdf p53), footer
|
||
# "52 QUIKLIFT SYSTEM 02/2025". Back-stripping anchors, a plate
|
||
# welded to the foot rather than the LPA/QuikLift ring-clutch
|
||
# shapes above. sources: p52; 2026-09-07
|
||
# -> rationale.md § catalogue.inserts.QL846G
|
||
|
||
QL846G:
|
||
manufacturer: ALP
|
||
ton: 4T
|
||
clutch: QL002 (4T-6T)
|
||
dimensions_in: {W: 1.5, H: 3, T: 0.625, FL: 3}
|
||
ultimate_mechanical_tension_lb: 32000
|
||
weight_lb: 1.23
|
||
qty_per_crate: 2000
|
||
working_load_lb: 3570
|
||
shear_load_lb: 3570
|
||
min_edge_distance_in: 6
|
||
# Published edge distance is TENSION only. The page's own footnote:
|
||
# "Shear edge distances should be based on ACI calculations or
|
||
# testing in plain concrete" -- do not read min_edge_distance_in as
|
||
# a shear edge distance too.
|
||
shear_edge_distance_published: false
|
||
note: >-
|
||
rebar should not be placed between the recess member and the base
|
||
plate; this may reduce the capacity of the system (page dagger
|
||
note, marked on this part)
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP Catalog 2024 p52, "Capacity in Concrete 4:1 SWL" --
|
||
the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP Catalog 2024 p52 footnote, "Minimum anchor spacing is
|
||
2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
source: 'ALP Catalog 2024 p52 (pdf p53, "QuikLift Plate Anchors" --
|
||
dimensions and "Capacity in Concrete 4:1 SWL" tables). Read
|
||
2026-09-07 off the PDF text layer, cross-checked at 8x zoom
|
||
against the rendered page image.'
|
||
|
||
QL847G:
|
||
manufacturer: ALP
|
||
ton: 4T
|
||
clutch: QL002 (4T-6T)
|
||
dimensions_in: {W: 1.5, H: 3.5, T: 0.625, FL: 3}
|
||
ultimate_mechanical_tension_lb: 32000
|
||
weight_lb: 1.42
|
||
qty_per_crate: 1700
|
||
working_load_lb: 4700
|
||
shear_load_lb: 4700
|
||
min_edge_distance_in: 7
|
||
shear_edge_distance_published: false
|
||
note: >-
|
||
rebar should not be placed between the recess member and the base
|
||
plate; this may reduce the capacity of the system (page dagger
|
||
note, marked on this part)
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP Catalog 2024 p52, "Capacity in Concrete 4:1 SWL" --
|
||
the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP Catalog 2024 p52 footnote, "Minimum anchor spacing is
|
||
2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
source: 'ALP Catalog 2024 p52 (pdf p53, "QuikLift Plate Anchors" --
|
||
dimensions and "Capacity in Concrete 4:1 SWL" tables). Read
|
||
2026-09-07 off the PDF text layer, cross-checked at 8x zoom
|
||
against the rendered page image.'
|
||
|
||
QL044G:
|
||
manufacturer: ALP
|
||
ton: 4T
|
||
clutch: QL002 (4T-6T)
|
||
dimensions_in: {W: 1.5, H: 4.375, T: 0.625, FL: 3.875}
|
||
ultimate_mechanical_tension_lb: 32000
|
||
weight_lb: 1.81
|
||
qty_per_crate: 1000
|
||
working_load_lb: 4730
|
||
shear_load_lb: 4730
|
||
min_edge_distance_in: 9
|
||
shear_edge_distance_published: false
|
||
# No dagger note on this row -- the rebar-placement caution above is
|
||
# marked on QL846G / QL847G (and QL128G) only, not on this part.
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP Catalog 2024 p52, "Capacity in Concrete 4:1 SWL" --
|
||
the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP Catalog 2024 p52 footnote, "Minimum anchor spacing is
|
||
2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
source: 'ALP Catalog 2024 p52 (pdf p53, "QuikLift Plate Anchors" --
|
||
dimensions and "Capacity in Concrete 4:1 SWL" tables). Read
|
||
2026-09-07 off the PDF text layer, cross-checked at 8x zoom
|
||
against the rendered page image.'
|
||
|
||
QL054G:
|
||
manufacturer: ALP
|
||
ton: 8T
|
||
clutch: QL003 (8T-12T)
|
||
dimensions_in: {W: 2.5, H: 6.25, T: 0.75, FL: 5}
|
||
ultimate_mechanical_tension_lb: 64000
|
||
weight_lb: 5.43
|
||
qty_per_crate: 400
|
||
working_load_lb: 6350
|
||
shear_load_lb: 6350
|
||
min_edge_distance_in: 12
|
||
shear_edge_distance_published: false
|
||
# No dagger note on this row -- see QL044G's comment above.
|
||
safety_factors:
|
||
tension_fos: 4.0
|
||
shear_fos: 4.0
|
||
source: 'ALP Catalog 2024 p52, "Capacity in Concrete 4:1 SWL" --
|
||
the table heading, spanning both load columns'
|
||
min_spacing_rule:
|
||
multiple_of_edge_distance: 2.0
|
||
published_in: null
|
||
source: 'ALP Catalog 2024 p52 footnote, "Minimum anchor spacing is
|
||
2x the published edge distance"'
|
||
basis_fc_psi: 3500
|
||
basis_pcf: 145
|
||
source: 'ALP Catalog 2024 p52 (pdf p53, "QuikLift Plate Anchors" --
|
||
dimensions and "Capacity in Concrete 4:1 SWL" tables). Read
|
||
2026-09-07 off the PDF text layer, cross-checked at 8x zoom
|
||
against the rendered page image.'
|
||
|
||
# sources: p48 p49 p50 p35; 2026-09-01
|
||
# -> rationale.md § catalogue.insulated_panel_anchor_capacities
|
||
|
||
insulated_panel_anchor_capacities:
|
||
_source: 'ALP Catalog 2024 p.48-49 (pdf p49-50), judge-verified 2026-09-01'
|
||
_basis_fc_psi: 4500
|
||
_rebar_grade: 60
|
||
|
||
panel_group_triple_semantics_uncertain: true
|
||
panel_group_triple_semantics_unknown_because: >-
|
||
The panel_group caption's three numbers (e.g. `(2" x 2" x 4")`) are
|
||
never defined on the page -- the catalogue does not say which
|
||
position is the exterior wythe, the insulation, or the interior
|
||
wythe, and does not say the order is even consistent between groups.
|
||
The left-side thumbnail sketches make this worse rather than better:
|
||
the "(2\" x 2\" x 4\")" group's thumbnail dimensions read 4/2/2
|
||
top-to-bottom, and the "(4\" x 2\" x 2\")" group's thumbnail reads
|
||
2/2/4 -- the two thumbnails do not even agree with each other on an
|
||
order, let alone with the caption string. Landed as the verbatim
|
||
caption string only. The order's meaning is an open question for
|
||
Will or ALP, never a parsed value.
|
||
|
||
rows:
|
||
- panel_group: 8" insulated panel (2" x 2" x 4")
|
||
part_number: QL184SPG
|
||
ton: 8T
|
||
shear_2_66_1_lb: 6900
|
||
shear_4_1_lb: 4600
|
||
shear_perpendicular_4_1_lb: 9870
|
||
reinforced_tension_4_1_lb: 16000
|
||
reinforced_tension_mechanically_limited: true
|
||
rebar_size: '#5'
|
||
bottom_bend_tl_in: 49
|
||
bottom_bend_detail: B
|
||
top_bend_tl_in: 39
|
||
top_bend_detail: A
|
||
|
||
- panel_group: 8" insulated panel (3" x 2" x 3")
|
||
part_number: QL184G
|
||
ton: 8T
|
||
shear_2_66_1_lb: 5775
|
||
shear_4_1_lb: 3850
|
||
shear_perpendicular_4_1_lb: 9900
|
||
reinforced_tension_4_1_lb: 16000
|
||
reinforced_tension_mechanically_limited: true
|
||
rebar_size: '#5'
|
||
bottom_bend_tl_in: 39
|
||
bottom_bend_detail: A
|
||
top_bend_tl_in: 39
|
||
top_bend_detail: A
|
||
|
||
- panel_group: 8" insulated panel (3" x 2" x 3")
|
||
part_number: QL184SPG
|
||
ton: 8T
|
||
shear_2_66_1_lb: 6600
|
||
shear_4_1_lb: 4400
|
||
shear_perpendicular_4_1_lb: 8800
|
||
reinforced_tension_4_1_lb: 16000
|
||
reinforced_tension_mechanically_limited: true
|
||
rebar_size: '#5'
|
||
bottom_bend_tl_in: 39
|
||
bottom_bend_detail: A
|
||
top_bend_tl_in: 39
|
||
top_bend_detail: A
|
||
|
||
- panel_group: 8" insulated panel (4" x 2" x 2")
|
||
part_number: QL184G
|
||
ton: 8T
|
||
shear_2_66_1_lb: 5175
|
||
shear_4_1_lb: 3450
|
||
shear_perpendicular_4_1_lb: 10500
|
||
reinforced_tension_4_1_lb: 16000
|
||
reinforced_tension_mechanically_limited: true
|
||
rebar_size: '#5'
|
||
bottom_bend_tl_in: 39
|
||
bottom_bend_detail: A
|
||
top_bend_tl_in: 49
|
||
top_bend_detail: B
|
||
|
||
# sources: 2026-08-30
|
||
# -> rationale.md § catalogue.rebar
|
||
rebar:
|
||
stock_length_ft: 40.0
|
||
|
||
# -> rationale.md § catalogue.rebar.astm_grades
|
||
astm_grades:
|
||
|
||
# Low-alloy, the weldable spec. Grade 60 only for most of its life, and
|
||
# the current A706/A706M also defines Grade 80 -- so 60 is a sound
|
||
# DEFAULT and not an identity. The default is Will's ruling,
|
||
# 2026-08-30, asked as a question ("A706 不就是 60ksi?") and recorded
|
||
# as the answer to one.
|
||
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.
|
||
|
||
# Carbon steel. The current standard covers Grades 60, 80 and 100, and
|
||
# historically 40 and 75 as well. NO DEFAULT IS DEFENSIBLE: a bar
|
||
# listed only as A615 could be any of them, and a check that assumed 60
|
||
# would be confidently wrong on a job that uses 80.
|
||
A615:
|
||
grades_ksi: [60, 80, 100]
|
||
default_fy_ksi: null
|
||
note: the designation alone does not give a grade -- ask, do not assume.
|
||
|
||
# Welded wire reinforcement (WWF / mesh): the DESIGNATION GRAMMAR, which
|
||
# is public (ASTM A1064/A1064M, size-number definition; also the trade
|
||
# explainers, e.g. mcswusa.com "how to read welded wire mesh sizes"),
|
||
# landed 2026-09-07 for issue #23 item 9g. Which STYLES a plant stocks is
|
||
# plant knowledge and lives in each plant layer (`mesh:`), never here.
|
||
#
|
||
# "6x6-W2.9xW2.9" -> longitudinal spacing 6 in, transverse spacing 6 in,
|
||
# longitudinal wire W2.9, transverse wire W2.9
|
||
# W = plain (smooth) wire, D = deformed wire; the number after the letter
|
||
# is the wire's nominal cross-sectional area in HUNDREDTHS of a square
|
||
# inch (W2.9 = 0.029 in2, D3 = 0.03 in2, D16 = 0.16 in2).
|
||
# area per foot of width, one layer = (100 / spacing_in) ... i.e.
|
||
# area_in2_per_ft = wire_area_in2 * 12 / spacing_in
|
||
# (6x6-W2.9xW2.9 -> 0.029 * 12 / 6 = 0.058 in2/ft each way).
|
||
# Older "gauge" designations (e.g. 6x6-10/10) are a different system and
|
||
# are NOT converted here; a gauge string is reported unparsed, never
|
||
# guessed into an area.
|
||
wwf:
|
||
designation_pattern: '<long_spacing>x<trans_spacing>-<long_wire>x<trans_wire>'
|
||
wire_letter_meaning: {W: plain, D: deformed}
|
||
wire_number_unit: hundredths of a square inch of nominal wire area
|
||
area_per_ft_formula: wire_area_in2 * 12 / spacing_in
|
||
gauge_designations_convertible: false
|
||
# SOURCE: ASTM A1064/A1064M size-number footnote ("the number of one
|
||
# hundredth of a square inch in the nominal area of the wire cross
|
||
# section"), read 2026-09-07 via the ASTM store abstract; the
|
||
# designation layout per Mid Continent Steel & Wire's reading guide.
|
||
|
||
# sources: 2026-08-31
|
||
# -> rationale.md § catalogue.slotted_inserts
|
||
slotted_inserts:
|
||
|
||
_source: 'JVI PSA catalogue 2016-5, p.3 (capacities), p.6 (dimensions), p.7 (edge distance, weights), p.5 (strap anchors, materials, finishes)'
|
||
_read_on: '2026-08-31'
|
||
|
||
# THE FACTOR THAT IS NOT HERE, said once for the whole block.
|
||
safety_factors:
|
||
tension_fos: null
|
||
shear_fos: null
|
||
unknown_because: >-
|
||
The catalogue publishes ULTIMATE pull-out and shear and states no
|
||
safety factor anywhere -- no heading, no footnote, no test-report
|
||
note. A working load cannot be derived from these without one, and
|
||
the 4:1 the disk anchors above publish belongs to a different
|
||
manufacturer's parts and may not be borrowed. A check that needs a
|
||
working load stands down naming this key.
|
||
capacity_is_ultimate: true
|
||
|
||
# The concrete these were tested in is not stated either, so there is no
|
||
# `basis_fc_psi` to scale from. Absent, not assumed.
|
||
basis_fc_psi: null
|
||
basis_fc_unknown_because: >-
|
||
The catalogue states no concrete strength for the published
|
||
capacities. Nothing here scales with sqrt(f'c) because there is no
|
||
basis to scale from.
|
||
|
||
# -> rationale.md § catalogue.slotted_inserts.edge_distance
|
||
edge_distance:
|
||
along_slot_axis_in: 6
|
||
across_slot_axis_in: 10
|
||
basis: without additional reinforcing steel
|
||
reducible_with_extra_reinforcement: true
|
||
reduction_source: 'PSA Test Report #2'
|
||
reduced_value_in: null
|
||
reduced_value_unknown_because: >-
|
||
The page says the edge distance CAN be reduced with extra
|
||
reinforcement and cites Test Report #2 for how far. The report is
|
||
not in hand, so there is no reduced number -- only the fact that a
|
||
reduction exists and where it is published.
|
||
note: >-
|
||
6 in. is measured along the slot's long axis and 10 in.
|
||
perpendicular to it. Both figures on the page show the same
|
||
invariant with the insert turned 90 degrees. NOT a standard/
|
||
reinforced pair -- both are the unreinforced minimum.
|
||
|
||
# -> rationale.md § catalogue.slotted_inserts.unreinforced_top_edge_reduction
|
||
unreinforced_top_edge_reduction:
|
||
fraction: 0.25
|
||
applies_to: ultimate_load
|
||
condition: unreinforced insert placed at the top edge of the panel
|
||
removed_by: added reinforcement -- restores full pull-out capacity
|
||
source: 'PSA Test Report #2'
|
||
not_a_general_unreinforced_penalty: true
|
||
|
||
# ---- the recommended edge reinforcement, as prose ----------------
|
||
#
|
||
# The page draws it rather than tabulating it: stepped hairpins near the
|
||
# edge, 3 1/2" from the edge, 3/4" minimum cover all round, 2 - #3
|
||
# stepped hairpins in the suggested corner detail, described as being IN
|
||
# ADDITION TO the panel's own reinforcement. Carried as text because it
|
||
# is a detail, not a rating.
|
||
edge_reinforcement: >-
|
||
Stepped hairpins near the edge -- the suggested corner detail draws
|
||
2 - #3 stepped hairpins at 3 1/2 in. from the edge with 3/4 in.
|
||
minimum cover, explicitly in addition to the panel's own
|
||
reinforcement. Drawn, not tabulated; no capacity is attached to it.
|
||
|
||
# ---- finishes ----------------------------------------------------
|
||
#
|
||
# Three, and they are three different material specifications rather
|
||
# than three coatings on one body -- a stainless insert has a stainless
|
||
# body and stainless nuts, not a coated carbon body. Material specs are
|
||
# carried per finish for that reason.
|
||
finishes:
|
||
j_finish:
|
||
what_it_is: >-
|
||
A patented three-step coating -- zinc plate to ASTM B633 Type II
|
||
at 0.0005 in. thickness, trivalent clear chromate (RoHS and ELV
|
||
compliant), then a seal coat. It reaches the threads of a strap
|
||
anchor, which is the area a dipped coating leaves most exposed.
|
||
plating_spec: 'ASTM B633, Type II'
|
||
plating_thickness_in: 0.0005
|
||
corrosion_test: 'ASTM B 117'
|
||
hours_to_red_rust: 500
|
||
hours_to_white_rust: 96
|
||
insert_body: 'Hot Rolled, P & O, HSLA SAE J2340 490XLF'
|
||
insert_square_nuts: '3/4 in. dia. NC thread, SAE J995 GR-5'
|
||
insert_studs: 'AISI 1016 or 1018 (round head)'
|
||
strap_body: 'ASTM A36/A529 GR 50, CSA G40.21 44W'
|
||
strap_jam_nuts: '3/4 in. dia. 10 UNC-2, SAE GR 5 hex, SAE J995'
|
||
strap_thread_stud: '3/4 in. dia. 10 UNC-2, AISI 1038 CRS'
|
||
hot_dipped_galvanized:
|
||
note: >-
|
||
Shares the J-finish material specification block on the page --
|
||
the same heading covers "J Finish & Hot Dipped Galvanized" for
|
||
both inserts and threaded strap anchors. No separate corrosion
|
||
figures are published for it.
|
||
corrosion_hours: null
|
||
corrosion_hours_unknown_because: >-
|
||
The 500 h / 96 h ASTM B 117 figures are printed under the J-finish
|
||
heading only. Nothing publishes an equivalent for the galvanized
|
||
option and it is not inherited.
|
||
stainless_steel:
|
||
insert_body: 'AISI 304 stainless steel'
|
||
insert_square_nuts: '3/4 in. dia. NC thread, AISI 304, ASTM A194 GR 8'
|
||
insert_studs: 'AISI 430 stainless steel'
|
||
strap_body: 'AISI 304 stainless steel'
|
||
strap_jam_nuts: 'AISI 304 stainless steel, ASTM A194 GR 8'
|
||
strap_thread_stud: '3/4 in. dia. 10 UNC-2, AISI 304 rolled formed'
|
||
plastic_closers: non-structural plastic, all finishes
|
||
welding: 'robot welding with minimum penetration of 0.8 mm (threaded strap anchors)'
|
||
|
||
# -> rationale.md § catalogue.slotted_inserts.models
|
||
models:
|
||
|
||
'4525':
|
||
series: '4500'
|
||
ultimate_pull_out_lb: 13400
|
||
ultimate_shear_lb: 20000
|
||
_stated_as: {pull_out: '>13,400 lbs.', shear: '>20,000 lbs.'}
|
||
available_adjustment_in: 2.875
|
||
depth_no_stud_in: 2.5
|
||
stud_length_in: null
|
||
stud_length_note: the shallowest model has no stud; the M dimension is blank on the page
|
||
weight_lb: 1.5
|
||
weight_kgf: 0.680
|
||
|
||
'4535':
|
||
series: '4500'
|
||
ultimate_pull_out_lb: 18800
|
||
ultimate_shear_lb: 20000
|
||
_stated_as: {pull_out: '>18,800 lbs.', shear: '>20,000 lbs.'}
|
||
available_adjustment_in: 2.875
|
||
depth_no_stud_in: 3.5
|
||
stud_length_in: 2.25
|
||
weight_lb: 1.9
|
||
weight_kgf: 0.862
|
||
|
||
'4545':
|
||
series: '4500'
|
||
ultimate_pull_out_lb: 21500
|
||
ultimate_shear_lb: 20000
|
||
_stated_as: {pull_out: '>21,500 lbs.', shear: '>20,000 lbs.'}
|
||
available_adjustment_in: 2.125
|
||
depth_no_stud_in: 4.5
|
||
stud_length_in: 3.25
|
||
weight_lb: 2.3
|
||
weight_kgf: 1.043
|
||
|
||
'6025':
|
||
series: '6000'
|
||
ultimate_pull_out_lb: 13400
|
||
ultimate_shear_lb: 20000
|
||
_stated_as: {pull_out: '>13,400 lbs.', shear: '>20,000 lbs.'}
|
||
available_adjustment_in: 4.375
|
||
depth_no_stud_in: 2.5
|
||
stud_length_in: null
|
||
stud_length_note: as 4525 -- no stud, M dimension blank
|
||
weight_lb: 2.0
|
||
weight_kgf: 0.907
|
||
|
||
'6035':
|
||
series: '6000'
|
||
ultimate_pull_out_lb: 18800
|
||
ultimate_shear_lb: 20000
|
||
_stated_as: {pull_out: '>18,800 lbs.', shear: '>20,000 lbs.'}
|
||
available_adjustment_in: 4.375
|
||
depth_no_stud_in: 3.5
|
||
stud_length_in: 2.25
|
||
weight_lb: 2.3
|
||
weight_kgf: 1.043
|
||
|
||
'6045':
|
||
series: '6000'
|
||
ultimate_pull_out_lb: 21500
|
||
ultimate_shear_lb: 20000
|
||
_stated_as: {pull_out: '>21,500 lbs.', shear: '>20,000 lbs.'}
|
||
available_adjustment_in: 3.625
|
||
depth_no_stud_in: 4.5
|
||
stud_length_in: 3.25
|
||
weight_lb: 2.5
|
||
weight_kgf: 1.134
|
||
|
||
# ---- the dimensions the two series share ------------------------
|
||
#
|
||
# Everything on the dimensional sketch that is NOT per model. Split out
|
||
# rather than repeated on six entries, because a value repeated six
|
||
# times is a value that goes out of step five times.
|
||
series_dimensions:
|
||
'4500':
|
||
length_overall_in: 5.75
|
||
length_excluding_plastic_tab_in: 4.5
|
||
width_overall_in: 4.125
|
||
width_at_base_in: 2.0
|
||
centre_to_centre_same_side_in: 1.5
|
||
centre_to_centre_across_insert_in: 2.75
|
||
top_of_insert_to_wing_in: 1.25
|
||
hole_diameter_in: 0.5625
|
||
stud_head_diameter_in: 0.875
|
||
'6000':
|
||
length_overall_in: 7.25
|
||
length_excluding_plastic_tab_in: 6.0
|
||
width_overall_in: 4.125
|
||
width_at_base_in: 2.0
|
||
centre_to_centre_same_side_in: 2.5
|
||
centre_to_centre_across_insert_in: 2.75
|
||
top_of_insert_to_wing_in: 1.25
|
||
hole_diameter_in: 0.5625
|
||
stud_head_diameter_in: 0.875
|
||
|
||
# -> rationale.md § catalogue.slotted_inserts.strap_anchors
|
||
strap_anchors:
|
||
tension_capacity_lb: 30000
|
||
tension_stated_as: 'Tension capacity exceeds 30 KIPS'
|
||
widths_in: [2]
|
||
widths_note: >-
|
||
The published shear table is for the 2 in. width, which the page
|
||
calls the highest-shear option ("Our standard 2" wide welded strap
|
||
anchor provides the Highest shear capacity"). Other widths exist --
|
||
the page says a range of strap anchors gives a range of shear
|
||
capacities -- and none of them is published here.
|
||
thickness_in: 0.375
|
||
lengths_in: [6, 8, 10, 12]
|
||
# The four catalogue numbers, and they read as the length: 675 is the
|
||
# 6 in. strap, 875 the 8 in., and so on. The 75 is the 3/4 in. thread.
|
||
models:
|
||
'675': {length_in: 6, weight_lb: 1.2, weight_kgf: 0.544}
|
||
'875': {length_in: 8, weight_lb: 1.6, weight_kgf: 0.726}
|
||
'1075': {length_in: 10, weight_lb: 2.0, weight_kgf: 0.907}
|
||
'1275': {length_in: 12, weight_lb: 2.4, weight_kgf: 1.089}
|
||
# Average tested shear against eccentricity, 2 in. width. The page
|
||
# heads the column "KIPS - Avg", so these are means and not the
|
||
# guaranteed minimums the insert capacities are.
|
||
# Keys are STRINGS ('1.0', not 1.0) for the same reason as
|
||
# catalogue.inserts.QL589SPG.by_panel_thickness_in -- a bare float key
|
||
# here mixes with the string keys `_units` / `_basis` in the same
|
||
# mapping and breaks `json.dumps(..., sort_keys=True)` on the whole
|
||
# document with `TypeError: '<' not supported between instances of
|
||
# 'float' and 'str'`. Found and fixed 2026-09-01 alongside that table.
|
||
shear_by_eccentricity_2in_width:
|
||
_units: kips
|
||
_basis: average
|
||
'1.0': 20.2
|
||
'1.5': 17.9
|
||
'2.0': 14.2
|
||
'2.5': 13.2
|
||
'3.0': 11.3
|
||
# Two erection facts with no numeric home except one clearance.
|
||
threaded_vs_notched: >-
|
||
A threaded strap rotates to any angle to take out tolerance without
|
||
losing pull-out capacity; a notched strap installs at 90 degrees to
|
||
the insert and concentrates the shear over its 3/8 in. notch width,
|
||
where the threaded strap spreads it across the insert lips.
|
||
notched_strap_rotation_clearance_in: 2
|
||
notched_strap_erection_caution: >-
|
||
A notched strap anchor must be placed after the panel is set and
|
||
needs at least 2 in. of clearance to rotate to 90 degrees. If the
|
||
insert sits too low, tipping the panel away from the frame to clear
|
||
the insert opening puts the installer's hands in the gap.
|
||
|
||
# ---- where the numbers come from, and what is not published -----
|
||
test_reports:
|
||
published_by: 'JVI (www.jvi-inc.com)'
|
||
list:
|
||
'1': pull-out capacity
|
||
'2': pull-out capacity near edge
|
||
'3': shear capacity
|
||
'4': pull-out capacity, sandwich panels
|
||
'5': pull-out capacity, end of insert
|
||
'6': corrosion resistance
|
||
'7': 30 KIP load capacity
|
||
note: >-
|
||
The catalogue cites these seven for its capacities and its edge
|
||
rules but reproduces none of them. Report #2 is the one this file
|
||
needs and does not have -- it is what would give a reduced edge
|
||
distance a number.
|
||
|
||
# -> rationale.md § catalogue.shear_grid
|
||
shear_grid:
|
||
|
||
c_grid:
|
||
manufacturer: Altus
|
||
product: C-GRID
|
||
what_it_is: >-
|
||
A carbon-fibre grid cast across the insulation of a sandwich wall
|
||
panel to transfer horizontal shear between the wythes. Capacity is
|
||
a shear flow -- pounds per inch of grid -- because the grid is
|
||
continuous, not a discrete part.
|
||
source: >-
|
||
Altus C-GRID Table 4.1, "Test Data and Nominal Strength Values",
|
||
reproduced in a 2022 C-GRID insulated-wall-panel design deck. Basis
|
||
stated on the same page: "To date Altus has performed over 200
|
||
double shear tests to arrive at values listed below."
|
||
test_basis: over 200 double shear tests
|
||
test_method: double shear on rectangular specimens, VQ/I
|
||
source_year: 2022
|
||
read_on: '2026-08-31'
|
||
|
||
recommended_value_rule: >-
|
||
recommended = average of (average test value) and (maximum minus 3
|
||
standard deviations), rounded half up. Verified to hold on all 37
|
||
published rows -- which is what checks this transcription.
|
||
maximum_rule: >-
|
||
The published maximum is 1.5 times the average, based on VQ/I shear
|
||
on the rectangular test specimens -- it is derived, not a
|
||
largest-observed.
|
||
values_are_nominal: true
|
||
values_are_nominal_note: >-
|
||
Nominal, unfactored. The phi a designer applies depends on the check
|
||
and on the insulation and is design practice, not product data --
|
||
it belongs in a plant layer, never here.
|
||
single_test_per_spacing_types: [POLY ISO]
|
||
single_test_caveat: >-
|
||
The page footnotes POLY ISO with "Single test for each spacing.
|
||
Standard deviation is across tests" -- i.e. that family's spread is
|
||
borrowed across spacings rather than measured within one. Its three
|
||
rows are weaker evidence than the rest of the table and the page
|
||
says so.
|
||
|
||
# A note printed above the table, for a condition the table does not
|
||
# cover: "Design value of C-GRID with debonded insulation is
|
||
# approximately 100 pli."
|
||
debonded_insulation_pli: 100
|
||
debonded_insulation_note: >-
|
||
Stated as "approximately", for debonded insulation, outside the
|
||
keyed table. It is not an entry in it and must not be read as one.
|
||
|
||
# -> rationale.md § catalogue.shear_grid.c_grid.shear_flow
|
||
shear_flow:
|
||
_units: pli
|
||
_columns: [average_test, max_minus_3sd, recommended_nominal]
|
||
|
||
EPS:
|
||
2: {12: [280, 381, 331], 24: [288, 414, 351], 48: [512, 711, 612]}
|
||
4: {12: [163, 223.5, 193], 24: [243, 334.5, 289], 48: [425, 496.5, 461]}
|
||
6: {12: [186, 258, 222], 24: [213, 286.5, 250], 48: [314, 360, 337]}
|
||
|
||
XPS:
|
||
2: {12: [212, 178, 195], 18: [180, 207, 194], 24: [160, 152, 156], 36: [142, 202, 172]}
|
||
4: {12: [176, 221, 199], 18: [198, 203, 201], 24: [161, 128, 145], 36: [163, 155, 159]}
|
||
|
||
XPS_sand_blasted:
|
||
2: {12: [290, 325, 308], 24: [540, 658, 599], 48: [586, 469, 528]}
|
||
4: {12: [314, 462, 388], 24: [444, 607, 526], 48: [593, 712, 653]}
|
||
|
||
XPS_machined:
|
||
3: {12: [243, 247, 245]}
|
||
|
||
POLY_ISO:
|
||
4: {12: [205, 289.5, 247], 24: [224, 276, 250], 48: [102, 105, 104]}
|
||
|
||
Kooltherm:
|
||
2: {12: [222, 234, 228], 24: [211, 277, 244], 48: [269, 144, 207]}
|
||
4: {12: [175, 223.5, 199], 24: [212, 270, 241], 48: [219, 259.5, 239]}
|
||
|
||
NeoPor_low_density:
|
||
2: {24: [438, 513, 476]}
|
||
6: {24: [323, 370.5, 347]}
|
||
|
||
NeoPor_high_density:
|
||
2: {24: [534, 735, 635]}
|
||
4: {24: [533, 750, 642]}
|
||
|
||
# ---- what this table does NOT publish --------------------------
|
||
#
|
||
# STIFFNESS. A partial-composite calculation needs a shear stiffness
|
||
# as well as a strength, and Table 4.1 is strengths only. Nothing on
|
||
# the page carries a k/in. A module that assumes a stiffness because
|
||
# it has a strength is inventing the half that governs deflection.
|
||
stiffness_k_per_in: null
|
||
stiffness_unknown_because: >-
|
||
Table 4.1 publishes shear flow STRENGTH only. No stiffness value
|
||
appears on the page in any form, so a partial-composite calculation
|
||
that needs one has to get it elsewhere and may not derive it from
|
||
these.
|
||
# FAILURE MODE. 200+ tests, and the page classifies none of them.
|
||
failure_modes: null
|
||
failure_modes_unknown_because: >-
|
||
The page states the test count and the derived values and never
|
||
classifies the failures. Whether a row is governed by the grid, the
|
||
bond or the insulation is not published.
|
||
|
||
|
||
# sources: 2026-09-07
|
||
# -> PCI Design Handbook 9th ed. (MNL-120-25), Section 5.8 "Loss of
|
||
# Prestress", pdf viewer p293-296, printed p5-42 to 5-45. Read via the
|
||
# Apryse WebViewer text layer, with Tables 5.8.1/5.8.2 and Eq. 5-105/
|
||
# 5-106 SCREEN-VERIFIED 2026-09-07 at 93% zoom (Eq. 5-105/5-106 also
|
||
# cross-checked numerically against Table 5.8.2 at three points, agree
|
||
# within rounding). Full extraction:
|
||
# knowledge/library/notes/PCI9-5.8-losses.md. Method: ACI-ASCE Committee
|
||
# 423 task group report (Zia et al. 1979), reprinted PCI Design Handbook
|
||
# 9th ed. Section 5.8.3 -- this is what will/REVIT #24 needs: the engine
|
||
# today assumes a lump-sum loss percentage, and the owner ruled "不要
|
||
# assume prestress loss 了,要算的,根据 PCI 算". Applies to pretensioned
|
||
# components; the handbook itself notes more detailed analysis may be
|
||
# warranted for unusual situations.
|
||
# -> rationale.md § catalogue.prestress_losses
|
||
prestress_losses:
|
||
method: 'PCI/Zia 1979 (ACI-ASCE Committee 423 task group report), PCI Design Handbook 9th ed. Section 5.8.3'
|
||
source: 'PCI Design Handbook 9th ed. (MNL-120-25) Section 5.8.3, p294-295 / printed 5-43 to 5-44'
|
||
applicability: pretensioned components
|
||
|
||
total_loss:
|
||
formula: 'TL = ES + CR + SH + RE'
|
||
source: 'Eq. 5-98, p294 / 5-43'
|
||
range_normalweight_psi: {min: 25000, max: 50000}
|
||
range_sand_lightweight_psi: {min: 30000, max: 55000}
|
||
load_table_lower_limit_psi: 30000
|
||
note: >-
|
||
"Total loss of prestress in typical components will range from
|
||
about 25,000 to 50,000 psi for normalweight concrete components,
|
||
and from about 30,000 to 55,000 psi for sand-lightweight
|
||
components... The load tables in Chapter 3 have a lower limit on
|
||
loss of 30,000 psi." Section 5.8.2, p294 / 5-43.
|
||
|
||
elastic_shortening:
|
||
formula: 'ES = Kes * Eps * fcir / Eci'
|
||
kes_pretensioned: 1.0
|
||
eps_psi: 28500000
|
||
eps_note: "about 28.5 x 10^6 psi -- Eps is a stated APPROXIMATION on this page, not itself a strand-specific modulus"
|
||
fcir_formula: 'fcir = Kcir*(Pi/Ag + Pi*e^2/Ig) - Mg*e/Ig'
|
||
kcir_pretensioned: 0.9
|
||
source: 'Eq. 5-99/5-100, p294-295 / 5-43 to 5-44'
|
||
|
||
creep:
|
||
formula: 'CR = Kcr * (Eps/Ec) * (fcir - fcds)'
|
||
kcr_normalweight: 2.0
|
||
kcr_sand_lightweight: 1.6
|
||
fcds_formula: 'fcds = Msd*e/Ig'
|
||
source: 'Eq. 5-101/5-102, p295 / 5-44. SCREEN-VERIFIED 2026-09-07.'
|
||
composite_note: >-
|
||
For composite components, if some dead load is applied to the
|
||
composite section, fcds is calculated in two operations -- one
|
||
for the noncomposite condition, one for the composite condition.
|
||
|
||
shrinkage:
|
||
formula: 'SH = 8.2e-6 * Ksh * Eps * (1 - 0.06*VS) * (100 - RH)'
|
||
ksh_pretensioned: 1.0
|
||
vs_definition: 'volume-to-surface ratio'
|
||
rh_definition: 'average ambient relative humidity, see PCI Design Aid 4-12'
|
||
source: 'Eq. 5-103, p295 / 5-44'
|
||
|
||
relaxation:
|
||
formula: 'RE = (Kre - J*(SH + CR + ES)) * C'
|
||
source: 'Eq. 5-104, p295 / 5-44'
|
||
kre_j_by_steel_type:
|
||
# Table 5.8.1, SCREEN-VERIFIED 2026-09-07 at 93% zoom against
|
||
# p295 / printed 5-44.
|
||
grade_270_low_relaxation_strand: {kre: 5000, j: 0.040}
|
||
grade_250_low_relaxation_wire: {kre: 4630, j: 0.037}
|
||
grade_240_or_235_low_relaxation_wire: {kre: 4400, j: 0.035}
|
||
grade_145_or_160_stress_relieved_bar: {kre: 6000, j: 0.050}
|
||
c_coefficient:
|
||
# Table 5.8.2 and its closed-form Eq. 5-105/5-106, both
|
||
# SCREEN-VERIFIED 2026-09-07 and cross-checked numerically
|
||
# against each other (three spot checks, agree within rounding --
|
||
# see knowledge/library/notes/PCI9-5.8-losses.md).
|
||
# STRING keys -- see catalogue.slotted_inserts.strap_anchors for
|
||
# why a bare float key here would break json.dumps(sort_keys=True).
|
||
table_by_fpi_over_fpu_ge_054:
|
||
# stress-relieved bar or low-relaxation strand/wire
|
||
'0.80': 1.28
|
||
'0.79': 1.22
|
||
'0.78': 1.16
|
||
'0.77': 1.11
|
||
'0.76': 1.05
|
||
'0.75': 1.00
|
||
'0.74': 0.95
|
||
'0.73': 0.90
|
||
'0.72': 0.85
|
||
'0.71': 0.80
|
||
'0.70': 0.75
|
||
'0.69': 0.70
|
||
'0.68': 0.66
|
||
'0.67': 0.61
|
||
'0.66': 0.57
|
||
'0.65': 0.53
|
||
'0.64': 0.49
|
||
'0.63': 0.45
|
||
'0.62': 0.41
|
||
'0.61': 0.37
|
||
'0.60': 0.33
|
||
formula_ge_054: 'C = (fpi_over_fpu / 0.21) * (fpi_over_fpu / 0.9 - 0.55)'
|
||
formula_ge_054_condition: 'low-relaxation strand, fpi/fpu >= 0.54, Eq. 5-105'
|
||
formula_le_054: 'C = fpi_over_fpu / 4.25'
|
||
formula_le_054_condition: 'low-relaxation strand, fpi/fpu <= 0.54, Eq. 5-106'
|
||
fpi_definition: 'fpi = Pi / Aps'
|
||
|
||
elastic_gain:
|
||
formula: 'fEG = (Eps/Ec) * fcgp'
|
||
source: 'Eq. 5-107, p296 / 5-45'
|
||
note: 'decrease in prestress loss from a transient superimposed load; in effect only while the transient load is active'
|
||
|
||
critical_locations:
|
||
note: >-
|
||
ES and CR losses are computed at the point of maximum flexural
|
||
tensile stress -- midspan for straight/parabolic/approximate-
|
||
parabolic strand, near the 0.4l point for strand deflected at
|
||
midspan only. Only the critical-point stresses need be
|
||
considered for bonded strand, unless a critical section falls
|
||
within the development length (Section 5.2.3).
|
||
source: 'Section 5.8.4, p295-296 / 5-44 to 5-45'
|
||
|
||
# sources: 2026-09-07
|
||
# -> PCI Design Handbook 9th ed., Section 15.2 "Material Properties --
|
||
# Prestressing Steel", Design Aids 15-9/15-10/15-11/15-12, pdf viewer
|
||
# p862-863, printed p15-31/15-32. SCREEN-VERIFIED 2026-09-07 at 93%
|
||
# zoom -- full-page render matches the text-layer transcription
|
||
# exactly. Full extraction:
|
||
# knowledge/library/notes/PCI9-ch15-reference.md.
|
||
# -> rationale.md § catalogue.strand
|
||
strand:
|
||
astm_a416_properties:
|
||
source: 'ASTM A416/A416M-18 via PCI Design Handbook 9th ed. Design Aid 15-9, p862 / 15-31'
|
||
grade_270:
|
||
fpu_ksi: 270
|
||
sizes:
|
||
'3/8': {diameter_in: 0.375, area_in2: 0.085, weight_lb_ft: 0.29}
|
||
'7/16': {diameter_in: 0.438, area_in2: 0.115, weight_lb_ft: 0.39}
|
||
'1/2': {diameter_in: 0.500, area_in2: 0.153, weight_lb_ft: 0.52}
|
||
'1/2 special': {diameter_in: 0.520, area_in2: 0.167, weight_lb_ft: 0.57}
|
||
'9/16': {diameter_in: 0.563, area_in2: 0.192, weight_lb_ft: 0.65}
|
||
'0.6': {diameter_in: 0.600, area_in2: 0.217, weight_lb_ft: 0.74}
|
||
'0.62': {diameter_in: 0.620, area_in2: 0.231, weight_lb_ft: 0.78}
|
||
'0.7': {diameter_in: 0.700, area_in2: 0.294, weight_lb_ft: 1.00}
|
||
grade_250:
|
||
fpu_ksi: 250
|
||
sizes:
|
||
'1/4': {diameter_in: 0.250, area_in2: 0.036, weight_lb_ft: 0.12}
|
||
'5/16': {diameter_in: 0.313, area_in2: 0.058, weight_lb_ft: 0.20}
|
||
'3/8': {diameter_in: 0.375, area_in2: 0.080, weight_lb_ft: 0.27}
|
||
'7/16': {diameter_in: 0.438, area_in2: 0.108, weight_lb_ft: 0.37}
|
||
'1/2': {diameter_in: 0.500, area_in2: 0.144, weight_lb_ft: 0.49}
|
||
'0.6': {diameter_in: 0.600, area_in2: 0.216, weight_lb_ft: 0.74}
|
||
|
||
astm_a421_wire_properties:
|
||
source: 'ASTM A421/A421M-21 via PCI Design Handbook 9th ed. Design Aid 15-10, p862 / 15-31'
|
||
entries:
|
||
- {diameter_in: 0.192, area_in2: 0.0289, weight_lb_ft: 0.1, fpu_ksi: 250}
|
||
- {diameter_in: 0.196, area_in2: 0.0302, weight_lb_ft: 0.104, fpu_ksi: 250}
|
||
- {diameter_in: 0.25, area_in2: 0.0491, weight_lb_ft: 0.169, fpu_ksi: 240}
|
||
- {diameter_in: 0.276, area_in2: 0.0598, weight_lb_ft: 0.206, fpu_ksi: 235}
|
||
|
||
astm_a722_bar_properties:
|
||
source: 'ASTM A722/A722M-18 via PCI Design Handbook 9th ed. Design Aid 15-11, p862 / 15-31'
|
||
type_1_plain:
|
||
fpu_ksi: 150
|
||
fpy_fraction_of_fpu: 0.85
|
||
sizes:
|
||
'3/4': {area_in2: 0.44, weight_lb_ft: 1.50}
|
||
'7/8': {area_in2: 0.60, weight_lb_ft: 2.04}
|
||
'1': {area_in2: 0.78, weight_lb_ft: 2.67}
|
||
'1-1/8': {area_in2: 0.99, weight_lb_ft: 3.38}
|
||
'1-1/4': {area_in2: 1.23, weight_lb_ft: 4.17}
|
||
'1-3/8': {area_in2: 1.48, weight_lb_ft: 5.05}
|
||
type_2_deformed:
|
||
fpu_ksi: 150
|
||
fpy_fraction_of_fpu: 0.80
|
||
sizes:
|
||
'5/8': {area_in2: 0.28, weight_lb_ft: 0.98}
|
||
'3/4': {area_in2: 0.42, weight_lb_ft: 1.49}
|
||
'1': {area_in2: 0.85, weight_lb_ft: 3.01}
|
||
'1-1/4': {area_in2: 1.25, weight_lb_ft: 4.39}
|
||
'1-3/8': {area_in2: 1.58, weight_lb_ft: 5.56}
|
||
'1-3/4': {area_in2: 2.58, weight_lb_ft: 9.10}
|
||
'2-1/2': {area_in2: 5.16, weight_lb_ft: 18.20}
|
||
'3': {area_in2: 6.85, weight_lb_ft: 24.09}
|
||
|
||
design_stress_strain:
|
||
source: 'PCI Design Handbook 9th ed. Design Aid 15-12, p863 / 15-32. SCREEN-VERIFIED 2026-09-07.'
|
||
astm_a416_min_yield_at_1pct_elongation_ksi: {grade_270: 243, grade_250: 225}
|
||
approx_strain_at_rupture_in_per_in: {min: 0.05, max: 0.07}
|
||
min_elongation_at_ultimate_pct: 3.5
|
||
formula_250ksi_below_0_0076: 'fps = 28500 * eps'
|
||
formula_250ksi_above_0_0076: 'fps = 250 - 0.04/(eps - 0.0064)'
|
||
formula_270ksi_below_0_0085: 'fps = 28500 * eps'
|
||
formula_270ksi_above_0_0085: 'fps = 270 - 0.04/(eps - 0.007)'
|
||
|
||
# sources: 2026-09-07
|
||
# -> PCI Design Handbook 9th ed., Section 5.9 "Camber and Deflection"
|
||
# and Design Aids 5-1/5-2, pdf viewer p293-300 (Section 5.9) and
|
||
# p448-449 (Design Aids), printed p5-45 to 5-49 and 5-197/5-198.
|
||
# Full extraction: knowledge/library/notes/PCI9-5.8-losses.md (§5.9 is
|
||
# in the same note as §5.8, both pulled from the same page range) and
|
||
# knowledge/library/notes/PCI9-5.17-design-aids.md.
|
||
# -> rationale.md § catalogue.camber_and_bowing
|
||
camber_and_bowing:
|
||
time_dependent_multipliers:
|
||
source: >-
|
||
Table 5.9.2, p297 / 5-46. SCREEN-VERIFIED 2026-09-07. Derivation:
|
||
Martin (1977). "Note that there is no corresponding multiplier
|
||
for prestressed concrete in ACI 318" -- these are PCI-original,
|
||
not an ACI 318 table.
|
||
at_erection:
|
||
deflection_downward_self_weight: {without_topping: 1.85, with_topping: 1.85}
|
||
camber_upward_prestress: {without_topping: 1.80, with_topping: 1.80}
|
||
final:
|
||
deflection_downward_self_weight: {without_topping: 2.70, with_topping: 2.40}
|
||
camber_upward_prestress: {without_topping: 2.45, with_topping: 2.20}
|
||
deflection_downward_superimposed_dead_load: {without_topping: 3.00, with_topping: 3.00}
|
||
deflection_downward_composite_topping: {without_topping: null, with_topping: 2.30}
|
||
nonprestressed_reinforcement_adjustment_formula: null
|
||
nonprestressed_reinforcement_adjustment_unknown_because: >-
|
||
Eq. 5-114 (Shaikh and Branson 1970, Martin 1977, p299 / 5-48) is
|
||
C2 as a function of C1 and Asd/Aps, but the text-layer extraction
|
||
garbled the fraction nesting and it was not screen-verified --
|
||
confidence C, not landed as a formula. Question for the owner /
|
||
next landing pass: re-render p299 and confirm before coding this.
|
||
|
||
camber_equations:
|
||
source: 'Design Aid 5-1, p448 / 5-197. SCREEN-VERIFIED 2026-09-07.'
|
||
straight_strands: 'Delta = Po*e*l^2 / (8*E*I)'
|
||
single_point_depressed: 'Delta = Po*ee*l^2/(8*E*I) + Po*e_end*l^2/(12*E*I)'
|
||
two_point_depressed: 'Delta = Po*ee*l^2/(8*E*I) + (Po*e_end/(E*I)) * (l^2/8 - a^2/6)'
|
||
variables: 'e/ee = strand eccentricity at midspan; e_end = eccentricity change from end to depression point; a = distance from each end to its depression point (two-point case)'
|
||
|
||
bowing:
|
||
formula: 'Delta = alpha * l^2 / (8*h)'
|
||
alpha_formula: 'alpha = C_thermal * (T1 - T2)'
|
||
source: 'Eq. 5-115/5-116, p299 / 5-48'
|
||
seasonal_temp_diff_open_structures_f: {min: 30, max: 40}
|
||
seasonal_note: >-
|
||
Seldom exceeds 30-40 F in open structures such as parking-deck
|
||
roofs; can be higher in an insulated wall panel, tempered by
|
||
concrete thermal lag.
|
||
restraint_forces_and_moments:
|
||
source: 'Design Aid 5-2, p449 / 5-198. SCREEN-VERIFIED 2026-09-07.'
|
||
effective_modulus_et:
|
||
short_term_fraction_of_ec: 0.75
|
||
note: >-
|
||
Consistent with the thermal-displacement reduction for
|
||
equivalent volume change, Section 4.4.3.1. Earlier editions
|
||
of this handbook used 0.5*Ec for long-term seasonal cases --
|
||
the 9th edition gives no current numeric value for that case.
|
||
intermediate_restraint:
|
||
case_1_single_midspan: {formula_p: 'P = 48*Et*I*Delta/l^3', formula_moment: 'M = P*l/4'}
|
||
case_2_two_points: {formula_p: 'P = 24*Et*I*Delta/(3*a*l^2 - 4*a^3)', formula_moment: 'M = P*a'}
|
||
case_3_three_or_more: {formula_sum_p: 'sum(P) = w*l = 77*Et*I*Delta/l^3', formula_moment: 'M = w*l^2/8 = sum(P)*(l/8)'}
|
||
end_restraint:
|
||
case_4_both_ends: {formula_moment: 'M = 8*Et*I*Delta/l^2'}
|
||
case_5_one_end: {formula_moment: 'M = 16*Et*I*Delta/l^2'}
|
||
|
||
# sources: 2026-09-07
|
||
# -> PCI Design Handbook 9th ed., Section 5.12 "Insulated Wall Panels",
|
||
# pdf viewer p304-309, printed p5-53 to 5-58. Full extraction:
|
||
# knowledge/library/notes/PCI9-5.12-insulated.md.
|
||
# -> rationale.md § catalogue.insulated_panel
|
||
insulated_panel:
|
||
insulation_properties:
|
||
source: 'Table 5.12.1, p305 / 5-54. SCREEN-VERIFIED 2026-09-07.'
|
||
note: >-
|
||
Only the maximum-use-temperature and the moisture caution are
|
||
landed here as the numbers a check might reasonably gate on; the
|
||
full per-density property matrix (density, water absorption,
|
||
compressive/tensile/shear/flexural strength, thermal
|
||
conductivity) is in the note file, not landed -- see the debt
|
||
list in the ledger.
|
||
max_use_temperature_f:
|
||
eps: 165
|
||
xps: 165
|
||
polyisocyanurate_unfaced: 250
|
||
polyisocyanurate_faced: 250
|
||
phenolic: 300
|
||
cellular_glass: 900
|
||
unfaced_felt_faced_polyiso_moisture_caution: >-
|
||
"Unfaced and felt-faced polyisocyanurates should not be used in
|
||
insulated wall panels because moisture absorption causes them to
|
||
expand." (footnote a, Table 5.12.1)
|
||
|
||
structural_design_assumptions:
|
||
source: 'Section 5.12.2, p305-306 / 5-54 to 5-55'
|
||
noncomposite: 'wythes act independently for the full life of the panel; flexible wythe connectors offer insignificant shrinkage/temperature restraint'
|
||
composite: 'wythes act as a fully composite unit for the full life; needs shear-resisting connectors, welded-wire trusses, or solid concrete zones -- thermal bowing tends to be GREATER than noncomposite; solid zones significantly compromise thermal efficiency'
|
||
partially_composite: 'between noncomposite and composite; may differ by check (deflection vs cracking vs ultimate strength)'
|
||
semicomposite: 'composite during handling (early insulation bond + flexible connectors), noncomposite in service (bond assumed unreliable long-term); wind loads split by wythe stiffness; slenderness uses the SUM of individual moments of inertia (Example 5-16)'
|
||
|
||
wythe_and_strand_limits:
|
||
source: 'Section 5.12.2 / 5.12.3 / 5.12.4, p306/p308, printed 5-55/5-57'
|
||
min_wythe_thickness_rule: 'no thinner than 3x the maximum aggregate size (some manufacturers use a 2-in. wythe with 3/4-in. aggregate)'
|
||
max_strand_diameter_by_wythe_thickness:
|
||
'3/8_in_ok_wythe_2_in': true
|
||
'1/2_in_needs_wythe_3_in_min': true
|
||
note: 'same underlying rule as catalogue.handling.stripping.max_strand_diameter_by_slab_thickness (Table 8.3.2), stated independently in two chapters -- both agree'
|
||
wythe_connector_spacing_in_oc: 24
|
||
wythe_connector_wire_gauge: '12 to 14 gauge, galvanized or stainless steel'
|
||
connection_center_third_of_span: true
|
||
|
||
camber_and_bowing_notes:
|
||
source: 'Section 5.12.5, p308-309 / 5-57 to 5-58'
|
||
thermal_bowing_greater_in_composite: true
|
||
bowing_usually_outward: true
|
||
|
||
# sources: 2026-09-07
|
||
# -> PCI Design Handbook 9th ed., Chapter 8 "Component Handling and
|
||
# Erection Bracing", pdf viewer p620-642, printed p8-3 to 8-23. Full
|
||
# extraction: knowledge/library/notes/PCI9-ch8-handling.md.
|
||
# -> rationale.md § catalogue.handling
|
||
handling:
|
||
stripping:
|
||
equivalent_static_load_multipliers:
|
||
source: 'Table 8.3.1, p629 / 8-10. SCREEN-VERIFIED 2026-09-07.'
|
||
note: 'For MEMBER FLEXURAL DESIGN ONLY -- NOT applied to lifting-device safety factors (which use the 4x-load factor below instead).'
|
||
exposed_aggregate_with_retarder:
|
||
flat_no_false_joints: 1.2
|
||
flat_false_joints_or_reveals: 1.3
|
||
fluted_proper_draft: 1.4
|
||
sculptured_other: 1.5
|
||
yard_handling_and_erection: 1.2
|
||
transportation: 1.5
|
||
smooth_form_release_agent_only:
|
||
flat_no_false_joints: 1.3
|
||
flat_false_joints_or_reveals: 1.4
|
||
fluted_proper_draft: 1.6
|
||
sculptured_other: 1.7
|
||
yard_handling_and_erection: 1.2
|
||
transportation: 1.5
|
||
|
||
allowable_tensile_stress:
|
||
formula: "ft_allowable = 7.5*sqrt(fc) / 1.5 = 5*sqrt(fc)"
|
||
factor_of_safety: 1.5
|
||
source: "Eq. 8-1, p629 / 8-10. Substitute f'ci for f'c during stripping."
|
||
|
||
prestressing_benefit_limits:
|
||
recommended_tensile_stress_limit: "5*sqrt(fci)"
|
||
recommended_avg_compression_after_losses_nonflexural_psi: {min: 125, max: 800}
|
||
source: 'Section 8.3.4.4, p630 / 8-11'
|
||
|
||
max_strand_diameter_by_slab_thickness:
|
||
source: 'Table 8.3.2, p630 / 8-11'
|
||
less_than_3_in: '3/8'
|
||
'3_in_or_more': '1/2 or larger'
|
||
|
||
post_tensioning:
|
||
transverse_reinforcement_exemption_max_width_ft: 12
|
||
monostrand_friction_coefficient: {min: 0.03, max: 0.05}
|
||
source: 'Section 8.3.4.4, p630 / 8-11 (ACI CODE-318-19 Section 24.4.3.5; Tanner 1977)'
|
||
|
||
moment_coefficients_edge_rotation:
|
||
source: 'Figure 8.3.1, p625 / 8-6'
|
||
two_point: {mx: 'w*a^2/8', my: '0.0107*w*a*b^2'}
|
||
four_point: {mx: 'w*a^2/8', my: '0.0027*w*a*b^2'}
|
||
moment_coefficients_flat_stripping:
|
||
source: 'Figure 8.3.2, p626 / 8-7'
|
||
two_point: {mx: '0.0107*w*a^2*b', my: '0.0214*w*a*b^2', mx_resisting_width: 'lesser of 15t or b/2'}
|
||
four_point: {mx: '0.0054*w*a^2*b', my: '0.0054*w*a*b^2', mx_resisting_width: 'lesser of 15t or b/4'}
|
||
|
||
rigging:
|
||
sling_angle_multiplier:
|
||
source: 'Figure 8.3.3, p627 / 8-8. Consistent with F = 1/sin(theta) to printed precision.'
|
||
'90_deg': 1.00
|
||
'75_deg': 1.04
|
||
'60_deg': 1.16
|
||
min_recommended_sling_angle_deg: 60
|
||
source_angle: 'Figures 8.3.4 / 8.3.11 / 8.6.2, p627 / p633 / p639'
|
||
|
||
lifting_devices:
|
||
aircraft_cable_wire_rope:
|
||
source: 'Table 8.3.3, p631 / 8-12. SCREEN-VERIFIED 2026-09-07. A safety factor of 4 (OSHA 1926.704) is already applied to these safe-load values.'
|
||
'3/8_in_aircraft_cable_safe_load_kip': 3.6
|
||
'7/16_in_wire_rope_safe_load_kip': 4.4
|
||
'1/2_in_wire_rope_safe_load_kip': 5.7
|
||
min_embedment_per_leg_in: 48
|
||
do_not_use_multiple_loops_single_location: true
|
||
|
||
strand_loops:
|
||
source: 'Section 8.3.5.2, p631 / 8-12'
|
||
safety_factor: 4
|
||
min_embedment_per_leg_in: 24
|
||
min_hook_diameter_x_strand_diameter: 4
|
||
min_bend_in: 2
|
||
default_safe_load_half_in_270ksi_single_loop_kip: 10
|
||
multi_strand_multiplier: {double: 1.7, triple: 2.2}
|
||
self_consolidating_concrete_caution: >-
|
||
Vertically inserted loops show lower pull-out strength
|
||
(air-bubble attraction around the strand); PCI TR-6-15
|
||
indicates longer embedment may be needed.
|
||
|
||
storage:
|
||
warpage_deflection:
|
||
formula: 'ymax = 22.5*w*sin(theta)*(l^4 + a^4) / (t^3 * Eci)'
|
||
time_dependent_formula: 'yt = ymax * (1 + lambda_delta)'
|
||
source: 'Eq. 8-2/8-3, p634-635 / 8-15 to 8-16'
|
||
support_at_0_2l_reduces_warpage_to_pct_of_end_support: 10
|
||
dimension_a_effect_pct_of_l_effect: 1
|
||
source: >-
|
||
p635 / 8-16 -- "most precast concrete producers will store panels
|
||
with support points at about 0.2l from each end, which will
|
||
reduce the warpage to approximately 10% of that of supports at
|
||
the ends" and "the effect of the dimension a is typically about
|
||
1% of that of l and can be ignored for usual storage conditions."
|
||
|
||
transportation:
|
||
common_payload_no_permit_tons: 24
|
||
standard_dimension_limits_ft: {vertical_horizontal: 8, length: 40}
|
||
lowboy_height_ft: {min: 10, max: 12}
|
||
total_height_no_permit: '13 ft 6 in (some states)'
|
||
max_width_with_permit_ft: {min: 10, max: 14}
|
||
length_permit_thresholds: 'varies by state -- some allow a simple permit over 70 ft, others require a special permit for any load over 55 ft'
|
||
weight_permit_thresholds: 'varies by state -- some allow up to 100 tons with a permit, others restrict severely above 25 tons'
|
||
source: 'Section 8.5, p635-636 / 8-16 to 8-17'
|
||
|
||
erection_stability:
|
||
safety_factors:
|
||
source: 'Table 8.7.1, p641 / 8-22. SCREEN-VERIFIED 2026-09-07.'
|
||
bracing_inserts_cast_in: 2
|
||
lifting_inserts: 4
|
||
lifting_hardware: 5
|
||
rotation_pick_coefficients:
|
||
source: 'Figure 8.6.1, p638 / 8-19. SCREEN-VERIFIED 2026-09-07.'
|
||
two_point_general:
|
||
reactions: ['w*l/(2a)', 'w*l*(1 - 1/(2a))']
|
||
neg_moment: '0.5*w*b^2*l^2'
|
||
pos_moment: '(w/2)*l^2*(1 - 1/(2a))^2'
|
||
constraint: 'a + b = 1.0'
|
||
two_point_equal_moments:
|
||
reactions_fraction: [0.70, 0.30]
|
||
positions_fraction_of_l: [0.29, 0.71]
|
||
neg_moment_coeff: 0.042
|
||
pos_moment_coeff: 0.045
|
||
two_point_four_point_stripping_locations:
|
||
reactions_fraction: [0.63, 0.37]
|
||
positions_fraction_of_l: [0.21, 0.79]
|
||
neg_moment_coeff: 0.022
|
||
pos_moment_coeff: 0.069
|
||
three_point_eight_point_stripping_locations:
|
||
reactions_fraction: [0.67, 0.33]
|
||
positions_fraction_of_l: [0.1, 0.3, 0.6]
|
||
positions_confidence: 'B -- read off the text layer, not screen-verified; the moment/reaction coefficients above ARE screen-verified'
|
||
neg_moment_coeff: -0.005
|
||
pos_moment_coeff: 0.055
|
||
three_point_alternate:
|
||
min_sling_length_x_l: 1.0
|
||
reactions_fraction: [0.77, 0.23]
|
||
neg_moment_coeff: -0.005
|
||
pos_moment_1_coeff: 0.036
|
||
pos_moment_2_coeff: 0.026
|
||
caution: 'see the source note on uncontrolled rolling, Section 8.6 p637 / 8-18'
|
||
asce_37_construction_loads: >-
|
||
Not adopted by IBC 2021 or ACI CODE-318-19; using ASCE 37 meets
|
||
the recognized standard of care absent contract-specific
|
||
construction-loading requirements. Source: Section 8.7.6,
|
||
p640 / 8-21.
|
||
|
||
# sources: 2026-09-07
|
||
# -> ACI 318-19, Chapter 25 "Reinforcement Details", §25.4 Development of
|
||
# reinforcement and §25.5 Splices. Read from the code's own text layer
|
||
# (knowledge/ACI318-19-ch25_decoded.txt, cross-checked against the cleaned
|
||
# extraction knowledge/ACI318-19-ch25.md). PUBLIC: this is the model code,
|
||
# the same for every producer and every job -- it identifies nobody.
|
||
# Cites below are the ACI PRINTED page (the number in the page footer);
|
||
# the raw text layer's own convention is printed = PDF page - 2.
|
||
# Full extraction and the page-level confidence marks:
|
||
# knowledge/library/notes/ACI318-19-ch25-development.md
|
||
# -> rationale.md § catalogue.development_length
|
||
development_length:
|
||
sqrt_fc_cap_psi: 100.0 # §25.4.1.4, p.471 -- use sqrt(100) when fc > 10,000 psi
|
||
minimums_in:
|
||
# The floor under every §25.4 calculated length -- "greater of (a)/(b)/(c)".
|
||
tension_general_or_simplified: 12.0 # §25.4.2.1(b), p.471
|
||
hooked_bar_db: 8.0 # §25.4.3.1(b), p.474
|
||
hooked_bar_in: 6.0 # §25.4.3.1(c), p.474
|
||
headed_bar_db: 8.0 # §25.4.4.2(b), p.477
|
||
headed_bar_in: 6.0 # §25.4.4.2(c), p.477
|
||
compression_in: 8.0 # §25.4.9.1(b), p.487
|
||
wwr_deformed_in: 8.0 # §25.4.6.1(b), p.483
|
||
wwr_plain_in: 6.0 # §25.4.7.1(b), p.484
|
||
|
||
high_grade_transverse_requirement:
|
||
# fy >= 80,000 psi bars spaced closer than 6 in. o.c. need transverse
|
||
# reinforcement sized so Ktr is never smaller than 0.5*db. Same rule
|
||
# stated twice, once for development and once for lap splices.
|
||
fy_threshold_psi: 80000
|
||
spacing_threshold_in: 6.0
|
||
ktr_min_factor_db: 0.5
|
||
source_development: 'ACI 318-19 §25.4.2.2, p.471'
|
||
source_lap_splice: 'ACI 318-19 §25.5.1.5, p.488'
|
||
|
||
tension:
|
||
general:
|
||
formula: 'ld = (3*fy*psi_t*psi_e*psi_s*psi_g / (40*lambda*sqrt(fc))) * (db / ((cb+Ktr)/db))'
|
||
source: 'ACI 318-19 §25.4.2.4, Eq. 25.4.2.4a, p.472'
|
||
confinement_term_max: 2.5 # (cb+Ktr)/db shall not exceed 2.5
|
||
source_confinement_max: 'ACI 318-19 §25.4.2.4, p.472'
|
||
ktr_formula: 'Ktr = 40*Atr/(s*n)'
|
||
source_ktr: 'ACI 318-19 §25.4.2.4b, p.473'
|
||
ktr_zero_permitted: true # design simplification, even if transverse reinf. present
|
||
cb_definition: 'lesser of: distance from bar/wire centre to nearest concrete surface; one-half the c-c spacing of the bars/wires'
|
||
source_cb: 'ACI 318-19 §25.4.2.4, p.472'
|
||
modification_factors:
|
||
psi_t: {top_bar: 1.3, other: 1.0} # >12in fresh concrete below reinforcement
|
||
psi_e: {epoxy_low_cover_or_spacing: 1.5, epoxy_other: 1.2, uncoated_or_galvanized: 1.0}
|
||
psi_s: {no7_and_larger: 1.0, no6_and_smaller: 0.8}
|
||
psi_g: {grade_40_or_60: 1.0, grade_80: 1.15, grade_100: 1.3}
|
||
lambda: {lightweight: 0.75, normalweight: 1.0}
|
||
psi_t_times_psi_e_max: 1.7 # footnote, p.473
|
||
source: 'ACI 318-19 Table 25.4.2.5, p.473-474'
|
||
|
||
simplified:
|
||
# Table 25.4.2.3. ld is based on two preselected (cb+Ktr)/db values
|
||
# (1.5 for case1, 1.0 for case2) rather than the actual ratio -- see
|
||
# R25.4.2.3, p.472. case1 = clear spacing/cover/ties meet the
|
||
# favourable row; case2 = everything else.
|
||
no6_and_smaller:
|
||
case1: 'ld = (fy*psi_t*psi_e*psi_s*psi_g / (25*lambda*sqrt(fc))) * db'
|
||
case2: 'ld = (3*fy*psi_t*psi_e*psi_s*psi_g / (50*lambda*sqrt(fc))) * db'
|
||
no7_and_larger:
|
||
case1: 'ld = (fy*psi_t*psi_e*psi_g / (20*lambda*sqrt(fc))) * db'
|
||
case2: 'ld = (3*fy*psi_t*psi_e*psi_g / (40*lambda*sqrt(fc))) * db'
|
||
source: 'ACI 318-19 Table 25.4.2.3, p.472'
|
||
worked_example_check: >-
|
||
R25.4.2.3's own worked example (fy=60,000 psi, lambda=1, uncoated,
|
||
bottom bar, fc=4,000 psi) gives no7_and_larger.case1 = 47*db and
|
||
case2 = 71*db off these same coefficients -- p.472.
|
||
|
||
hooked_bar:
|
||
formula: 'ldh = (fy*psi_e*psi_r*psi_o*psi_c / (50*lambda*sqrt(fc))) * db'
|
||
source: 'ACI 318-19 §25.4.3.1(a), p.474'
|
||
measured_from: 'critical section to the outside end (edge) of the hook'
|
||
modification_factors:
|
||
psi_e: {coated: 1.2, uncoated_or_galvanized: 1.0}
|
||
psi_r: {no11_or_smaller_confined: 1.0, other: 1.6} # Ath >= 0.4*Ahs or s >= 6db
|
||
psi_o: {inside_column_core_or_side_cover_ge_6db: 1.0, other: 1.25}
|
||
psi_c: {fc_lt_6000: 'fc/15000 + 0.6', fc_ge_6000: 1.0}
|
||
lambda: {lightweight: 0.75, normalweight: 1.0}
|
||
source: 'ACI 318-19 Table 25.4.3.2, p.474-475'
|
||
discontinuous_end_tie_spacing_max_db: 3 # both side + top/bottom cover < 2.5in
|
||
source_discontinuous_end: 'ACI 318-19 §25.4.3.4, p.476'
|
||
|
||
headed_bar:
|
||
formula: 'ldt = (1.5*fy*psi_e*psi_p*psi_o*psi_c / (75*sqrt(fc))) * db'
|
||
source: 'ACI 318-19 §25.4.4.2(a), p.477'
|
||
no_lambda_normalweight_only: true # §25.4.4.1(d) requires normalweight concrete
|
||
conditions:
|
||
max_bar_size: 11
|
||
abrg_min: '4*Ab' # net bearing area of head
|
||
clear_cover_min_db: 2
|
||
ctc_spacing_min_db: 3
|
||
source_conditions: 'ACI 318-19 §25.4.4.1, p.477'
|
||
modification_factors:
|
||
psi_e: {coated: 1.2, uncoated_or_galvanized: 1.0}
|
||
psi_p: {no11_or_smaller_confined: 1.0, other: 1.6} # Att >= 0.3*Ahs or s >= 6db
|
||
psi_o: {inside_column_core_or_side_cover_ge_6db: 1.0, other: 1.25}
|
||
psi_c: {fc_lt_6000: 'fc/15000 + 0.6', fc_ge_6000: 1.0}
|
||
source: 'ACI 318-19 Table 25.4.4.3, p.480'
|
||
|
||
compression:
|
||
formula: 'ldc = max((fy*psi_r/(50*lambda*sqrt(fc)))*db, 0.0003*fy*psi_r*db)'
|
||
source: 'ACI 318-19 §25.4.9.2, p.487'
|
||
modification_factors:
|
||
psi_r: {enclosed_spiral_tie_or_hoop: 0.75, other: 1.0, permitted_default: 1.0}
|
||
lambda: {lightweight: 0.75, normalweight: 1.0}
|
||
source: 'ACI 318-19 Table 25.4.9.3, p.487'
|
||
|
||
excess_reinforcement_reduction:
|
||
ratio: '(As_required / As_provided)'
|
||
source: 'ACI 318-19 §25.4.10.1, p.487'
|
||
applies_to: ['tension.general (§25.4.2.1a)', 'wwr.deformed (§25.4.6.1a)', 'wwr.plain (§25.4.7.1a)', 'compression (§25.4.9.1a)']
|
||
floor: 'never below the matching entry in minimums_in'
|
||
not_permitted:
|
||
noncontinuous_supports: true
|
||
anchorage_or_development_for_fy_required: true
|
||
bars_required_continuous: true
|
||
hooked_headed_or_mechanically_anchored: true
|
||
seismic_design_category_c_d_e_or_f: true
|
||
pile_anchorage_seismic_design_category_c_d_e_or_f: true
|
||
source_exclusions: 'ACI 318-19 §25.4.10.2, p.487-488'
|
||
excluded_from_lap_splices: true # §25.5.1.4 -- never permitted when calculating a lap length
|
||
source_lap_exclusion: 'ACI 318-19 §25.5.1.4, p.488'
|
||
|
||
wwr:
|
||
deformed:
|
||
formula: 'ld = ld_per_tension_simplified_or_general * psi_w'
|
||
source: 'ACI 318-19 §25.4.6.2, p.483'
|
||
measured_from: 'critical section to the end of wire'
|
||
requires_all_wires_le_D31: true
|
||
psi_w:
|
||
case_a: 'psi_w = (fy - 35000) / fy'
|
||
case_b: 'psi_w = 5*db/s'
|
||
max: 1.0
|
||
applies_when: 'at least one cross wire within ld, at least 2in from the critical section'
|
||
no_qualifying_cross_wire: 1.0
|
||
source: 'ACI 318-19 §25.4.6.3 / §25.4.6.4, p.483-484'
|
||
confidence: >-
|
||
B -- case_a is reconstructed from a fragmented raw-text-layer
|
||
equation image (two occurrences of fy, one occurrence of
|
||
35,000, one subtraction, no other terms; no rendered page was
|
||
available to confirm placement). case_b (5*db/s) reads
|
||
unambiguously off the same page. Re-verify case_a against a
|
||
rendered page before treating it as A.
|
||
epoxy_psi_e_permitted: 1.0 # for epoxy-coated WWR meeting §25.4.6.3
|
||
source_epoxy: 'ACI 318-19 §25.4.6.2, p.483'
|
||
no_qualifying_wire_or_zinc_coated_use: 'plain WWR provisions (§25.4.7)'
|
||
source_fallback: 'ACI 318-19 §25.4.6.5 / §25.4.6.6, p.484'
|
||
plain:
|
||
formula: 'ld = max(spacing_of_cross_wires + 2, 0.27*(fy*Ab)/(s*lambda*sqrt(fc)))'
|
||
source: 'ACI 318-19 §25.4.7.2, p.484-485'
|
||
measured_from: 'critical section to the outermost cross wire'
|
||
requires_min_two_cross_wires: true
|
||
source_min_cross_wires: 'ACI 318-19 §25.4.7.1, p.484'
|
||
variables: 'Ab = area of the individual wire being developed; s = spacing between the wires being developed; lambda per Table 25.4.2.5'
|
||
|
||
strand:
|
||
# Pretensioned seven-wire strand, clean, 1/4in / 3/8in / 1/2in diameter,
|
||
# bonded applications only.
|
||
development:
|
||
formula: 'ld = (fse/3000)*db + ((fps - fse)/1000)*db'
|
||
source: 'ACI 318-19 §25.4.8.1, Eq. 25.4.8.1, p.485'
|
||
applies_to: 'seven-wire strand, clean, 1/4in/3/8in/1/2in diameter, bonded'
|
||
does_not_apply_to: ['plain wires', 'end-anchored tendons', 'unstressed strand']
|
||
source_scope: 'ACI 318-19 §25.4.8, p.485'
|
||
max_fps_tested_psi: 275000
|
||
transfer_length_formula: '(fse/3000)*db'
|
||
transfer_db: 50.0 # shorthand at fse = 150,000 psi: (150000/3000) = 50
|
||
transfer_db_basis_fse_psi: 150000
|
||
additional_bonded_length_formula: '((fps - fse)/1000)*db'
|
||
doubling_required_when_not_bonded_to_end_and_tension_at_service: true
|
||
source_doubling: 'ACI 318-19 §25.4.8.1(b), p.485'
|
||
doubling_exception_zero_tension_service_loads: true
|
||
source_doubling_exception: 'ACI 318-19 §24.5.2, discussed at R25.4.8.3, p.486'
|
||
reduced_embedment_permitted:
|
||
condition: 'design strand stress at the section does not exceed the bilinear Eq. 25.4.8.1 relationship'
|
||
source: 'ACI 318-19 §25.4.8.2 / §25.4.8.3, p.485-486'
|
||
correction: >-
|
||
The extraction note filed the doubling requirement under §25.4.8.3;
|
||
the code text puts it at §25.4.8.1(b) (conditioned on "bonding does
|
||
not extend to end of member AND design includes tension at service
|
||
loads"). §25.4.8.3 is the separate, related provision permitting
|
||
embedment SHORTER than ld at a section, and the "twice ld" / zero-
|
||
tension-exception language the note quoted from there is R25.4.8.3
|
||
COMMENTARY explaining the §25.4.8.1(b) rule, not a second code rule.
|
||
|
||
lap:
|
||
max_bar_size: 11 # bars larger than No. 11 may not be lap spliced
|
||
source_max_bar_size: 'ACI 318-19 §25.5.1.1, p.488'
|
||
tension:
|
||
class_a_factor: 1.0
|
||
class_b_factor: 1.3
|
||
min_in: 12.0
|
||
formula: 'lst = max(factor*ld, min_in)'
|
||
ld_basis: 'ld per §25.4.2.1(a)'
|
||
class_a_requires: 'As_provided/As_required >= 2.0 over the splice length, AND <= 50 percent of As spliced within the required lap length'
|
||
class_b_requires: 'anything not meeting Class A (includes every case where As_provided/As_required < 2.0)'
|
||
source: 'ACI 318-19 §25.5.2.1, Table 25.5.2.1, p.488-489'
|
||
different_size_bars: 'lst = greater of ld(larger bar) and lst(smaller bar)'
|
||
source_different_size: 'ACI 318-19 §25.5.2.2, p.489'
|
||
compression:
|
||
fy_le_60000: 'lsc = max(0.0005*fy*db, 12 in.)'
|
||
fy_60000_to_80000: 'lsc = max((0.0009*fy - 24)*db, 12 in.)'
|
||
fy_gt_80000: 'lsc = max((0.0009*fy - 24)*db, lst_per_25.5.2.1)'
|
||
source: 'ACI 318-19 §25.5.5.1(a-c), p.491'
|
||
fc_lt_3000_increase_factor: 1.3333 # "increased by one-third"
|
||
source_increase: 'ACI 318-19 §25.5.5.1, p.491'
|
||
no14_no18_to_no11_or_smaller_permitted: true # the only exception to max_bar_size above
|
||
source_exception: 'ACI 318-19 §25.5.5.3, p.491'
|
||
different_size_bars: 'lsc = greater of ldc(larger bar, per §25.4.9.1) and lsc(smaller bar, per §25.5.5.1)'
|
||
source_different_size: 'ACI 318-19 §25.5.5.4, p.491'
|
||
wwr_deformed:
|
||
formula: 'lst = max(1.3*ld, 8 in.)'
|
||
source: 'ACI 318-19 §25.5.3.1, p.489-490'
|
||
wwr_plain:
|
||
formula: 'lst = max(spacing_of_cross_wires + 2, 1.5*ld, 6 in.)'
|
||
formula_when_As_ratio_ge_2: 'lst = max(1.5*ld, 2 in.)'
|
||
source: 'ACI 318-19 §25.5.4.1 / §25.5.4.2, p.490-491'
|
||
|
||
# sources: 2026-08-30 2026-08-31
|
||
# -> rationale.md § connectors
|
||
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:
|
||
# KEYED BY THE FULL PRODUCT NAME, manufacturer included, because that
|
||
# is how the owner wrote it and -- measured 2026-08-31 -- it is also
|
||
# verbatim what the model's connector TYPE carries in its description
|
||
# field. (Which field that is, is plant knowledge and is named in the
|
||
# plant layer through the `member.identity_description` role, never
|
||
# here.) One spelling, and the alias table has nothing to translate.
|
||
# ---- THE STANDARD (NON-COMPOSITE) LINE -----------------------------
|
||
#
|
||
# SOURCE FOR EVERY VALUE IN THE THREE ENTRIES BELOW: W1 (hkties.com
|
||
# standard / non-composite products page, captured 2026-08-30), re-read
|
||
# against the live page by the landing agent 2026-09-01 -- the whole
|
||
# ST50/ST75/ST100 comparison table and its three footnotes, transcribed
|
||
# a second time and compared cell by cell. Every cell agreed. The
|
||
# capture is a clue; the page is the source, and this line is the
|
||
# difference (CLAUDE.md, the three-stage law).
|
||
#
|
||
# A CAPTURE HASH IS NOT A DOCUMENT HASH. The vendor can edit the page
|
||
# tomorrow and nothing here would notice, so read these as "what that
|
||
# page said on those dates", and re-fetch before relying on one in an
|
||
# engineering decision.
|
||
#
|
||
# THE TABLE'S OWN IDENTITY, ASSERTED AT LANDING: insulation thickness
|
||
# (2/3/4 in) tracks the designation number (ST50/ST75/ST100 = 50/75/100
|
||
# mm), and tie length grows with it (5.31 / 6.25 / 7.25 in). Both hold
|
||
# across all three columns, which is what makes a row-shift detectable.
|
||
# ONE COLUMN DOES NOT RISE MONOTONICALLY AND IT IS NOT AN ERROR:
|
||
# `ultimate_panel_shear_per_tie_lb` reads 648 / 924 / 780 -- ST75 is the
|
||
# highest and ST100 is BELOW it. That was checked twice against the page
|
||
# for exactly the reason the identity rule exists, and the page really
|
||
# does print it that way. Do not "correct" it into a rising series.
|
||
'HK Composites (ST50)':
|
||
manufacturer: HK Composites
|
||
designation: ST50
|
||
system: standard_non_composite
|
||
design_basis: non_composite
|
||
tie_length_in: 5.31
|
||
embedment_head_in: 1.5
|
||
embedment_tip_in: 1.81
|
||
foam_plug_diameter_in: 0.5
|
||
insulation_thickness_in: 2.0
|
||
structural_wythe_min_in: 2.0
|
||
fascia_wythe_range_in: [2.0, 4.0]
|
||
ultimate_tensile_pullout_lb: 1260
|
||
shear_strength_lb: 1300
|
||
ultimate_panel_shear_per_tie_lb: 648
|
||
basis_fc_psi: 3000
|
||
test_criteria: 'ICC-ES AC 320'
|
||
thermal_conductivity_btu_in_hr_ft2_f: 2.1
|
||
fire_performance: >-
|
||
Resists a 300 lb tension load for over 90 minutes when fire tested
|
||
per ASTM E1512-01 section 7.4.3.
|
||
alkaline_resistance: >-
|
||
Excellent -- 99.1% retained strength after 3,000 hours in pH 12
|
||
solution.
|
||
service_temperature_f: [-40, 200]
|
||
# THE ONE NUMBER THAT DID NOT ARRIVE WITH THE REST. The page publishes
|
||
# no working load and no safety factor; see `safety_factors` below.
|
||
capacity_lb: null
|
||
capacity_unknown_because: >-
|
||
The three capacities above are ULTIMATES and are named as such. The
|
||
page publishes no working load and no safety factor, so a single
|
||
`capacity_lb` -- which every reader would take for an allowable --
|
||
cannot be derived from them. A check that needs a working load
|
||
stands down naming this key; a check that can consume an ultimate
|
||
reads the `ultimate_*` keys and declares that it is doing so.
|
||
min_edge_distance_in: null
|
||
min_edge_distance_unknown_because: >-
|
||
Still not published. The vendor's own product page carries embedment
|
||
depths and wythe thicknesses but NO edge distance for any
|
||
designation, so the 2026-09-01 landing did not fill this and did not
|
||
weaken the rule that filled it for ST100: it is a property of the
|
||
PRODUCT, the check that needs it stands down naming this key, and it
|
||
may never be filled from another product's datasheet.
|
||
|
||
# ST75 IS NEW HERE, added 2026-09-01 off the same table. It was not in
|
||
# this file before because nobody had read the page; it is neither
|
||
# evidenced on a job nor named by the owner, and it is landed because
|
||
# the table publishes it, which is what a public catalogue is for.
|
||
'HK Composites (ST75)':
|
||
manufacturer: HK Composites
|
||
designation: ST75
|
||
system: standard_non_composite
|
||
design_basis: non_composite
|
||
tie_length_in: 6.25
|
||
embedment_head_in: 1.5
|
||
embedment_tip_in: 1.73
|
||
foam_plug_diameter_in: 0.57
|
||
insulation_thickness_in: 3.0
|
||
structural_wythe_min_in: 2.0
|
||
fascia_wythe_range_in: [2.0, 4.0]
|
||
ultimate_tensile_pullout_lb: 1660
|
||
shear_strength_lb: 1700
|
||
ultimate_panel_shear_per_tie_lb: 924
|
||
basis_fc_psi: 3000
|
||
test_criteria: 'ICC-ES AC 320'
|
||
thermal_conductivity_btu_in_hr_ft2_f: 2.1
|
||
fire_performance: >-
|
||
Resists a 300 lb tension load for over 90 minutes when fire tested
|
||
per ASTM E1512-01 section 7.4.3.
|
||
alkaline_resistance: >-
|
||
Excellent -- 99.1% retained strength after 3,000 hours in pH 12
|
||
solution.
|
||
service_temperature_f: [-40, 200]
|
||
capacity_lb: null
|
||
capacity_unknown_because: >-
|
||
As ST50 -- the published figures are ultimates and the page states
|
||
no safety factor.
|
||
min_edge_distance_in: null
|
||
min_edge_distance_unknown_because: >-
|
||
Not published on the page, and NOT inherited from ST100's 3.0 in.
|
||
That number came from the owner about ST100 specifically.
|
||
'HK Composites (ST100)':
|
||
manufacturer: HK Composites
|
||
designation: ST100
|
||
system: standard_non_composite
|
||
design_basis: non_composite
|
||
tie_length_in: 7.25
|
||
embedment_head_in: 1.5
|
||
embedment_tip_in: 1.73
|
||
foam_plug_diameter_in: 0.57
|
||
insulation_thickness_in: 4.0
|
||
structural_wythe_min_in: 2.0
|
||
fascia_wythe_range_in: [2.0, 4.0]
|
||
ultimate_tensile_pullout_lb: 1660
|
||
shear_strength_lb: 1700
|
||
# 780, and it is LOWER than ST75's 924. See the identity note above.
|
||
ultimate_panel_shear_per_tie_lb: 780
|
||
basis_fc_psi: 3000
|
||
test_criteria: 'ICC-ES AC 320'
|
||
thermal_conductivity_btu_in_hr_ft2_f: 2.1
|
||
fire_performance: >-
|
||
Resists a 300 lb tension load for over 90 minutes when fire tested
|
||
per ASTM E1512-01 section 7.4.3.
|
||
alkaline_resistance: >-
|
||
Excellent -- 99.1% retained strength after 3,000 hours in pH 12
|
||
solution.
|
||
service_temperature_f: [-40, 200]
|
||
capacity_lb: null
|
||
capacity_unknown_because: >-
|
||
As ST50 -- the published figures are ultimates and the page states
|
||
no safety factor. The tensile and shear figures happen to equal
|
||
ST75's; the panel-shear figure does not, and none of the three is
|
||
inherited from anywhere. Each was read off this designation's own
|
||
column.
|
||
# STATED BY THE OWNER, 2026-08-31: "pin edge distance = 3". ST100 的
|
||
# 知识。写。" -- a number, for this designation, in his own words.
|
||
# ST50 and the rest stay null: he gave one product's number and
|
||
# borrowing it is the thing `min_edge_distance_unknown_because`
|
||
# exists to forbid.
|
||
min_edge_distance_in: 3.0
|
||
min_edge_distance_source: >-
|
||
Stated by the owner 2026-08-31 ("pin edge distance = 3"). Not read
|
||
off a datasheet -- when HK Composites' sheet arrives it is worth
|
||
checking against, and a disagreement is a question for him, not a
|
||
silent replacement.
|
||
# THE 6.0 IN CALIBRATION THAT USED TO SIT HERE HAS BEEN WITHDRAWN, and
|
||
# withdrawing it is the point rather than an omission. It was the
|
||
# smallest in-plane distance measured from a pin to the PANEL edge,
|
||
# and 2026-08-31 the owner defined the measurement differently: the
|
||
# edge that governs is the INSULATION edge (see `edge_reference`
|
||
# below). A pin-to-panel-edge number is not a calibration for a
|
||
# pin-to-insulation-edge check -- the two are different measurements
|
||
# of different things, and carrying the 6.0 across would have set an
|
||
# expectation the first live run then looked like a regression
|
||
# against. The insulation-edge distances on this job are UNMEASURED.
|
||
# Whatever the first run prints is new information.
|
||
|
||
# ---- THE CA (COMPOSITE ACTION) LINE, landed 2026-09-01 --------------
|
||
#
|
||
# SOURCE FOR EVERY VALUE IN THE THREE ENTRIES BELOW: W2 (hkties.com
|
||
# CA / composite-action products page, captured 2026-08-30), re-read
|
||
# against the live page by the landing agent 2026-09-01, cell by cell,
|
||
# with every footnote. Every cell agreed.
|
||
#
|
||
# A DIFFERENT DESIGN BASIS, NOT A BIGGER TIE. These are for panels
|
||
# designed to act COMPOSITELY -- the vendor's own sentence is in
|
||
# `design_bases` below -- and they are glass-fibre reinforced where the
|
||
# Standard line deliberately is not. The capacities are three to five
|
||
# times the Standard line's, which is exactly why nothing may read one
|
||
# line's number onto the other's designation.
|
||
#
|
||
# THE TABLE'S IDENTITY, ASSERTED AT LANDING: insulation thickness
|
||
# (2/3/4 in) tracks the designation (CA50/CA75/CA100), tie length rises
|
||
# (5.5 / 6.5 / 7.5 in), ultimate tension is CONSTANT across all three
|
||
# (5,900 lb -- it is a property of the tie's own section, not of the
|
||
# panel), and ultimate shear FALLS as the tie gets longer
|
||
# (5,315 / 4,902 / 4,489), as does the 5% fractile (5,183 / 4,720 /
|
||
# 4,257). Every fractile value sits below its own ultimate, on every
|
||
# row, which is the check that catches a shifted column.
|
||
'HK Composites (CA50)':
|
||
manufacturer: HK Composites
|
||
designation: CA50
|
||
system: composite_action
|
||
design_basis: composite
|
||
tie_length_in: 5.5
|
||
embedment_head_in: 1.75
|
||
embedment_tip_in: 1.75
|
||
foam_section_in: [0.47, 3.13]
|
||
insulation_thickness_in: 2.0
|
||
wythe_1_range_in: [2.0, 6.0]
|
||
wythe_2_range_in: [2.0, 6.0]
|
||
ultimate_tension_lb: 5900
|
||
ultimate_tension_basis_fc_psi: 5000
|
||
ultimate_shear_lb: 5315
|
||
shear_5pct_fractile_95pct_confidence_lb: 5183
|
||
shear_basis_fc_psi: 5000
|
||
test_criteria: 'ICC-ES AC 320'
|
||
thermal_conductivity_btu_in_hr_ft2_f: 1.75
|
||
fire_performance: >-
|
||
Resists a 300 lb tension load for over 90 minutes when fire tested
|
||
per ASTM E1512-01 section 7.4.3.
|
||
alkaline_resistance: >-
|
||
Excellent -- 96.2% retained strength after 3,000 hours in pH 12
|
||
solution.
|
||
service_temperature_f: [-40, 200]
|
||
capacity_lb: null
|
||
capacity_unknown_because: >-
|
||
Ultimates only, and the page states no safety factor. See
|
||
`safety_factors` below. The 5% fractile is NOT a working load
|
||
either -- it is a statistical lower bound on the same ultimate
|
||
test population, with no factor applied.
|
||
min_edge_distance_in: null
|
||
min_edge_distance_unknown_because: >-
|
||
The CA page publishes no edge distance for any designation. Not
|
||
inherited from the ST100 figure, which came from the owner about a
|
||
different product on a different design basis.
|
||
'HK Composites (CA75)':
|
||
manufacturer: HK Composites
|
||
designation: CA75
|
||
system: composite_action
|
||
design_basis: composite
|
||
tie_length_in: 6.5
|
||
embedment_head_in: 1.75
|
||
embedment_tip_in: 1.75
|
||
foam_section_in: [0.47, 3.13]
|
||
insulation_thickness_in: 3.0
|
||
wythe_1_range_in: [2.0, 6.0]
|
||
wythe_2_range_in: [2.0, 6.0]
|
||
ultimate_tension_lb: 5900
|
||
ultimate_tension_basis_fc_psi: 5000
|
||
ultimate_shear_lb: 4902
|
||
shear_5pct_fractile_95pct_confidence_lb: 4720
|
||
shear_basis_fc_psi: 5000
|
||
test_criteria: 'ICC-ES AC 320'
|
||
thermal_conductivity_btu_in_hr_ft2_f: 1.75
|
||
fire_performance: >-
|
||
Resists a 300 lb tension load for over 90 minutes when fire tested
|
||
per ASTM E1512-01 section 7.4.3.
|
||
alkaline_resistance: >-
|
||
Excellent -- 96.2% retained strength after 3,000 hours in pH 12
|
||
solution.
|
||
service_temperature_f: [-40, 200]
|
||
capacity_lb: null
|
||
capacity_unknown_because: >-
|
||
As CA50 -- ultimates, no published safety factor.
|
||
min_edge_distance_in: null
|
||
min_edge_distance_unknown_because: >-
|
||
Not published on the page.
|
||
'HK Composites (CA100)':
|
||
manufacturer: HK Composites
|
||
designation: CA100
|
||
system: composite_action
|
||
design_basis: composite
|
||
tie_length_in: 7.5
|
||
embedment_head_in: 1.75
|
||
embedment_tip_in: 1.75
|
||
foam_section_in: [0.47, 3.13]
|
||
insulation_thickness_in: 4.0
|
||
wythe_1_range_in: [2.0, 6.0]
|
||
wythe_2_range_in: [2.0, 6.0]
|
||
ultimate_tension_lb: 5900
|
||
ultimate_tension_basis_fc_psi: 5000
|
||
ultimate_shear_lb: 4489
|
||
shear_5pct_fractile_95pct_confidence_lb: 4257
|
||
shear_basis_fc_psi: 5000
|
||
test_criteria: 'ICC-ES AC 320'
|
||
thermal_conductivity_btu_in_hr_ft2_f: 1.75
|
||
fire_performance: >-
|
||
Resists a 300 lb tension load for over 90 minutes when fire tested
|
||
per ASTM E1512-01 section 7.4.3.
|
||
alkaline_resistance: >-
|
||
Excellent -- 96.2% retained strength after 3,000 hours in pH 12
|
||
solution.
|
||
service_temperature_f: [-40, 200]
|
||
capacity_lb: null
|
||
capacity_unknown_because: >-
|
||
As CA50 -- ultimates, no published safety factor.
|
||
min_edge_distance_in: null
|
||
min_edge_distance_unknown_because: >-
|
||
Not published on the page.
|
||
|
||
# -> rationale.md § connectors.design_bases
|
||
design_bases:
|
||
non_composite:
|
||
applies_to_system: standard_non_composite
|
||
designations: [DP25, DP30s, DP38, DP40, ST50, ST60, ST75, ST100]
|
||
# SOURCE: W1 (hkties.com standard page, captured 2026-08-30,
|
||
# re-read live 2026-09-01). The page's own sentence, verbatim.
|
||
source_sentence: >-
|
||
"This system is designed to create a non-composite insulated
|
||
concrete sandwich panel" -- the two wythes of concrete are tied
|
||
together but the design "still allow[s] the two layers to shrink or
|
||
expand independently", the tie flexing to take the differential
|
||
movement.
|
||
what_it_means: >-
|
||
The wythes are NOT designed to act as one section. The ties carry
|
||
the fascia wythe and flex under the differential thermal movement
|
||
between the two wythes; the structural wythe carries the panel.
|
||
source: 'W1 -- hkties.com standard / non-composite products page, captured 2026-08-30, re-read 2026-09-01'
|
||
composite:
|
||
applies_to_system: composite_action
|
||
designations: [CA25, CA40, CA50, CA75, CA100, CA125, CA150]
|
||
# SOURCE: W2 (hkties.com CA page, captured 2026-08-30, re-read live
|
||
# 2026-09-01). The page's own sentence, verbatim.
|
||
source_sentence: >-
|
||
"The two wythes of concrete are acting together structurally thus
|
||
allowing a thinner panel to be created."
|
||
what_it_means: >-
|
||
The wythes ARE designed to act together, so the section a
|
||
calculation may use is the composite one -- which is the whole
|
||
reason the panel can be thinner.
|
||
source: 'W2 -- hkties.com CA / composite-action products page, captured 2026-08-30, re-read 2026-09-01'
|
||
# A THIRD ANSWER EXISTS AND IT IS THE HONEST DEFAULT.
|
||
unknown_is_not_non_composite: >-
|
||
A panel whose tie designation is not in either list above, or which
|
||
carries no recognised tie at all, has an UNKNOWN design basis. It is
|
||
not non-composite by default and it is not composite by default. The
|
||
lookup returns None with the reason, in the same discipline as
|
||
knowledge.same_face().
|
||
|
||
# -> rationale.md § connectors.product_line_no_published_capacity
|
||
product_line_no_published_capacity:
|
||
standard_non_composite:
|
||
# SOURCE: W1, product-line table (captured 2026-08-30, re-read 2026-09-01)
|
||
DP25: {description: 'Double-Prong 1" Tie', capacity_lb: null}
|
||
DP30s: {description: 'Double-Prong 1" Tie', capacity_lb: null}
|
||
DP38: {description: 'Double-Prong 1.50" Tie', capacity_lb: null}
|
||
DP40: {description: 'Double-Prong 1.50" Tie', capacity_lb: null}
|
||
ST60: {description: 'Standard 2.5" Tie', capacity_lb: null}
|
||
composite_action:
|
||
# SOURCE: W2, product-line table (captured 2026-08-30, re-read 2026-09-01)
|
||
CA25: {description: 'Quad Tip 1" Tie', capacity_lb: null}
|
||
CA40: {description: 'Quad Tip 1.5" Tie', capacity_lb: null}
|
||
CA125: {description: 'Quad Tip 5" Tie', capacity_lb: null}
|
||
CA150: {description: 'Quad Tip 6" Tie', capacity_lb: null}
|
||
unknown_because: >-
|
||
The manufacturer's pages name these model numbers in the product-line
|
||
list and tabulate capacities only for ST50/ST75/ST100 and
|
||
CA50/CA75/CA100. No capacity is published for the models above, in
|
||
any unit, on either page. They exist; nothing else about them is
|
||
known here, and nothing may be interpolated from the tabulated
|
||
neighbours.
|
||
|
||
# -> rationale.md § connectors.safety_factors
|
||
safety_factors:
|
||
tension_fos: null
|
||
shear_fos: null
|
||
unknown_because: >-
|
||
Both manufacturer pages publish ULTIMATE capacities and state no
|
||
safety factor anywhere -- no heading, no footnote, no test citation.
|
||
A working load cannot be derived from an ultimate without one, and
|
||
the 4:1 published for the disk-anchor inserts belongs to another
|
||
manufacturer's product and may not be borrowed. Read 2026-09-01
|
||
against both live pages by the landing agent; the absence was looked
|
||
for, not assumed.
|
||
capacity_is_ultimate: true
|
||
|
||
# sources: 2026-08-31
|
||
# -> rationale.md § connectors.edge_reference
|
||
edge_reference:
|
||
measured_to: insulation_edge
|
||
stated_by: Will
|
||
stated_on: '2026-08-31'
|
||
what_it_means: >-
|
||
A connector's edge distance is measured to the edge of the INSULATION,
|
||
not to the edge of the concrete panel. On a piece whose insulation runs
|
||
to the panel edge the two are the same number; where they differ, the
|
||
insulation governs.
|
||
# A SOLID ZONE THAT GOES THROUGH REDEFINES THE EDGE; A RECESS DOES NOT.
|
||
# Full depth means concrete has REPLACED the insulation there, so the
|
||
# zone's border is a real insulation boundary and a pin beside it is at
|
||
# an edge. A recess is partial depth: insulation still runs under it,
|
||
# the pin still has insulation on every side, and the original boundary
|
||
# governs.
|
||
through_cut_solid_zone_moves_the_edge: true
|
||
recess_moves_the_edge: false
|
||
consequences: >-
|
||
The check's reference geometry is the insulation extent MINUS the
|
||
solid zones that cut through it. That is the same solid-zone
|
||
population rows 5.11-5.13 recognise -- ONE recognition, several
|
||
consumers, and a second reader for the same parts is how two rows
|
||
come to disagree about what is on a piece. Recesses are excluded from
|
||
it entirely, on his sentence: they never move the edge, so for this
|
||
measurement they do not exist.
|
||
# HOW THROUGH-CUT IS TOLD FROM PARTIAL IS AN INFERENCE, and it is
|
||
# labelled one everywhere it is used. Depth is not a field on these
|
||
# parts; it is in the type's description text (`3" SOLID ZONE`,
|
||
# `4" SOLID ZONE`) beside an insulation type named for its own
|
||
# thickness. Equal depths read as through-cut. A zone whose depth
|
||
# cannot be parsed is NOT guessed at either way -- the pins near it go
|
||
# unjudged and the finding says so.
|
||
depth_is_inferred_from_names: true
|
||
depth_inference_caveat: >-
|
||
Reading a depth out of a description string is a reading, not a
|
||
measurement. It is marked inferred in every finding built on it, and
|
||
a solid zone whose description states no depth stands the pins around
|
||
it down rather than defaulting to either answer.
|
||
|
||
# sources: 2026-08-31
|
||
# -> rationale.md § checklist
|
||
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'
|
||
|
||
# Re-graded A -> B 2026-08-30. Mechanical, but it needs the plant's
|
||
# design-token pattern to recognise a design label inside a view name,
|
||
# and its verdict is never worth failing a ticket over -- a stale name
|
||
# on a correct note is a trap for a reader, not a defect in the piece.
|
||
- 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'
|
||
|
||
# Built 2026-08-30 (CALLOUT-OVERLAP, ticketpage.callout_overlap_status /
|
||
# ticketchecks.check_callout_overlap). Text-bearing annotations on one
|
||
# placed view whose printed boxes intersect with positive area. Grade C
|
||
# and not B: a bounding box carries the text's leading and side
|
||
# bearings, so it is a little larger than the ink -- an intersection is
|
||
# a place for a person to look, never a defect claim. Text-vs-linework
|
||
# is deliberately out of scope (a call-out over a drawn edge is the
|
||
# normal condition on every elevation). Rotated annotations report an
|
||
# axis-aligned box that overstates the ink, so a pair with a rotated
|
||
# member is set aside under CALLOUT-OVERLAP-UNREAD, never flagged.
|
||
- 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
|
||
|
||
# Printed / reconstructed / measured, and the finding names which of
|
||
# the three is the odd one out. When only two of them can be read the
|
||
# check says so (WGT-TWO-WAY, never OK) rather than passing a two-way
|
||
# off as a three-way; with fewer than two it does not run at all.
|
||
- 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
|
||
|
||
# Built 2026-08-30 (CAST-EXTRA, ticketpage.cast_extra_agreement /
|
||
# ticketchecks.check_cast_extras). It is a SET comparison, not a weight
|
||
# one: the extras the ticket names against the extras whose volume fed
|
||
# 2.2's reconstructed weight (liftexport.extra_cast_members, the same
|
||
# members extra_cast_ft3 sums). That is the question 2.2 cannot ask --
|
||
# three weights can agree while all three are wrong the same way, and a
|
||
# ledge missing from both model and drawing agrees with itself.
|
||
# The ticket side is TEXT (a BOM row or a view's words naming a
|
||
# families.cast_include token), never the drawn geometry: no query
|
||
# answers "does this elevation show a ledge". An unreadable or
|
||
# un-gathered BOM stands the comparison down -- a row naming the extra
|
||
# may have been missed -- while an absent BOM is judged from view text
|
||
# and says so.
|
||
- 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'
|
||
|
||
# Built 2026-08-30 (STRAND-CALLOUT, ticketpage.debond_callout_status /
|
||
# ticketchecks.check_debond_callout). Owner's ruling: where the debond
|
||
# condition is met, expect a call-out; where there is none, WARN.
|
||
# It CONSUMES 4.7 rather than re-deriving the geometry -- 4.7 owns where
|
||
# debonding is required, 4.5 owns whether the ticket says so. When 4.7
|
||
# could not judge, 4.5 reports NOT RUN with 4.7's own reason instead of
|
||
# warning about a requirement nobody established.
|
||
# Grade C stands: the call-out found on these tickets is a bare note
|
||
# with no station and no strand number, so a present call-out shortlists
|
||
# rather than proves, and the finding says exactly that.
|
||
- 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'
|
||
|
||
# ---- THE BOM'S OWN STRAND ROW, added 2026-08-31 ----------------------
|
||
#
|
||
# A CHECK THAT RAN AND COULD REACH NO ROW. `check_bom_strand_count` has
|
||
# been registered and running since before the master checklist moved into
|
||
# this file; nothing named it, so its BOM-STRAND finding -- which can be a
|
||
# FAIL -- landed in `qc-run.json` under a code no row owned and no row
|
||
# ever turned red. It was recorded as a known exemption
|
||
# (`ROWLESS_CHECKS`) rather than fixed, because giving a check a row is a
|
||
# decision about what the report claims and that is the owner's. He made
|
||
# it: "看看能跑的,能做的,现在都做了去".
|
||
#
|
||
# WHY ITS OWN ROW AND NOT A SECOND CHECK ON 4.1. 4.1 asks the printed
|
||
# section call-out against the model (STR-QTY, emitted by
|
||
# `ticketqc.check_ticket`). This asks the BOM's LINEAR-FEET row -- a
|
||
# length, divided by the piece length -- against the same model, and
|
||
# optionally against the section print as a third leg. Different input,
|
||
# different failure, different repair: a wrong BOM row is fixed in the
|
||
# schedule and a wrong section call-out is fixed on the drawing.
|
||
#
|
||
# AND THE MULTI-CHECK IDIOM WOULD HAVE COST NOT RUNS, WHICH IS THE
|
||
# OPPOSITE OF THE ORDER. A row is answered only when EVERY check it names
|
||
# has spoken, so hanging this off 4.1 would make 4.1 NOT RUN on every
|
||
# ticket whose BOM could not be read -- turning a row that had a verdict
|
||
# into a red one, over a silence about a different question. 5.1 pairs two
|
||
# checks because they are two halves of ONE question and half an answer is
|
||
# not an answer; these are two independent answers, and either alone is a
|
||
# real verdict.
|
||
#
|
||
# GRADE A: the comparison is arithmetic and its one constant is measured
|
||
# (`strand_count_from_linear_ft`'s 0.05 ratio tolerance, from 12 real
|
||
# tickets whose remainders span 0.0032-0.0226). The third leg needs
|
||
# `legend.section_strand_view` and is optional -- without it the row is
|
||
# still fully answered two ways.
|
||
- 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'
|
||
|
||
# 5.1 IS TWO QUESTIONS AND ONLY ONE OF THEM WAS EVER ASKED.
|
||
# `check_bom_members` compares the BOM's named rows against the
|
||
# assembly -- a real comparison, and not the one this row is written
|
||
# as (docs/checklist-code-map.md, disagreement #2). The other half is
|
||
# the plan's own call-outs, and the part of THAT which needs the
|
||
# detail sheets is not built: `check_detail_callouts` reads
|
||
# nomenclature.detail_sheet_prefix, finds the bubbles the plan cites,
|
||
# and reports NOT RUN naming the sheets nobody reads. It passes only
|
||
# when the plan cites no detail at all, which is a real verdict.
|
||
# Two checks, so the row is answered only when BOTH spoke -- see
|
||
# checklist_states.
|
||
- 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'
|
||
|
||
# 5.3 before 5.4. They were the wrong way round until 2026-08-30 (the
|
||
# owner read a real WP133 run and spotted it); the table is read as a
|
||
# checklist, and a reader who cannot find 5.3 where 5.3 belongs starts
|
||
# doubting whether the row is there at all. `test_checklist_is_in
|
||
# _numerical_order` now holds every row to it.
|
||
# The reason slot is what makes this a FOR ENGINEER row rather than an
|
||
# unbuilt one -- see CHECKLIST_FOR_ENGINEER -- so it says plainly that
|
||
# nothing computes it. It used to read "code narrows, person decides",
|
||
# which promised a narrowing no code performs.
|
||
- 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'
|
||
|
||
# SPLIT 2026-08-30, on the owner's approval. 5.5 was one row asking two
|
||
# questions of different kinds. UNIQUENESS is a comparison between the
|
||
# model's marks and the sheet's printed text, and a comparison is code's
|
||
# job -- it moved to 5.6. LEGIBILITY is a property of the PICTURE, which
|
||
# no query answers, so it stays here at grade D and reads FOR ENGINEER.
|
||
# The vision path (`ticketvision.ESCALATIONS`, AI-BARMARK) is unchanged
|
||
# and still escalates this row; its question text now overlaps 5.6 on
|
||
# the uniqueness half, which is deliberate -- a model reading the
|
||
# rendered sheet is a second, independent look, never the computed
|
||
# answer, and section 8bis forbids it from claiming a verdict either way.
|
||
- 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
|
||
|
||
# The computed half of the old 5.5 (BARMARK-UNIQUE,
|
||
# ticketpage.bar_mark_uniqueness_status / ticketchecks.
|
||
# check_bar_mark_uniqueness). Three questions, three defects: one mark
|
||
# naming two parts, a printed mark no bar carries, a modelled bar never
|
||
# printed. Grade B -- mechanical, and the only local constant is the
|
||
# shape of a mark token, derived here rather than added as a plant fact.
|
||
- 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'
|
||
|
||
# Built 2026-08-30 (BAR-LENGTH, ticketpage.bar_stock_length_status /
|
||
# ticketchecks.check_bar_stock_length) on the owner's ruling that a bar
|
||
# is cut from 40 ft stock. The length is READ from the member.length
|
||
# role and never measured -- a bent bar consumes its developed length
|
||
# and a bounding box understates every one of them. Grade B: mechanical
|
||
# comparison against a published stock length, which is why the number
|
||
# lives in the catalogue and not in this file.
|
||
- 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'
|
||
|
||
# ---- CONNECTORS ON AN INSULATED PANEL, added 2026-08-31 ---------------
|
||
#
|
||
# Owner: "insulated panel 加一个 check,检查 connector 是不是存在,以及够不够"
|
||
# and, the same day, "再增加 connector edge distance 的 check".
|
||
#
|
||
# THE FIRST QUESTIONS EVER ADDED UNDER THE THREE-LAYER ARCHITECTURE, and
|
||
# the procedure is the point: a new QUESTION is three entries here (public,
|
||
# because what a connector is and why it matters is trade knowledge), three
|
||
# check functions in `vibe.ticketchecks` bound by these ids, and a line in
|
||
# the plant's own board saying where it sits in ITS numbering. Nothing
|
||
# about them is plant-specific except the part numbers, which live in the
|
||
# plant layer where part numbers belong.
|
||
#
|
||
# ALL THREE ARE INSULATED-ONLY, through `checks.only_applies_to` in the
|
||
# plant layer -- NOT through anything written here. On a solid panel there
|
||
# is no insulation for a connector to cross, so the question is not quiet,
|
||
# it is meaningless; and on a piece nothing could classify they read NOT
|
||
# RUN in red, because answering an insulated question about a piece that
|
||
# may not be one is exactly the silent pass this tool exists to refuse.
|
||
- id: '5.8'
|
||
name: 'Connectors present on an insulated panel'
|
||
grade: 'B'
|
||
owner_codes: ['CONNECTOR-EXIST']
|
||
not_run_reason: null
|
||
checks: 'check_connectors_exist'
|
||
|
||
# Grade B and not A: the count is mechanical, but WHAT THE DESIGN REQUIRES
|
||
# is a line of the design summary the parser cannot read yet -- WP115's
|
||
# 8.1 lists `HK ST100'S @1'-4" O.C.` among its uninterpreted lines. The
|
||
# model honours it exactly (measured 2026-08-31: five rows across at 16.0
|
||
# in field spacing, which IS 1'-4"), so the comparison has a calibrated
|
||
# example waiting for a parser that can state the requirement.
|
||
- 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'
|
||
|
||
# The 6.2 shape, one part along. The minimum is a property of the PRODUCT
|
||
# and lives in the public catalogue beside its capacity; it resolves
|
||
# product-first through the plant's alias, and a plant-wide fallback is
|
||
# second-class and named as such in the finding, because "6 inches" and
|
||
# "6 inches for this product" are different claims.
|
||
- id: '5.10'
|
||
name: 'Connector edge distances'
|
||
grade: 'B'
|
||
owner_codes: ['CONNECTOR-EDGE']
|
||
not_run_reason: null
|
||
checks: 'check_connector_edge_distance'
|
||
|
||
# ---- SOLID ZONES AND INSULATION RECESSES, added 2026-08-31 -----------
|
||
#
|
||
# Owner, twice, having asked for it before: "没有 solid zone 相关的检查。
|
||
# lifter 自带 solid zone,没检查这些 solid zone 是不是被加入了 assembly,
|
||
# 是不是被显示在 ticket 上面,hatch pattern 对不对。这些都没有啊" -- and
|
||
# then "不光是 solid zone,insulation recess 也得加上。你看看 page 2 里面
|
||
# 的那些 hatch pattern 就知道了。"
|
||
#
|
||
# WHAT A SOLID ZONE IS, in trade terms and therefore here: a block of
|
||
# concrete that replaces the insulation locally so a lifting insert has
|
||
# solid material to pull against. On this job every lifter NESTS one as a
|
||
# sub-component of its own family, and there are standalone ones at
|
||
# openings as well.
|
||
#
|
||
# WHAT A RECESS IS: a partial-depth pocket in the insulation. It is NOT a
|
||
# model element on this job -- the recesses are DRAFTED filled regions on
|
||
# the ticket, of types named for their depth -- so nothing about assembly
|
||
# membership applies to them and 5.14/5.15 ask a different pair of
|
||
# questions from 5.11/5.12 on purpose.
|
||
#
|
||
# ALL FIVE ARE INSULATED-ONLY, through `checks.only_applies_to` in the
|
||
# plant layer and NOT through anything written here: a solid panel has no
|
||
# insulation for a zone to interrupt or a recess to be cut in, so the
|
||
# question is meaningless rather than quiet. Same ruling as 5.8-5.10.
|
||
#
|
||
# WHY 5.11-5.13 ARE THREE ROWS AND NOT ONE. They are three different
|
||
# failures with three different repairs: a zone modelled but left out of
|
||
# the assembly (add it), a zone in the assembly but not reaching the
|
||
# layout view (a view or filter problem), and a zone that draws with the
|
||
# wrong hatch (a filter override). Collapsing them would tell a modeler
|
||
# something is wrong and not what to do.
|
||
- 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'
|
||
|
||
# SOLID-ZONE-ABSENT is a SECOND code on this row, not a second row, and
|
||
# it is the distinct finding "a lifter that nests NO solid zone at all".
|
||
# Measured 2026-08-31 it is zero across 192 lifters on 27 insulated
|
||
# pieces -- and the day it is not zero it is a bigger defect than any
|
||
# membership question, because there is no zone to add. Two codes, worst
|
||
# severity wins, so it cannot be hidden behind the membership verdict.
|
||
|
||
- 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'
|
||
|
||
# The reference for the hatch is THE LEGEND'S OWN SWATCH, resolved live
|
||
# from the sheet where it can be, with the plant's expected-pattern map
|
||
# named as a fallback when it cannot. The legend is the sheet's own
|
||
# statement of what each hatch means and it is the only reference that
|
||
# updates itself when the plant changes one; a table in a YAML file is a
|
||
# copy of it, and a copy is what goes stale.
|
||
- 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'
|
||
|
||
# GRADE C AND SCOPED HONESTLY. There is no model counterpart to compare a
|
||
# drafted region against, and the design side -- which recesses this
|
||
# piece is supposed to have -- is not parsed by anything today. So this
|
||
# row's first life is presence-and-inventory, and where it cannot compare
|
||
# it says what it lacks instead of comparing something else. A row that
|
||
# counts regions and calls it agreement would be the silent pass this
|
||
# table exists to refuse.
|
||
- 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'
|
||
|
||
# THE SIZE DISCREPANCY IS NOT THIS ROW'S QUESTION and the finding says so:
|
||
# the legend's text says 1" and 2" while the region type names say 2in and
|
||
# 3in. That is a real thing somebody should answer and the owner has been
|
||
# asked. This row compares PATTERNS, which is a question with an exact
|
||
# answer, and refuses to launder the size question through it.
|
||
- 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'
|
||
|
||
# Counts the MODELLED bars flagged as opening / blockout bars (a scheduled
|
||
# rebar family member carries a 'bar type blockout' yes/no) at the openings
|
||
# read off the piece -- the tickets carry no bar list. Short is a WARN a
|
||
# person resolves (small openings often cannot take the bars), never a FAIL.
|
||
|
||
- id: '5.16'
|
||
name: 'Door openings / blockouts: opening bar type flagged and #3 diagonals present'
|
||
grade: 'B'
|
||
owner_codes: ['OPENING-DIAG']
|
||
not_run_reason: null
|
||
checks: 'check_opening_diagonal_bars'
|
||
|
||
- 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'
|
||
|
||
# Re-graded A -> B 2026-08-30. What is deterministic is EMPTINESS -- a
|
||
# note view holding nothing but its own heading -- and that needs the
|
||
# plant's names for those views. Whether present content is the RIGHT
|
||
# instruction is not decided here and is not claimed to be.
|
||
- id: '6.5'
|
||
name: 'DUNNAGE / ERECTION / PICKING notes say something'
|
||
grade: 'B'
|
||
owner_codes: ['NOTE-CONTENT']
|
||
not_run_reason: null
|
||
checks: 'check_note_views'
|
||
|
||
# Built 2026-08-31 on the owner's ruling (PARITY-NOTE,
|
||
# ticketpage.parity_note_status / ticketchecks.check_parity_note): when
|
||
# the count of one part on a piece is ODD, the BED PLAN must carry a
|
||
# particular phrase. In section 6 because the trigger is a lifting
|
||
# insert's count and the consequence is an erection instruction; the
|
||
# BED PLAN is only where the instruction is printed.
|
||
#
|
||
# Grade B, not A, and the reason is not modesty. The count rests on a
|
||
# family name the PLANT declares and the phrase match proves only that
|
||
# the words are on the plan, not that they are about this part -- the
|
||
# same wording covers a temporary erection-only element on a `*.A`
|
||
# packet. Mechanical rule, plant-local constants: B.
|
||
- 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'
|
||
|
||
# ---- MINIMUM ANCHOR SPACING, added 2026-08-31 -------------------------
|
||
#
|
||
# ALP catalog p53, 02/2024, footnote under the capacity table: "Minimum
|
||
# anchor spacing is 2x the published edge distance". The owner supplied
|
||
# that page; its edge-distance column became 6.2 and its capacities became
|
||
# `catalogue.inserts`, and this sentence on the same page was read past.
|
||
# Until today nothing in the tool asked how far apart two anchors must
|
||
# sit, so two 8T anchors 20 in apart passed every row on the board while
|
||
# the page asked for 28.
|
||
#
|
||
# Grade A, like 6.2, and for the same reason: the measurement is
|
||
# mechanical and the minimum is PUBLISHED PRODUCT DATA in this file,
|
||
# reached through the plant's alias. Nothing about the rule is a plant
|
||
# habit. What is per-plant is only which parts are on the piece.
|
||
#
|
||
# The minimum is usually DERIVED rather than printed -- 2x the part's own
|
||
# published edge distance -- and the finding prints that arithmetic,
|
||
# because "28 inches" and "twice this part's published 14 inches" are
|
||
# different claims and only the second can be checked. A part whose sheet
|
||
# states a spacing outright overrides the multiple
|
||
# (`min_spacing_rule.published_in`), and a part with no published edge
|
||
# distance to double is NOT judged and is named: there is no plant-wide
|
||
# fallback here, because a general "anchors go two feet apart" is not
|
||
# something any layer states and inventing one is how a safety minimum
|
||
# gets borrowed from a product it does not belong to.
|
||
- id: '6.7'
|
||
name: 'Minimum spacing between lifting anchors'
|
||
grade: 'A'
|
||
owner_codes: ['LIFT-SPACING']
|
||
not_run_reason: null
|
||
checks: 'check_lifter_anchor_spacing'
|
||
|
||
# ---- PICKING STATIONS, added 2026-08-31 ------------------------------
|
||
#
|
||
# THE SECOND CHECK THAT RAN AND REACHED NO ROW. `check_picking_match`
|
||
# emits PICK-STATIONS / PICK-UNREADABLE and NOTHING ON THE CHECKLIST
|
||
# ASKED ABOUT PICKING STATIONS AT ALL -- so unlike 4.8 there was not even
|
||
# a neighbouring row that could have claimed it. Same ruling, same day.
|
||
#
|
||
# WHY IT IS NOT PART OF 6.5. 6.5 asks whether the PICKING note view says
|
||
# anything at all; this asks whether the stations printed in the picking
|
||
# DIAGRAM are where the picking inserts actually are. A note that says
|
||
# something and a diagram that is right are different claims, and folding
|
||
# them together would let a full note view carry a wrong station past the
|
||
# reader.
|
||
#
|
||
# SECTION 6 BECAUSE THE SUBJECT IS THE LIFTING INSERTS, and it sits after
|
||
# 6.7 rather than beside 6.3 for the reason the board's own note gives:
|
||
# nothing he already reads by number moves.
|
||
#
|
||
# GRADE B AND WARN BY RULING. The arithmetic is exact -- the diagram
|
||
# prints segments from EACH END and `stations_from_ends` resolves them --
|
||
# but which families are picking inserts is a plant fact
|
||
# (`handling.lifter_groups.face.families`), the tolerance is one
|
||
# (`handling.picking_tolerance_ft`), and reading the diagram at all rests
|
||
# on a measured drafting habit: picking prints at the highest y of the
|
||
# size notes. Owner, 2026-08-27: a dunnage-style finding is never the
|
||
# tool's verdict, so a mismatch is WARN and an engineer judges.
|
||
- 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'
|
||
|
||
# ---- LIFTING-POINT COUNT vs LENGTH, added 2026-09-02 -------------------
|
||
#
|
||
# An MC plant rule, not a published catalogue number: owner, verbatim,
|
||
# "ticketqc在MC加一条check:lifting points: MC的规矩是,panel长度小于20ft
|
||
# 则2p lifting,大于20则是4p lifting。实际上25以内都可以2p。你按照20-25给
|
||
# warn,25以上给fail写。" Nominal rule: under 20 ft, 2-point; 20 ft and
|
||
# over, 4-point. The real ceiling is looser than the nominal rule --
|
||
# 2-point actually holds to 25 ft -- so the grey zone between the two is a
|
||
# WARN and only past 25 ft does 2-point FAIL. 4 or more points is always
|
||
# OK; this only flags too FEW points for the length, never too many.
|
||
#
|
||
# Grade A, like 6.2/6.7/6.4: the arithmetic is mechanical (count the
|
||
# modelled points, compare to the panel length) once the thresholds are
|
||
# known, and what is per-plant is only the two numbers themselves --
|
||
# `lifters.lifting_points.two_point_max_length_ft` / `.two_point_
|
||
# absolute_max_ft` -- landed in MC's own plant layer. A layer that has
|
||
# not set both -- any non-MC plant -- gets no judgement from this rule at
|
||
# all: the check stands down naming the missing keys rather than holding
|
||
# another plant's panels to MC's numbers.
|
||
- id: '6.9'
|
||
name: 'Lifting-point count vs panel length (plant rule)'
|
||
grade: 'A'
|
||
owner_codes: ['LIFT-POINTS', 'LIFT-POINTS-UNREAD']
|
||
not_run_reason: null
|
||
checks: 'check_lifting_points'
|
||
|
||
# ---- LIFTING-POINT POSITION vs PCI, added 2026-09-02 --------------------
|
||
#
|
||
# DISTINCT FROM 6.9, on the same day. 6.9 grades the COUNT of lifting
|
||
# points against panel length; this grades WHERE each already-counted
|
||
# point sits against PCI's recommended station. An MC plant rule again,
|
||
# not a published catalogue number: owner, verbatim, "follow PCI的意思是
|
||
# 检查一下lifter的位置,如果跟PCI相差大于6" 则报WARN。很多时候没办法完全
|
||
# follow PCI,但是这件事儿让用户判断可行不可行。"
|
||
#
|
||
# WARN-ONLY, NEVER FAIL -- by that same ruling. Real panels often cannot
|
||
# follow PCI's ideal two-point location exactly, and whether a given miss
|
||
# is acceptable is the engineer's judgement, not this tool's verdict --
|
||
# same posture as 6.8's picking-station mismatch.
|
||
#
|
||
# THE 0.207L TWO-POINT LOCATION IS A PCI PUBLIC CONSTANT (the equal-moment
|
||
# two-point pick, confirmed on the sample_job drawings and mirrored by
|
||
# `panellift.pci.OPTIMAL_TWO_LINE_FRACTION`), not plant knowledge -- only
|
||
# the 6" TOLERANCE (`lifters.lifting_points.pci_position_tolerance_in`) is
|
||
# MC's own number, landed beside the 6.9 thresholds. A plant that has not
|
||
# set it gets no judgement from this rule, exactly like 6.9's stand-down.
|
||
#
|
||
# FOUR-POINT (OR ANY COUNT OTHER THAN TWO) IS NOT YET CONFIGURED. PCI's
|
||
# recommended stations for a 4-point pick are real published numbers this
|
||
# tool has not yet been given, so any count other than two stands the row
|
||
# down naming the count rather than guessing a 4-point rule.
|
||
#
|
||
# Grade A: the arithmetic is mechanical (compare a modelled station to
|
||
# 0.207L/0.793L) once the tolerance is known, and reuses 6.9's own point
|
||
# clustering rather than re-deriving it.
|
||
- id: '6.10'
|
||
name: 'Lifting-point position vs PCI recommendation (plant rule)'
|
||
grade: 'A'
|
||
owner_codes: ['LIFT-POS', 'LIFT-POS-UNREAD']
|
||
not_run_reason: null
|
||
checks: 'check_lift_positions'
|
||
|
||
# ---- DUNNAGE-POINT COUNT vs STRIPPING-POINT COUNT, added 2026-09-02 -----
|
||
#
|
||
# A THIRD MC plant rule, not a published catalogue number: owner,
|
||
# verbatim, "默认MC panels dunnage point=stripping points。4p stripping
|
||
# 则4p dunnage。" -- by default an MC panel's dunnage-point count equals
|
||
# its stripping-point count. And: "stripping point就是face lifters位置"
|
||
# / "LPA开头的就是face lifter" -- a stripping point is a face
|
||
# (back-stripping) lifter position, and the LPA-prefixed anchors are the
|
||
# face lifters.
|
||
#
|
||
# A DEFAULT, NOT AN ABSOLUTE RULE -- a mismatch is a deviation from it and
|
||
# the owner judges feasibility, exactly like 6.9/6.10: WARN, never FAIL.
|
||
#
|
||
# Grade A, like 6.9/6.10: the arithmetic is mechanical (count the two
|
||
# kinds of point, compare) once the plant fact -- which lifters are the
|
||
# face/stripping ones -- is known. That fact is read structurally, off
|
||
# `lifters.capacity_lb.<family>.usage: back_stripping` (the same tree and
|
||
# resolver `lifter_capacity()` uses, so this row can never disagree with
|
||
# 6.1 about which entry a family resolves to), with the bare `LPA`
|
||
# family-name prefix as a fallback for a family with no usage tag at all.
|
||
# `lifters.lifting_points.dunnage_matches_stripping` gates the rule -- a
|
||
# layer that has not set it gets no judgement from this row at all,
|
||
# exactly like 6.9/6.10's own stand-down.
|
||
- id: '6.11'
|
||
name: 'Dunnage-point count vs stripping-point count (plant rule)'
|
||
grade: 'A'
|
||
owner_codes: ['DUN-STRIP', 'DUN-STRIP-UNREAD']
|
||
not_run_reason: null
|
||
checks: 'check_dunnage_stripping_match'
|
||
|
||
# ---- LIFTER ACCESSORY (CUP/PATCH) ASSEMBLY MEMBERSHIP, added 2026-09-08,
|
||
# REVIT issue #26 ---------------------------------------------------------
|
||
#
|
||
# 6.12 IS DELIBERATELY SKIPPED -- see the `FLEXURAL_CHECKS_ALREADY_ASKED`
|
||
# comment in `ticketchecks.py`: a "6.12" built to an earlier draft of the
|
||
# flexural table would have duplicated 6.10, so this row is numbered 6.13
|
||
# rather than reuse a number that already almost meant something else.
|
||
#
|
||
# A lifter can nest a small accessory family that is not itself a
|
||
# recognised lifter -- a cup / void former that forms the crane-hook hole
|
||
# (QL121 under LIFT_QL589G_8T, QL062 under LIFT_QL548G_4T) or a patch
|
||
# (DB_PATCH, nested under either LPA pin-anchor family, `parent` given as
|
||
# a list) -- and none of it is reachable through the SAME family-name
|
||
# recognition 6.1's lifter capacity uses, because these are not lifters
|
||
# themselves. `lifters.accessories` in the plant layer names which
|
||
# families count and what role each plays; a nested child matching one of
|
||
# those families that never joined the piece's assembly is invisible on
|
||
# the ticket the same way a stray solid zone is (5.11's own reasoning,
|
||
# one part class over) -- the layout view is assembly-scoped and cannot
|
||
# show what the assembly does not contain.
|
||
#
|
||
# GRADE A: the gather is mechanical (`GetSubComponentIds()` on every
|
||
# recognised lifter, generalising 5.11's own reader rather than adding a
|
||
# second one) and the comparison is a plain membership test once
|
||
# `lifters.accessories` says which families to look for. What is
|
||
# per-plant is only that table -- which families are accessories at all
|
||
# and what each one is called.
|
||
#
|
||
# A child NOT in `lifters.accessories` and also not a member is a
|
||
# separate WARN (`LIFT-ACCESSORY-UNCLASSIFIED`), never folded into the
|
||
# FAIL: this check has no basis to call an unrecognised nested part a
|
||
# defect, only to flag it for a person to look at.
|
||
#
|
||
# LIVE-VALIDATED 2026-09-08 on the open MC model: WPA648 (assembly
|
||
# 9141343) FAILs naming 8 DB_PATCH children nested in its LPA pin anchors
|
||
# (e.g. child 9521037 under anchor 9521036) that never joined the
|
||
# assembly; WPA655 (9141344) and SMD516 (6113164) are OK.
|
||
- id: '6.13'
|
||
name: 'Lifter accessory (cup/patch) is a member of the assembly'
|
||
grade: 'A'
|
||
owner_codes: ['LIFT-ACCESSORY-NOT-IN-ASSEMBLY', 'LIFT-ACCESSORY-UNCLASSIFIED']
|
||
not_run_reason: null
|
||
checks: 'check_lifter_accessory_in_assembly'
|
||
|
||
- 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'
|
||
|