WillTools 2026-09-09 -- clean snapshot of the development repo for review
ci / test (push) Successful in 6m14s
ci / test (push) Successful in 6m14s
History-free snapshot of the private development repository at 77a82eb. Code, docs and the public catalogue only: no plant or job knowledge layers, no client, job or producer names (tools/scrub.py clean against the widened term list; a second word-level grep clean). The intro deck is left out because its slide images cannot be checked for job drawings.
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Which end of the piece is up, when it came from a fallback -- and the red
|
||||
line telling the reader to go check TOT on the model.
|
||||
|
||||
`report.up_end_disclosure()` / `report._up_end_block()` already print the
|
||||
fallback's own explanation, unconditionally, whenever `source.up_end_basis`
|
||||
is anything but the ruled mechanism (`RULED_UP_END_BASIS`). What is new here
|
||||
is `report._up_end_is_origin_defect()`: of the three reasons the ruled
|
||||
mechanism can decline (see `up_end_from_origin()` in
|
||||
`WillTools.extension/lib/vibe/knowledge.py`), only the FIRST -- the origin's
|
||||
own up vector does not point up -- is a defect on the assembly's origin
|
||||
itself. The other two (near-square; not yet confirmed for this piece's
|
||||
orientation) are gaps in what the rule covers, not something wrong with the
|
||||
model, and must never carry the same red call to action.
|
||||
"""
|
||||
import re
|
||||
|
||||
from conftest import make_panel
|
||||
|
||||
from panellift import report
|
||||
|
||||
|
||||
# Verbatim from `up_end_from_origin()`'s FIRST refusal
|
||||
# (WillTools.extension/lib/vibe/knowledge.py) -- the exact shape
|
||||
# `liftexport` writes into `source.up_end_basis_why`, and the real text on
|
||||
# WP401 (2026-09-01).
|
||||
ORIGIN_NOT_UP_WHY = (
|
||||
"The origin of assembly WP401 does not stand the piece up: its up "
|
||||
"basis is (0.0, 1.0, 0.0) rather than world up. One assembly in 282 is "
|
||||
"like this -- its face normal points up instead -- and on such a "
|
||||
"piece every reading off the frame is wrong, so nothing is read off "
|
||||
"this one. Which end is up was therefore read from GLOBAL ELEVATION "
|
||||
"instead -- the end of the piece that is higher in the model. That is "
|
||||
"a fallback, not the rule.")
|
||||
|
||||
# Verbatim shape of the SECOND refusal (near square) -- must NOT flag.
|
||||
NEAR_SQUARE_WHY = (
|
||||
"Assembly PNL127 is near square (11.63 x 11.58 ft, ratio 1.00), and "
|
||||
"below 1.25 the long direction cannot be told from the up direction.")
|
||||
|
||||
# Verbatim shape of the THIRD refusal (not yet confirmed for this
|
||||
# orientation) -- must NOT flag either; this is a coverage gap, not a
|
||||
# defect on the model. Matches `up_end_from_origin()`'s wording as fixed
|
||||
# 2026-09-01: green (BasisY/world-up) is now confirmed for a vertical wall
|
||||
# panel too, so the message no longer claims nobody has said how vertical
|
||||
# panels work -- only that this function has not been extended to run
|
||||
# there, which is a coverage gap and NOT a defect on the origin.
|
||||
NOT_HORIZONTAL_WHY = (
|
||||
"The origin rule is confirmed for HORIZONTAL panels only, and the "
|
||||
"origin of assembly PNL1 stands its length up, which is not one. The "
|
||||
"owner has confirmed the same green-arrow reading also holds on a "
|
||||
"vertical wall panel (2026-09-01), but this rule has not been "
|
||||
"extended to run there yet, so the origin is not read on this piece.")
|
||||
|
||||
|
||||
def _panel_with_fallback(why, basis='global elevation'):
|
||||
panel = make_panel()
|
||||
panel.source = {
|
||||
'up_end_basis': basis,
|
||||
'up_end_basis_why': why,
|
||||
'up_end_affects': 'erection -- which row of face lifters the crane '
|
||||
'cannot reach, and which edge the anchors are on',
|
||||
}
|
||||
return panel
|
||||
|
||||
|
||||
# ------------------------------------------------- _up_end_is_origin_defect
|
||||
|
||||
def test_the_origin_not_up_refusal_is_flagged():
|
||||
assert report._up_end_is_origin_defect(ORIGIN_NOT_UP_WHY) is True
|
||||
|
||||
|
||||
def test_the_near_square_refusal_is_not_flagged():
|
||||
assert report._up_end_is_origin_defect(NEAR_SQUARE_WHY) is False
|
||||
|
||||
|
||||
def test_the_not_yet_confirmed_orientation_refusal_is_not_flagged():
|
||||
assert report._up_end_is_origin_defect(NOT_HORIZONTAL_WHY) is False
|
||||
|
||||
|
||||
def test_empty_or_none_why_is_not_flagged():
|
||||
assert report._up_end_is_origin_defect('') is False
|
||||
assert report._up_end_is_origin_defect(None) is False
|
||||
|
||||
|
||||
# --------------------------------------------------------- _up_end_block()
|
||||
|
||||
def test_the_red_line_appears_when_the_origin_itself_is_wrong():
|
||||
"""WP401's real shape: the origin does not point up at all, so this is
|
||||
a defect on the assembly's own TOT, not a caveat about the analysis."""
|
||||
panel = _panel_with_fallback(ORIGIN_NOT_UP_WHY)
|
||||
block = report._up_end_block(panel)
|
||||
assert 'tot-flag' in block
|
||||
assert 'TOT' in block
|
||||
# The short fact is always visible; the measured reasoning ("does not
|
||||
# stand the piece up") is inside the fold, not repeated at top level.
|
||||
assert 'read from global elevation, not the assembly origin' in block
|
||||
assert 'does not stand the piece up' in block
|
||||
|
||||
|
||||
def test_the_block_is_short_a_few_lines_not_a_wall_of_text():
|
||||
"""The owner's own words, 2026-09-01: '把这一段从lift的结果里面删掉,
|
||||
或者缩短...太长了压根不会看的' -- delete this section or shorten it, it
|
||||
is so long nobody will read it at all. The block he cut was ~700
|
||||
characters; the always-visible text (outside the fold) must be a small
|
||||
fraction of that."""
|
||||
panel = _panel_with_fallback(ORIGIN_NOT_UP_WHY)
|
||||
block = report._up_end_block(panel)
|
||||
# Everything inside the fold is closed by default and does not count
|
||||
# against "what a reader sees at a glance" -- strip it out before
|
||||
# measuring, the same way a browser would hide it on load. Tags do not
|
||||
# count either: they are never visible text, only the characters
|
||||
# between them are.
|
||||
fold_start = block.index('<details')
|
||||
fold_end = block.index('</details>') + len('</details>')
|
||||
always_visible = block[:fold_start] + block[fold_end:]
|
||||
visible_text = re.sub(r'<[^>]+>', '', always_visible)
|
||||
assert len(visible_text) < 250, (len(visible_text), visible_text)
|
||||
|
||||
|
||||
def test_fallback_not_the_rule_appears_at_most_once():
|
||||
"""The old block said this exact clause TWICE in one paragraph -- once
|
||||
as the report's own intro sentence, once again from the end of the
|
||||
producer string it quoted. That repetition, not the length alone, was
|
||||
what the owner named as the reason he stopped reading."""
|
||||
panel = _panel_with_fallback(ORIGIN_NOT_UP_WHY)
|
||||
block = report._up_end_block(panel)
|
||||
assert block.count('fallback, not the rule') <= 1
|
||||
|
||||
|
||||
def test_the_full_reasoning_is_folded_using_the_report_s_own_mechanism():
|
||||
"""Not deleted, not moved to a different wall of visible text -- folded
|
||||
behind the SAME <details>/_sec() idiom every other section already
|
||||
uses, closed by default."""
|
||||
panel = _panel_with_fallback(ORIGIN_NOT_UP_WHY)
|
||||
block = report._up_end_block(panel)
|
||||
assert '<details class="section upend-why">' in block
|
||||
assert '<summary>Why</summary>' in block
|
||||
assert 'open' not in block.split('<details')[1].split('>')[0]
|
||||
# The full producer reasoning is still there -- just inside the fold.
|
||||
assert 'One assembly in 282' in block
|
||||
assert 'That is a fallback, not the rule.' in block
|
||||
|
||||
|
||||
def test_the_red_line_is_absent_for_the_near_square_refusal():
|
||||
"""A near-square piece is genuinely undecidable, not a broken origin --
|
||||
the red 'go check TOT' line would send the reader to fix a model that
|
||||
is not wrong."""
|
||||
panel = _panel_with_fallback(NEAR_SQUARE_WHY)
|
||||
block = report._up_end_block(panel)
|
||||
assert block # the disclosure itself still prints
|
||||
assert 'tot-flag' not in block
|
||||
assert 'TOT' not in block
|
||||
|
||||
|
||||
def test_the_red_line_is_absent_for_the_not_yet_confirmed_orientation():
|
||||
"""A vertical panel the rule has not been extended to cover yet is a
|
||||
known gap, not a defect -- same non-flag as the near-square case."""
|
||||
panel = _panel_with_fallback(NOT_HORIZONTAL_WHY)
|
||||
block = report._up_end_block(panel)
|
||||
assert block
|
||||
assert 'tot-flag' not in block
|
||||
assert 'TOT' not in block
|
||||
|
||||
|
||||
def test_no_block_at_all_when_the_ruled_mechanism_answered():
|
||||
"""`up_end_basis` == the ruled mechanism (`RULED_UP_END_BASIS`) means
|
||||
there is nothing to disclose -- and therefore nothing to flag."""
|
||||
panel = _panel_with_fallback('assembly origin should never get here',
|
||||
basis=report.RULED_UP_END_BASIS)
|
||||
assert report._up_end_block(panel) == ''
|
||||
|
||||
|
||||
def test_no_block_at_all_when_the_panel_has_no_source_disclosure():
|
||||
panel = make_panel()
|
||||
panel.source = {}
|
||||
assert report._up_end_block(panel) == ''
|
||||
|
||||
|
||||
def test_the_flag_uses_the_same_red_every_fail_on_the_page_already_uses():
|
||||
"""Match the report's existing severity styling rather than inventing a
|
||||
new colour -- var(--fail), the same variable `.FAIL` uses."""
|
||||
assert '.tot-flag{color:var(--fail)' in report.CSS
|
||||
|
||||
|
||||
def test_the_flag_is_small_text_not_a_banner():
|
||||
"""It sits inside the existing warn-styled .upend box; it must not carry
|
||||
its own background, border or oversized font that would read as a
|
||||
second banner on the page."""
|
||||
css = report.CSS
|
||||
start = css.index('.tot-flag{')
|
||||
end = css.index('}', start)
|
||||
rule = css[start:end]
|
||||
assert 'font-size:12px' in rule
|
||||
assert 'background' not in rule
|
||||
assert 'border' not in rule
|
||||
Reference in New Issue
Block a user