# Knowledge keys deliberately exempted from tools/knowledge_drift.py. # # FORMAT -- one per line: # # -- why this one is fine # # categories: unread undeclared defaults surface-only test-only # # THE REASON IS MANDATORY. A line with no ' -- why' is refused and the run # exits 2, because an unexplained suppression is how a checker quietly stops # checking. The point of an exception is that the next person can read why it # was made and decide whether it still holds; a bare path cannot be argued # with, only inherited. # # WHY A FILE AND NOT A YAML COMMENT. Two of the five categories are about keys # that exist only in Python (a hidden default) or only in a gitignored plant # or job file that a colleague's clone does not have. A comment convention # could not express those, so half the exceptions would have nowhere to live # and would end up as a second, undocumented mechanism. One file, in the repo, # beside the tool that reads it, greppable, and reviewed like code. # # HOW IT STAYS HONEST. Every run prints how many findings this file suppressed, # so a shrinking report is never mistaken for a shrinking problem. Every run # also lists entries here that no longer match anything, so a key that was # fixed or deleted does not leave a permanent blindfold behind. # # DO NOT put a real drift here to make the report green. An exception says # "this key is not meant to be read"; it does not say "we know and have not # got to it yet". For the second, leave the finding and fix the code. # # Example of the shape (commented out -- this is not an active exemption): # # unread nomenclature.view_design_token_re -- derived from design_number_re # when left None, so nothing reads the key itself by design. # ---- active exemptions below this line ---- # =========================================================================== # GROUP 1 -- the key IS read, by a call shape this detector cannot resolve. # =========================================================================== # Every line below was verified by hand on 2026-08-30 by opening the reader # and reading it. None of them is a deferral: the code acts on the key today. # Two shapes recur, and the tool's own blind-spot report already names both: # a knowledge getter passed in as a FUNCTION ARGUMENT (so the call reads # get(...) / getter(...), not K.get(...)), and a subtree fetched whole and # then walked by dict access. Where the fix belongs in the detector rather # than in the code the line says so; the day it lands, the run will call # these lines stale and they should be deleted. # takeoffcore.settings(know, get) loops its own module-owned DEFAULTS table # and calls get(know, 'takeoff.' + key) once per entry. Both halves are # invisible: `get` is an argument -- injected so the module needs no Revit and # stays testable off a model -- and the path is concatenated. The takeoff acts # on all seven; they are what classifies a family as bar / part / shape / # not-ordered. See takeoffcore.DEFAULTS and takeoffcore.classify(). unread takeoff.bar_prefixes -- read by takeoffcore.settings() through an injected getter and a concatenated path; classifies bar families in takeoffcore.classify() unread takeoff.part_prefixes -- read by takeoffcore.settings() through an injected getter and a concatenated path; classifies part families in takeoffcore.classify() unread takeoff.shape_markers -- read by takeoffcore.settings() through an injected getter and a concatenated path; marks a bend-shape row in takeoffcore.classify() unread takeoff.not_ordered -- read by takeoffcore.settings() through an injected getter and a concatenated path; drops families the plant does not order unread takeoff.family_class -- read by takeoffcore.settings() through an injected getter and a concatenated path; a family named here beats every pattern unread takeoff.nested_in -- read by takeoffcore.settings() through an injected getter and a concatenated path; rolls a nested family up into its parent unread takeoff.order_attached_bars_separately -- read by takeoffcore.settings() through an injected getter and a concatenated path; decides whether an attached bar is ordered on its own line # jobreconscan._roles() resolves nine roles in one loop over a literal tuple # and calls K.param_names(know, role) with the loop variable. The tool sees # the call and reports it as a blind spot -- 'non-literal key into # param_names' -- but cannot bind the roles. Job Recon reads all four of # these off the model on every run. unread parameters.member.ticket_created -- resolved in jobreconscan._roles()'s role loop and read off every member by Job Recon; the loop variable hides it from the scan unread parameters.member.ticket_detailed -- resolved in jobreconscan._roles()'s role loop and read off every member by Job Recon; the loop variable hides it from the scan unread parameters.sheet.total_required -- resolved in jobreconscan._roles()'s role loop; Job Recon compares it against the pieces the model carries unread parameters.sheet.sheet_count -- resolved in jobreconscan._roles()'s role loop; Job Recon compares it against the sheets actually placed # ticketchecks._sheet_param_value(t, know, 'sheet.weight') -> ticketqc.rstr() # -> K.param_names(). The literal role is right there, but behind two # wrappers, and only _nomen / param_names / _s are unwrapped by the detector. # It is deliberately NOT in knowledge.PARAMETER_ROLES: the printed-weight # check stands down with its own sentence when the plant maps no name for it, # so Self Check must not nag a plant that never prints a weight. unread parameters.sheet.weight -- read by ticketchecks through _sheet_param_value() -> ticketqc.rstr() -> param_names; kept out of PARAMETER_ROLES on purpose, the weight check stands down and says so itself # ticketpage.muted_checks(know, getter=None) reads it through an injected # getter, the same shape as takeoffcore. Ticket QC calls it on every run and # filters checklist rows with the result, so this is behaviour, not display. surface-only checks.muted -- read by ticketpage.muted_checks() through an injected getter; Ticket QC mutes checklist rows on it every run # liftexport fetches handling.dunnage WHOLE at behaviour tier and # dunnage_supports() walks the dict by hand for mode and fraction -- together # they decide where the transportation supports go. The detector only skips a # surface-read path when a behaviour reader sits BELOW it; a covering # behaviour read of an ANCESTOR is not considered, which is the only reason # these two fire. Delete both lines when that is fixed in the tool. surface-only handling.dunnage.mode -- liftexport reads the whole handling.dunnage subtree at behaviour tier and dunnage_supports() walks it; the tool does not credit a covering behaviour read of an ancestor surface-only handling.dunnage.fraction -- liftexport reads the whole handling.dunnage subtree at behaviour tier and dunnage_supports() walks it; the tool does not credit a covering behaviour read of an ancestor # liftexport._fast_box picks the key by run mode and passes `not batch` as the # fallback: for handling.fast_lifter_box that expression IS True, and for # handling.fast_lifter_box_batch it IS False -- exactly what configdump # passes. The two call sites agree on the value and differ only in source # text, which is all this category can compare. defaults handling.fast_lifter_box -- liftexport._fast_box passes `not batch`, which for this key evaluates to True, the same fallback configdump prints; the two differ in source text only defaults handling.fast_lifter_box_batch -- liftexport._fast_box passes `not batch`, which for this key evaluates to False, the same fallback configdump prints; the two differ in source text only # The two call sites ask different questions and both answers are written # down. designspec.design_key MUST always return a key, so it falls back to a # built-in generic pattern. ticketchecks._view_design_token_re would have to # strip the leading anchor off that pattern and hunt for it UNANCHORED inside # a view name; guessing there is how a view called 'Elevation Top 2' becomes # a design. It returns None instead and checklist 1.4 reads NOT RUN, which # its docstring states outright. Not a disagreement about what unset means. defaults nomenclature.design_number_re -- deliberate: designspec.design_key falls back to a built-in pattern because it must always return a key, while ticketchecks._view_design_token_re refuses to guess an unanchored view token and lets checklist 1.4 read NOT RUN # =========================================================================== # GROUP 2 -- not knowledge keys at all: a design spec read as a layer # =========================================================================== # knowledge_drift._job_files() walks the job folder recursively and takes # every .yaml in it. A design spec -- designspec.spec_path writes them to # /specs/.yaml, first line `schema: 1` -- is a scraped record of # one design, not a knowledge layer, and merging one plants its whole shape # as declared paths: schema, source, confidence, unresolved, and the measured # values under them. Nothing reads them through knowledge.get because nothing # should; designspec loads a spec by path. # # THE FIX IS IN THE TOOL and it is one line: _job_files() must not descend # into specs/. These thirteen lines live only until it does, and the run will # name them stale the moment it lands. While they are here they are also a # small hazard worth knowing about: `source` and `schema` are generic enough # that a future real knowledge key of either name would be suppressed by them. unread schema -- design-spec field, not a knowledge key; _job_files() descends into /specs/ and reads a spec document as a layer unread source -- design-spec field (which model, sheet and view it was scraped from), not a knowledge key; _job_files() reads /specs/ as a layer unread confidence -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer unread unresolved -- design-spec field (what the scrape could not settle), not a knowledge key; _job_files() reads /specs/ as a layer unread design_number -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer unread piece_description -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer unread thickness_in -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer unread envelope -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer unread reinforcing -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer unread concrete.fc_psi -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer (the knowledge-layer concrete branch carries min_fci_ratio, which is read) unread concrete.fci_psi -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer unread concrete.unit_weight_pcf -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer unread concrete.weight_class -- design-spec field, not a knowledge key; _job_files() reads /specs/ as a layer # ---- declared inert on purpose ---- # A key that is deliberately not wired, ruled on rather than overlooked. Not # the same thing as muting a CHECKLIST ROW (that is `checks.muted`, a job # fact, deep-merged, and set from the Project Config window): this changes no # run on any job, is the same everywhere, and its audience is whoever reads # this report next. unread tolerances.psi -- MUTED, NOT DELETED. Owner's ruling on triage D1, 2026-08-30: neither wire nor delete. Nothing compares a psi against it (3.1 and 3.2 compare the ticket and the design summary exactly), so it decides nothing on any job today; it is kept declared and settable so that the day a tolerance is wanted the number and its name are already there. The engineer-facing half is configform's `inert` row, which shows it with this ruling instead of as a number box that decides nothing. # ---- the master checklist moved into the public layer, 2026-08-31 -------- unread checklist -- the master checklist is read by ticketpage.load_master, which opens knowledge/catalogue.yaml DIRECTLY at import and parses it; it never goes through knowledge.get on the merged tree, so this detector cannot see the reader. It is the most-read data in the tool -- CHECKLIST_ITEMS is derived from it -- and two tests in test_ticketchecks_host.py pair every entry against the check functions. # ---- connector knowledge, 2026-08-31 ------------------------------------ unread connectors.what_it_is -- the definition of a connector, in prose, for a person reading the catalogue. Deliberately not a predicate: what a connector IS belongs in the file that publishes the products, and what RECOGNISES one is connectors.marks, which is read. unread connectors.insulation_note -- the model's own description of these pins as NON-COMPOSITE, quoted and dated. Recorded because it states a design assumption with engineering weight; deliberately read by nothing, and it must not become a check without the owner's word. unread connectors.recognition_verified_on -- provenance for connectors.recognition_verified, which IS read. A date beside a flag is for the person deciding whether the flag still holds. unread connectors.recognition_verified_by -- as above: what was measured, so the flag can be argued with rather than inherited. # =========================================================================== # GROUP 3 -- LANDED FROM THE PDF LIBRARY, READER PENDING. 2026-08-31. # =========================================================================== # Stage 3c of knowledge/library/RUNBOOK.md, executed against library row D1 # (the plant standards manual, 929 pages) whose 25-fact audit had been # EXTRACTED AND NEVER LANDED. The owner's ruling that commissioned this pass # is quoted in that runbook and in knowledge/library/LEDGER.md. # # EVERY LINE BELOW IS A FACT IN A KNOWLEDGE LAYER THAT NO CODE READS YET, and # that is the intended state, not a deferral of a fix. Knowledge leads and # readers follow: the alternative is a drift gate that PUNISHES LANDING, and a # gate that punishes the right behaviour is a gate people route around -- # which is exactly how roughly 150 A-class records ended up in notes instead # of in YAML. With these lines the drift list becomes the to-do list: every # unread key is a reader somebody owes, named, dated, with its cite attached. # # ---- AND THIS FILE'S OWN HEADER SAYS THE OPPOSITE, IN AS MANY WORDS ------- # "An exception says 'this key is not meant to be read'; it does not say 'we # know and have not got to it yet'. For the second, leave the finding and fix # the code." THE COMMISSION AND THAT SENTENCE DISAGREE. The honest # resolution is either a new category (`reader-pending`, dated) or an # amendment to the header -- NOT a quiet re-use of `unread` that makes the # header a lie. Per RUNBOOK.md stage 3c, until the owner rules: `unread` is # used, every reason says "reader pending", and THE CONFLICT IS ON HIS LIST # (QNA/open-questions-2026-08-30.md). The header was NOT edited here -- that # is not this pass's call to make. # # Cites are PDF page / printed section, the convention the extraction notes # use. Both halves always: the PDF page is how the next agent finds it, the # printed section is how the owner does, and they do not match. Full # argument, page cites and confidence marks for every one of these: # QNA/knowledge-audit-plant-2026-08-30.md, and knowledge/library/LEDGER.md D1. # # Three of these are also PARKED CONTRADICTIONS -- a live value the manual # disagrees with, landed BESIDE it rather than over it, awaiting a ruling. # They are marked "RULING PENDING" and carry their open-questions number. unread beds -- landed 2026-08-31 from the plant standards manual (library D1) p584-600 / 6110-6126, reader pending: the per-bed strand-hole grid, panel width and abutment capacity. 4.6 BED-WIDTH/BED-OFFSET reads the rails.max_bed_width_in scalar today and the manual contradicts it (open-questions A6.1); 4.6 STRAND-GRID does not exist yet unread rails.narrow_panel -- landed 2026-08-31 from the plant standards manual p819 / 10315.1 and p804 / 10301.1 notes 27-29, reader pending: a narrow panel is HELD TO THE FIXED RAIL, so 4.6 BED-OFFSET's permitted band is an outer bound and not an expectation, and 4.4's asymmetric pattern is expected rather than a finding unread strand.standard_patterns -- landed 2026-08-31 from the plant standards manual p174-178 / 3201-3205 and p873 / 12204, reader pending: the plant's three standard strand chains, so 4.4 STRAND-POS gets a second opinion beside the design summary unread strand.edge_strand_in -- landed 2026-08-31 from the plant standards manual p876 / 12210, reader pending: EDGE STRAND @ 3 5/8 in, the first and last segment of every standard chain unread strand.both_wythes_same_stations -- landed 2026-08-31 from the plant standards manual p174-178 / 3201-3205, reader pending: STRAND E.L. means both wythes share x-positions, so total strand is 2x the per-wythe count unread strand.debond_by_blockout -- landed 2026-08-31 from the plant standards manual p817 / 10306.1, reader pending: 4.7 has the opening geometry and strand.debond_below_continuous_ft, but the L-vs-W ratio rows have no counterpart in the tool at all unread strand.deflection -- landed 2026-08-31 from the plant standards manual p804 / 10301.1 note 20C and p817 / 10306.1, reader pending: deflection is the alternative to debonding and is ranked LAST, max 2 in, min cover 1 1/2 in unread strand.detensioning -- landed 2026-08-31 from the plant standards manual p628 / 6320, reader pending: nothing in the tool reads a cutting sequence. Landed because knowledge leads readers, audit 3.25 unread reinforce.panel_standard -- landed 2026-08-31 from the plant standards manual p183-191 / 3280-3288, reader pending: ReinforceSuggest works only from donor pieces today, and this is its first non-donor source. The middle band is PER DESIGN and must never be proposed unread reinforce.design_sheet_selector -- landed 2026-08-31 from the plant standards manual p183-191 / 3280-3288, reader pending: which of the nine standard reinforcing sheets applies, from panel geometry alone unread reinforce.weight_plf -- landed 2026-08-31 from the plant standards manual p183-191 / 3280-3288, reader pending: a per-linear-foot sanity band for Takeoff and for bar-schedule plausibility unread reinforce.master_ticket -- landed 2026-08-31 from the plant standards manual p716 / 8430.1, reader pending: it defines what reinforce.master_token marks. The durations and the submission list are process with no check behind them unread lifters.stripping_rows_by_height_ft -- landed 2026-08-31 from the plant standards manual p183 / 3280, reader pending: panellift.layout decides where inserts go and does not know the plant's own row count by panel height unread lifters.stripping_rows_gap_at_ft -- landed 2026-08-31 from the plant standards manual p183 / 3280, reader pending: the sheet's own bands leave H = 39 ft exactly unassigned; a reader must pick a side and say which unread lifters.stripping_rows_gap_because -- landed 2026-08-31 from the plant standards manual p183 / 3280, reader pending: the sentence a reader must print when it resolves the 39 ft boundary itself unread lifters.default_layout -- landed 2026-08-31 from the plant standards manual p713 / 8320.2, reader pending: fifth points is a DEFAULT and the sheet says to verify the insert type with the engineer unread lifters.insert_type_verified_with_engineer -- landed 2026-08-31 from the plant standards manual p713 / 8320.2, reader pending: the half of that sentence that stops the default being read as governing unread lifters.common_elevation_panel_to_panel -- landed 2026-08-31 from the plant standards manual p804 / 10301.1 note 14, reader pending: lifting inserts at a common elevation panel to panel unread lifters.dimension_centre_to_centre_and_both_edges -- landed 2026-08-31 from the plant standards manual p812 / 10303.1, reader pending: a dimensioning rule for lift inserts, checkable once something reads printed insert dimensions unread lifters.edge_lifter_centre_matches_cg -- landed 2026-08-31 from the plant standards manual p812 / 10303.1, reader pending: 6.2 LIFT-EDGE has the geometry but not this condition unread lifters.side_lifters -- landed 2026-08-31 from the plant standards manual p813 / 10303.2 and p804 / 10301.1 note 10, reader pending: an ADD'L FINISH = YES title block with no side lifters is a new check needing only two title-block reads unread lifters.top_pick_count -- landed 2026-08-31 from the plant standards manual p183 / 3280, reader pending: 4 top-pick inserts. The PART is deliberately not landed -- the sheet names M42/M43 and the model uses P76 (audit Q5) unread part_numbers.prefix_class -- landed 2026-08-31 from the plant standards manual p406 / 5001, reader pending: the material-type prefix, which gives families.* a fallback that cannot go stale the way a list does unread part_numbers.number_bands -- landed 2026-08-31 from the plant standards manual p406 / 5001 and p713 / 8320.2, reader pending: the number range tells a standard part from an erection item from a repair item with no list at all unread part_numbers.finish_suffix -- landed 2026-08-31 from the plant standards manual p406 / 5001, reader pending: g/p/z/s/e finish suffixes on a material designation unread part_numbers.job_specific_prefixes -- landed 2026-08-31 from the plant standards manual p406 / 5001, reader pending: the printed rule behind the SP-series move to the job layer on 2026-08-30, which this file acted on without holding the rule unread part_numbers.rebar_mark -- landed 2026-08-31 from the plant standards manual p536 / 5302, reader pending: 5.6 BARMARK-UNIQUE could catch a mark whose first digit disagrees with the modelled bar size with no geometry at all unread panel_types.make_ups -- landed 2026-08-31 from the plant standards manual p174-178 / 3201-3205 and p879 / 12221, reader pending: 2.1 SIZE-* reads panel_type.thickness and has no list of the five thicknesses this plant builds unread girders -- landed 2026-08-31 from the plant standards manual p805 / 10301.2 note 3 and p879 / 12221, reader pending: girder depth, the insulation-plus-3in size rule and the opening-proximity rules. The COUNT is deliberately null -- three sources give three answers (audit Q3) unread nomenclature.control_numbers -- landed 2026-08-31 from the plant standards manual p693-695 / 8102.3-8102.5, reader pending: JobRecon does the 163-vs-61 reconciliation and does not hold the arithmetic rule that makes it a defect unread nomenclature.marks -- landed 2026-08-31 from the plant standards manual p693-695 / 8102.3-8102.5, reader pending: a gap in the mark sequence is EXPECTED, and the renumber trigger reframes 2.1 SIZE-* and 2.2 WGT-* as a piece that should have been renumbered unread nomenclature.ticket_set -- landed 2026-08-31 from the plant standards manual p827 / 10340.2 and p807 / 10301.4, reader pending: 1.3 TICKET-SET gathers sheets today but does not know that sheets after the first carry no product data, nor that third-party sheets are legitimately appended unread nomenclature.sheet_families_manual_stated -- landed 2026-08-31 from the plant standards manual p819 / 10315.1, p822 / 10330.1, p821 / 10320, p716 / 8430.1, p851 / 10950, reader pending AND RULING PENDING: nomenclature.detail_sheet_prefix is live and unchanged; this is the manual's fuller set, parked beside it as open-questions A6.2 unread drawings.rebar_placement_manual_stated -- landed 2026-08-31 from the plant standards manual p804 / 10301.1 notes 25, 26, 40, 47 and p805 / 10301.2 note 15C, reader pending AND RULING PENDING: drawings.rebar_must_appear_on is a residual and unchanged; this is the manual's per-bar-class enumeration, parked beside it as open-questions A6.5 unread drawings.dimension_exceptions -- landed 2026-08-31 from the plant standards manual p804 / 10301.1 notes 6, 33, 46, 48, p816 / 10305, p726 / 8520.1, reader pending: every entry is a place where a MISSING dimension is correct by standard, and a completeness check that does not know them produces a steady drip of false findings unread drawings.bom_rebar_has_no_description -- landed 2026-08-31 from the plant standards manual p713 / 8320.2, reader pending: an empty BOM description on a rebar row is CORRECT, and without this 5.1 BOM-MEMBERS would fire on every rebar row of every ticket unread drawings.not_printed_on_ticket -- landed 2026-08-31 from the plant standards manual p701 / 8203, reader pending: the manual's own statement of what is deliberately absent from a ticket -- the panel ID and the behind-panel sections unread drawings.alternate_datum -- landed 2026-08-31 from the plant standards manual p811 / 10302.2 and p814 / 10304, reader pending: on an angled-top panel embeds are dimensioned to a WORK POINT, a legitimate alternative datum that will confuse a naive datum check unread drawings.dimensions -- landed 2026-08-31 from the plant standards manual p804 / 10301.1 note 5, p810 / 10302.1, p814 / 10304, reader pending: centre-of-embed is this plant's universal datum and is a precondition for any check comparing a printed dimension to a modelled position unread drawings.orientation_on_sheet -- landed 2026-08-31 from the plant standards manual p804 / 10301.1 notes 2, 3, 12, 13 and p819 / 10315.1, reader pending: drawings.section_a and section_b were measured off crop boxes on three pieces; this is the convention that binding should agree with unread drawings.attached_bar_rule -- landed 2026-08-31 from the plant standards manual p413-418 / 5100.1-5100.6 and p701 / 8203, reader pending: the rule behind drawings.annotation_covered_by_parent, which is a two-entry list today and goes stale in silence the way drawings.reinforcing_rule's predecessor did unread drawings.cad_layers -- landed 2026-08-31 from the plant standards manual p701 / 8203, reader pending: the layer a thing is drawn on IS its classification, and REBAR-HEAVY / REBAR-MED / REBAR-LIGHT is a reinforcing size split unread handling.weight_band_lb -- landed 2026-08-31 from the plant standards manual p800 / 10230.1, reader pending AND RULING PENDING: knowledge.DEFAULTS' weight_tolerance 0.02 is unchanged and 2.2 WGT-* still runs on it; this is the manual's -0/+100 lb band, parked beside it as open-questions A6.4 unread geometry -- landed 2026-08-31 from the plant standards manual p168-170 / 3040-3042, p814 / 10304, p712 / 8320.1, p278 / 4294.0, p784 / 10150, reader pending: the recessed-plate rule ties a geometric property to a required X-sheet callout, which is checkable against DETAIL-CALLOUT unread finishes -- landed 2026-08-31 from the plant standards manual p165-166 / 3010, 3011, reader pending: a closed vocabulary with two checkable obligations -- a raked panel needs a direction on the ticket, and an end finish is checkable against the product type unread concrete.wall_panel_default -- landed 2026-08-31 from the plant standards manual p183-191 / 3280-3288, reader pending: f'ci 3500 gives 3.1/3.2/3.3 a plausibility anchor. f'c is null on purpose -- printed 5000, hand-revised 6000 in red, and neither state is settled (audit Q2) unread concrete.release_range_psi -- landed 2026-08-31 from the plant standards manual p627 / 6200, reader pending: the release-strength range this plant offers unread concrete.release_standard_psi -- landed 2026-08-31 from the plant standards manual p627 / 6200, reader pending: 3500 psi is the standard release, the rest is specialty unread concrete.day28_range_psi -- landed 2026-08-31 from the plant standards manual p627 / 6200, reader pending: 5000-7000 psi at 28 days available or more unread concrete.mix_role -- landed 2026-08-31 from the plant standards manual p800 / 10230.1, reader pending: FACE = BOTTOM wythe and BASE = TOP, because the panel is cast face-down. A reader that takes FACE MIX for the exterior mix is right by accident; one that takes it for the top wythe is wrong unread concrete.single_wythe_uses -- landed 2026-08-31 from the plant standards manual p800 / 10230.1, reader pending: a single-layer piece uses the BASE mix number, not the face one unread concrete.named_mixes -- landed 2026-08-31 from the plant standards manual p164 / 3003, reader pending: the plant's named mixes quoted directly. The positional digit decoding an extraction inferred is filed C there and deliberately not landed unread material_grades -- landed 2026-08-31 from the plant standards manual p863 / 11301.1 and p412 / 5015, reader pending: a plant CHOICE among published ASTM options, confidence B because it is read off a filled example form. HSS is null -- A513 struck to A500-C in red, neither state settled unread openings -- landed 2026-08-31 from the plant standards manual p760 / 9301 and p887 / 12261, reader pending: a void below 100 sq in or 8 in is one the plant does not cast, which filters the population 6.4 DUN-OPENING, 4.7 and liftexport._openings all count unread revisions -- landed 2026-08-31 from the plant standards manual p723 / 8511, reader pending: a ticket at revision 3 whose two predecessors are missing is NORMAL, because the sequence advances project-wide. The old-cloud layer name is null -- two spellings in one manual (audit Q10) unread connections -- landed 2026-08-31 from the plant standards manual p216-220 / 4201-4205, p231 / 4214, p243 / 4232, p375-403 / 4900-4974, reader pending: base-connection count by seismic category and butt-joint count by panel height are countable findings for 5.1 BOM-MEMBERS. The alignment count is null -- its table is red-marked (audit Q2) # FOUR FACTS THIS PASS LANDED HAVE NO LINE HERE, AND THE REASON IS A BLIND # SPOT RATHER THAN A READER: notes.handling_views_on_sheet, # notes.handling_view_order, face_designations.carried_by_hatch and # face_designations.insulation_hatch all sit under a subtree that some caller # fetches WHOLE. The detector credits a covering read of an ancestor, so it # never reports them and an allowlist line for them is refused as stale. They # are as unread as everything below -- nothing acts on any of the four -- and # they are recorded in knowledge/library/LEDGER.md D1 instead. If the covering # read is ever narrowed, four findings appear at once and they are these. # ---- two owner rulings landed the same day, 2026-08-31 ------------------- # Not from the library; from the owner directly, landed in the same pass # because it holds the plant file. See knowledge/library/LEDGER.md D1's row # for the pass and QNA/will-owes-2026-08-31.md for the open consequence. unread lifters.min_edge_distance_in_by_panel_type -- landed 2026-08-31 from the owner directly ("insulated panel minimum edge distance is 2ft, plant knowledge"), reader pending: knowledge.families_for() resolves a *_by_panel_type map for a LIST role only and there is no scalar resolver, so 6.2 still runs on the published-first order in ticketchecks._edge_limit(). The composition a reader must implement is LARGER-OF with the provenance named -- the plant's 24 in exceeds every published part minimum, so published-first would silently discard it unread panel_types.detect_verified_on -- provenance for panel_types.detect_verified, which IS read and was armed 2026-08-31. A date beside a flag is for the person deciding whether the flag still holds; same shape as connectors.recognition_verified_on above unread panel_types.detect_verified_by -- as above: what the arming rested on (three signals at 100% separation over 282 panels, a 1,951-mark connector census, and the owner's ruling), and the one thing it did NOT rest on -- a live press -- so the flag can be argued with rather than inherited # ---- the live-model guard, 2026-09-01 ------------------------------------ # Both ARE read, on every single bridge request, by # `vibe/bridgeguard.config_from()`. The detector cannot see it: that function # is deliberately given `knowledge.get` as an ARGUMENT rather than importing # it, so the module stays free of anything that reads a file and can be unit # tested off-Revit (tests/test_bridgeguard.py). The literal paths are there, # one line apart -- they just arrive through a parameter named `getter`. unread bridge.refuse_titles -- read every request via bridgeguard.config_from(know, knowledge.get); the path literal is passed to an injected getter, not to knowledge.get by name, which is the wrapper shape this detector says it does not follow unread bridge.allow_roots -- as above, same call, same line pair # =========================================================================== # GROUP 4 -- LANDED FROM THE PDF LIBRARY, READER PENDING. 2026-09-07. # =========================================================================== # Stage 3c of knowledge/library/RUNBOOK.md, run against library row P1 -- the # PCI Design Handbook, 9th ed. (MNL-120-25), read live in the owner's Chrome # via the Apryse WebViewer (licensed, viewed online, not downloaded). This is # the PUBLIC layer's own pass, unlike GROUP 3's plant-layer D1 pass: every # value below identifies no producer, no job and no client, so it landed in # knowledge/catalogue.yaml rather than a plant file. Same rule as GROUP 3 # applies: `unread` is used, every reason says "reader pending", and the # tension with this file's own header is the same one GROUP 3 already # raised and not re-argued here. # # Cites are PDF VIEWER page / printed page (footer), same convention as # GROUP 3. Full extraction, confidence marks and screen-verification notes: # knowledge/library/notes/PCI9-5.8-losses.md, PCI9-5.12-insulated.md, # PCI9-5.17-design-aids.md, PCI9-ch8-handling.md, PCI9-ch15-reference.md. # Ledger row: knowledge/library/LEDGER.md P1. # # The reason this is FIVE lines and not fifty: the detector reports the # HIGHEST unread ancestor, not every leaf -- same shape as the pre-existing # `catalogue.shear_grid` / `catalogue.slotted_inserts` findings, which this # pass did not touch and which are still unread themselves (see the plain # findings list, not this file). unread catalogue.prestress_losses -- landed 2026-09-07 from PCI Design Handbook 9th ed. Section 5.8 "Loss of Prestress", viewer p293-296 / printed 5-42 to 5-45, reader pending: this is what will/REVIT #24 needs -- the panellift/liftexport engine today assumes a lump-sum prestress-loss percentage, and the owner ruled the tool must compute losses per the PCI/Zia method instead of assuming one. The ES/CR/SH/RE equations and the Kre/J/C coefficient tables are landed; nothing calls them yet. unread catalogue.strand -- landed 2026-09-07 from PCI Design Handbook 9th ed. Section 15.2, Design Aids 15-9/15-10/15-11/15-12, viewer p862-863 / printed 15-31/15-32, reader pending: nominal diameter -> area/weight/fpu for ASTM A416 strand (incl. 1/2" SPECIAL at 0.167 in^2), A421 wire and A722 bars, plus the design stress-strain curve. No product-family module currently reads a strand area from this table; ticket QC's own strand count/spacing checks read the model's own strand matrix (strand-matrix-geometry-read), not a published property table. unread catalogue.camber_and_bowing -- landed 2026-09-07 from PCI Design Handbook 9th ed. Section 5.9 and Design Aids 5-1/5-2, viewer p293-300 / printed 5-45 to 5-49 and p448-449 / printed 5-197/5-198, reader pending: the PCI multiplier-method table (1.85/1.80/2.70/2.45/3.00/2.30), the three camber-vs-strand-pattern formulas, and the bowing-restraint-force design aid (including the 0.75*Ec short-term effective-modulus fact). Nothing in this tool currently computes camber or bowing. unread catalogue.insulated_panel -- landed 2026-09-07 from PCI Design Handbook 9th ed. Section 5.12, viewer p304-309 / printed 5-53 to 5-58, reader pending: insulation max-use-temperatures, the four composite/noncomposite/partially-composite/semicomposite structural design assumptions, and wythe/strand/connector-spacing limits (24 in o.c., 12-14 gauge). Distinct from `insulation.*` (a plant/job-layer namespace already read for the current job's recess/hatch geometry) -- this is the published PCI design-method layer, not this job's drafted geometry. unread catalogue.handling -- landed 2026-09-07 from PCI Design Handbook 9th ed. Chapter 8 "Component Handling and Erection Bracing", viewer p620-642 / printed 8-3 to 8-23, reader pending: Table 8.3.1's stripping/handling/transport load multipliers, the 4x/5x/2x lifting/hardware/bracing safety factors (OSHA 1926.704), Table 8.3.3's aircraft-cable/wire-rope safe loads, the strand-loop capacity defaults (10 kip base, 1.7x/2.2x for double/triple loops), and Figure 8.6.1's rotation-pick moment/reaction coefficients. NAMING NOTE for whoever picks this up: there is an UNRELATED, already-read top-level `handling.*` namespace (`handling.connectors.declared_action`, `handling.ignore_lateral_prestress` in liftexport.py) that is panellift's OWN per-job handling-analysis config -- a different dotted path (`catalogue.handling.*` vs `handling.*`) so no collision today, but close enough in name to confuse a reader; consider renaming one of the two before wiring a check to either. # =========================================================================== # GROUP 5 -- LANDED FROM THE PDF LIBRARY, READER PENDING. 2026-09-07. # =========================================================================== # Stage 3 of knowledge/library/RUNBOOK.md, run against ACI 318-19 Chapter 25 # "Reinforcement Details" (§25.4 Development of reinforcement, §25.5 # Splices), read from the code's own text layer, not a producer's manual -- # PUBLIC, same as GROUP 4: it identifies no producer, no job, no client. # Full extraction, confidence marks and the raw-text-fragment cross-checks: # knowledge/library/notes/ACI318-19-ch25-development.md. Ledger row: C1 in # knowledge/library/LEDGER.md. unread catalogue.development_length -- landed 2026-09-07 from ACI 318-19 Chapter 25 §25.4/§25.5, printed p.471-491, reader pending: development-length and lap-splice formulas, minimums and modification factors for deformed bars/wires in tension and compression, standard hooks, headed bars, pretensioned strand, welded wire reinforcement, and the excess-reinforcement reduction with its six exclusions. No product-family module currently checks a bar's or a strand's development length against a formula -- ticket QC reads dimension strings and bar counts off the model today, not an embedment length. The reader this is for: a future rebar/strand embedment check (would sit beside ticketchecks.py's existing bar checks) and the strand transfer-length assumption panellift/liftexport currently treats as a plant-layer default rather than computing from Eq. 25.4.8.1.