WillTools 2026-09-09 -- clean snapshot of the development repo for review
ci / test (push) Successful in 6m18s
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:
@@ -0,0 +1,192 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Switching the position search off, and saying so.
|
||||
|
||||
The search is 93% of a run -- measured 2026-08-30 across the 184-piece
|
||||
reference sweep: 12.6 s of a 13.6 s median, and 41 minutes of a 42 minute
|
||||
batch. `--no-recommend` is what makes a batch usable.
|
||||
|
||||
Everything here is about the same one risk. A report whose "Recommended
|
||||
positions" section had simply gone missing reads exactly like a report on a
|
||||
piece with nothing to recommend -- and the report's own words for that case
|
||||
are "the inserts as drawn are already at the best position this search can
|
||||
find", which is a sentence about a search nobody ran. Same rule as a stage
|
||||
with `enabled: false`: NOT RUN is never silent.
|
||||
|
||||
The other half is that the default must not move. `searched` is written into
|
||||
the JSON summary only when the search was skipped, the same way the job writer
|
||||
emits `enabled` only when it is false, so a run with no flag produces the same
|
||||
bytes it did before the flag existed.
|
||||
"""
|
||||
import io
|
||||
import json
|
||||
|
||||
from panellift import cli, layout, report
|
||||
from test_cli import aspire_job
|
||||
|
||||
|
||||
def _run(tmp_path, *flags):
|
||||
"""The CLI, end to end, on a real job file. Returns (code, out, html)."""
|
||||
tmp_path.mkdir(parents=True, exist_ok=True)
|
||||
job_path = tmp_path / 'job.json'
|
||||
out_path = tmp_path / 'report.html'
|
||||
with io.open(str(job_path), 'w', encoding='utf-8') as fh:
|
||||
fh.write(json.dumps(aspire_job()))
|
||||
code = cli.main([str(job_path), '-o', str(out_path)] + list(flags))
|
||||
with io.open(str(out_path), 'r', encoding='utf-8') as fh:
|
||||
return code, out_path, fh.read()
|
||||
|
||||
|
||||
# ----------------------------------------------------- the flag does its job
|
||||
|
||||
def test_no_recommend_leaves_every_verdict_alone(tmp_path, capsys):
|
||||
"""The flag drops an ANSWER, never a CHECK. If it could change a verdict
|
||||
it would be a different calculation, not a faster one."""
|
||||
with_search = _run(tmp_path / 'a', )
|
||||
capsys.readouterr()
|
||||
without = _run(tmp_path / 'b', '--no-recommend')
|
||||
capsys.readouterr()
|
||||
assert with_search[0] == without[0]
|
||||
|
||||
job = aspire_job()
|
||||
_p, _r, cases = cli.analyse_job(job)
|
||||
full = cli.summarise(cases, layout.recommend(cases))
|
||||
skipped = cli.summarise(cases, layout.not_searched())
|
||||
assert full['verdict'] == skipped['verdict']
|
||||
assert [s['verdict'] for s in full['stages']] == \
|
||||
[s['verdict'] for s in skipped['stages']]
|
||||
assert [s['peak_tension_psi'] for s in full['stages']] == \
|
||||
[s['peak_tension_psi'] for s in skipped['stages']]
|
||||
|
||||
|
||||
def test_no_recommend_is_actually_faster(tmp_path, capsys):
|
||||
"""Not a behaviour test -- a claim test. The flag exists for one reason
|
||||
and a version of it that still searched would pass every other test
|
||||
here."""
|
||||
import time
|
||||
job = aspire_job()
|
||||
_p, _r, cases = cli.analyse_job(job)
|
||||
|
||||
t0 = time.perf_counter()
|
||||
layout.recommend(cases)
|
||||
searched = time.perf_counter() - t0
|
||||
|
||||
t0 = time.perf_counter()
|
||||
layout.not_searched()
|
||||
skipped = time.perf_counter() - t0
|
||||
|
||||
assert skipped < searched / 10.0
|
||||
|
||||
|
||||
# ------------------------------------------------------- and says it did it
|
||||
|
||||
def test_the_report_says_the_positions_were_not_computed(tmp_path, capsys):
|
||||
"""Present, closed, flagged NOT RUN, honest when opened.
|
||||
|
||||
Skipping the search is the ordinary way this runs now, so the section is
|
||||
no longer a warning box on an open heading -- it is a collapsed
|
||||
disclosure like every other section on the page, carrying NOT RUN on the
|
||||
line you can read without opening it.
|
||||
"""
|
||||
_code, _path, html = _run(tmp_path, '--no-recommend')
|
||||
capsys.readouterr()
|
||||
assert 'Recommended positions' in html # the section stays
|
||||
assert 'Not computed' in html
|
||||
# the closed summary line says so, and nothing shouts
|
||||
assert '<b class="notrun-tag">not run</b>' in html
|
||||
assert 'class="caveat"' not in html
|
||||
# and none of the things a search that RAN would have said
|
||||
assert 'already at the best position' not in html
|
||||
assert 'recommended x' not in html
|
||||
|
||||
|
||||
def test_the_not_run_section_is_a_collapsed_details(tmp_path, capsys):
|
||||
"""The engineer's own words: it is always there, and closed by default.
|
||||
|
||||
Both halves matter. A section that vanishes on a skipped search reads as
|
||||
a piece with nothing to move; a section that opens itself puts a notice
|
||||
nobody asked for above the numbers they did.
|
||||
"""
|
||||
_code, _path, skipped_html = _run(tmp_path / 'skipped', '--no-recommend')
|
||||
capsys.readouterr()
|
||||
_code, _path, ran_html = _run(tmp_path / 'ran')
|
||||
capsys.readouterr()
|
||||
|
||||
for html, tagged in ((skipped_html, True), (ran_html, False)):
|
||||
i = html.index('Recommended positions')
|
||||
head = html[max(0, i - 200):i]
|
||||
# inside a <details class="section">, and never an open one
|
||||
assert '<details class="section">' in head
|
||||
assert '<details class="section" open' not in html
|
||||
assert '<h2>Recommended positions</h2>' not in html
|
||||
assert ('notrun-tag">not run' in html) is tagged
|
||||
|
||||
|
||||
def test_a_skipped_search_never_reads_as_nothing_to_move():
|
||||
"""The exact confusion this is all here to prevent."""
|
||||
ran = report._recommendation(layout.Recommendation())
|
||||
skipped = report._recommendation(layout.not_searched())
|
||||
assert 'already at the best position' in ran
|
||||
assert 'already at the best position' not in skipped
|
||||
assert 'did not run' in skipped
|
||||
|
||||
|
||||
def test_the_stdout_line_says_so_too(tmp_path, capsys):
|
||||
"""A batch scrolling past has to be visible without opening a report."""
|
||||
_run(tmp_path, '--no-recommend')
|
||||
out = capsys.readouterr().out
|
||||
assert 'NOT COMPUTED' in out
|
||||
|
||||
_run(tmp_path / 'again')
|
||||
out = capsys.readouterr().out
|
||||
assert 'NOT COMPUTED' not in out
|
||||
|
||||
|
||||
def test_the_summary_carries_searched_false(tmp_path, capsys):
|
||||
job = aspire_job()
|
||||
_p, _r, cases = cli.analyse_job(job)
|
||||
skipped = cli.summarise(cases, layout.not_searched())
|
||||
assert skipped['recommendation']['searched'] is False
|
||||
assert skipped['recommendation']['note']
|
||||
assert skipped['recommendation']['moves'] == []
|
||||
|
||||
|
||||
def test_searched_is_absent_when_the_search_ran():
|
||||
"""Written only when it was skipped -- the same rule the job writer
|
||||
follows for `enabled`. Absent means it ran, which is what every summary
|
||||
written before this flag existed means.
|
||||
"""
|
||||
job = aspire_job()
|
||||
_p, _r, cases = cli.analyse_job(job)
|
||||
full = cli.summarise(cases, layout.recommend(cases))
|
||||
assert 'searched' not in full['recommendation']
|
||||
assert full['recommendation'].get('searched', True) is True
|
||||
|
||||
|
||||
# --------------------------------------------------------- nothing else moved
|
||||
|
||||
def test_a_default_run_is_byte_for_byte_what_it_was(tmp_path, capsys):
|
||||
"""The flag is additive. With nothing asked for, every byte of the
|
||||
report and of the JSON summary is what it was before the flag existed --
|
||||
which is checked here on one job and, out of band, on all 184 of the
|
||||
reference sweep with the clock frozen."""
|
||||
job = aspire_job()
|
||||
_p, _r, cases = cli.analyse_job(job)
|
||||
rec = layout.recommend(cases)
|
||||
|
||||
html_default = report.build_many(cases, recommendation=rec)
|
||||
summary_default = json.dumps(cli.summarise(cases, rec), sort_keys=True)
|
||||
|
||||
# the same call the pre-flag code made, with no recommendation passed in
|
||||
_p2, _r2, cases2 = cli.analyse_job(aspire_job())
|
||||
html_implicit = report.build_many(cases2)
|
||||
summary_implicit = json.dumps(cli.summarise(cases2), sort_keys=True)
|
||||
|
||||
assert html_default == html_implicit
|
||||
assert summary_default == summary_implicit
|
||||
|
||||
|
||||
def test_the_flag_is_off_unless_asked_for(tmp_path, capsys):
|
||||
"""A default that has to be asked for is a default nobody gets."""
|
||||
_code, _path, html = _run(tmp_path)
|
||||
capsys.readouterr()
|
||||
assert 'Not computed' not in html
|
||||
Reference in New Issue
Block a user