WillTools 2026-09-09 -- clean snapshot of the development repo for review
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.
This commit is contained in:
2026-09-09 08:32:15 -05:00
commit 8e6ee31596
406 changed files with 223435 additions and 0 deletions
@@ -0,0 +1,192 @@
# -*- coding: utf-8 -*-
"""Plant extraction rule packs.
The property every test here circles is the one the module rests on: a pack
may re-describe a note or move it to a field a person reads, and NOTHING it
can say makes a note disappear. Everything else -- which regex fires, what
sentence comes back -- is detail beside that.
The seven notes used throughout are the real ones, verbatim, from `WPA1.0`
(sample_job, 8" horizontal wall) read on 2026-09-01: the run that
prompted this module, where all seven landed in `unresolved` under one
blanket reason.
"""
import pytest
from vibe import extractrules
from vibe.extractrules import mc
# The seven, in sheet order. Whitespace-normalised the way
# `ticketqc.unresolved_in_view` normalises before anything sees them.
WPA1_NOTES = [
'*USE MC STANDARD REINFORCEMENT FOR CUT DOWN PANELS AND AROUND ALL OPENINGS',
'STRIPPING & BLOCKING DETAIL',
'USE FOR BACK OR EDGE PICK (UNO)',
'STRAND PATTERN',
'STRAND',
"#5 BAR X CONT ONLY NEEDED WHEN LAST PAIR OF STRANDS ARE MORE THAN 1'-0 "
'FROM EDGE OF WALL.',
"STRIPPING & BLOCKING DETAIL < 25'",
]
def entries(texts, reason='no extraction rule matched this note'):
return [{'text': t, 'reason': reason} for t in texts]
def know_with(packs):
"""A knowledge stand-in and a getter over it, so these tests never need
the real layered loader (which wants a Revit doc)."""
store = {'extract.rule_packs': packs}
return store, lambda know, key, default=None: know.get(key, default)
# --------------------------------------------------------------- the gate
def test_no_declaration_loads_no_pack_and_changes_nothing():
"""The honest default: told nothing about an office, recognise nothing."""
know, get = know_with([])
packs, problems = extractrules.load(know, get)
assert packs == []
assert problems == []
given = entries(WPA1_NOTES)
notes, unresolved = extractrules.apply_to(given, packs)
assert notes == []
assert unresolved == given
def test_declared_pack_loads():
know, get = know_with(['mc'])
packs, problems = extractrules.load(know, get)
assert problems == []
assert [p.NAME for p in packs] == ['mc']
def test_a_bare_string_is_accepted_as_one_name():
know, get = know_with('mc')
packs, problems = extractrules.load(know, get)
assert problems == []
assert [p.NAME for p in packs] == ['mc']
def test_unknown_pack_is_refused_loudly_and_nothing_loads():
"""All or nothing. A half-loaded rule set classifies some notes and not
others, and the reader cannot tell which sentences to trust."""
know, get = know_with(['mc', 'no-such-plant'])
packs, problems = extractrules.load(know, get)
assert packs == []
assert len(problems) == 1
assert 'no-such-plant' in problems[0]
assert 'mc' in problems[0] # says what IS available
def test_empty_and_duplicate_names_are_refused():
know, get = know_with(['mc', 'mc'])
_, problems = extractrules.load(know, get)
assert problems and 'twice' in problems[0]
know, get = know_with([''])
_, problems = extractrules.load(know, get)
assert problems and 'empty' in problems[0]
def test_knowledge_default_is_empty():
from vibe import knowledge
assert knowledge.DEFAULTS['extract']['rule_packs'] == []
# ------------------------------------------------- the load-bearing property
def test_no_note_is_ever_dropped():
"""The whole module in one assertion."""
know, get = know_with(['mc'])
packs, _ = extractrules.load(know, get)
given = entries(WPA1_NOTES)
notes, unresolved = extractrules.apply_to(given, packs)
assert len(notes) + len(unresolved) == len(given)
assert (sorted(n['text'] for n in notes + unresolved)
== sorted(WPA1_NOTES))
def test_every_placement_names_the_rule_that_made_it():
"""An unattributable classification is one nobody can argue with."""
know, get = know_with(['mc'])
packs, _ = extractrules.load(know, get)
notes, unresolved = extractrules.apply_to(entries(WPA1_NOTES), packs)
for entry in notes:
assert entry['rule'].startswith('mc/')
for entry in unresolved:
if 'rule' in entry:
assert entry['rule'].startswith('mc/')
def test_a_placement_must_declare_a_known_kind_and_a_rule():
with pytest.raises(ValueError):
extractrules.Placement('vanish', 'mc/x', 'because')
with pytest.raises(ValueError):
extractrules.Placement(extractrules.NOTE, '', 'because')
# ------------------------------------------------------- the mc pack itself
def test_the_seven_notes_land_where_they_should():
know, get = know_with(['mc'])
packs, _ = extractrules.load(know, get)
notes, unresolved = extractrules.apply_to(entries(WPA1_NOTES), packs)
assert sorted(n['text'] for n in notes) == sorted([
'*USE MC STANDARD REINFORCEMENT FOR CUT DOWN PANELS AND AROUND ALL '
'OPENINGS',
'USE FOR BACK OR EDGE PICK (UNO)',
"#5 BAR X CONT ONLY NEEDED WHEN LAST PAIR OF STRANDS ARE MORE THAN "
"1'-0 FROM EDGE OF WALL.",
"STRIPPING & BLOCKING DETAIL < 25'",
])
assert sorted(u['text'] for u in unresolved) == sorted([
'STRIPPING & BLOCKING DETAIL',
'STRAND PATTERN',
'STRAND',
])
def test_a_conditional_detail_title_is_a_note_and_the_bare_one_is_not():
"""The asymmetry this pack exists to get right: the condition is the part
that could change what gets built, so it is never called furniture."""
bare = mc.classify('STRIPPING & BLOCKING DETAIL')
cond = mc.classify("STRIPPING & BLOCKING DETAIL < 25'")
assert bare.kind == extractrules.FURNITURE
assert cond.kind == extractrules.NOTE
assert bare.rule != cond.rule
def test_furniture_keeps_its_place_in_unresolved():
"""`furniture` is not an ignore list -- the line is still written out,
only the sentence beside it changes."""
know, get = know_with(['mc'])
packs, _ = extractrules.load(know, get)
given = entries(['STRAND PATTERN'])
notes, unresolved = extractrules.apply_to(given, packs)
assert notes == []
assert len(unresolved) == 1
assert unresolved[0]['text'] == 'STRAND PATTERN'
assert unresolved[0]['reason'] != given[0]['reason'] # better sentence
assert 'legend' in unresolved[0]['reason']
def test_the_pack_recognises_nothing_it_was_not_shown():
"""A rule with no observation behind it does not belong in the pack, and
a sentence from another producer's sheet must fall straight through."""
for text in ('SEE ARCHITECTURAL DRAWINGS',
'ALL DIMENSIONS ARE NOMINAL',
'USE 6X6 -D3.0/D3.0 W.W.F.',
'',
'STRANDS'):
assert mc.classify(text) is None
def test_classify_is_case_and_padding_tolerant():
assert mc.classify(' strand pattern ') is not None
assert mc.classify('Strand Pattern').kind == extractrules.FURNITURE