CB-WP-0005 read 5/8 and CB-WP-0007 read 2/6 in every status run since they closed, because only 'done' counted and their remaining tasks are 'cancel'. Two permanently-wrong numbers teach the reader to skip the column. Both now collapse into 'closed and complete' -- 18 of them -- while an open workplan with cancellations still shows the count separately, so a cancellation is visible rather than laundered into completion. The workplan block is extracted as render_workplans so the control is stated over what the tool PRINTS rather than over a literal the test wrote: a done+cancelled fixture must collapse, and one with a real todo must not. The first version of that control asserted arithmetic on its own input, which is the tautological shape ADR-0010 D2 demoted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
cc8917a6fb
commit
5c00c72d3b
1 changed files with 40 additions and 2 deletions
|
|
@ -266,18 +266,37 @@ def report():
|
||||||
# length limit it is meant to keep. Collapse the fully-closed ones to
|
# length limit it is meant to keep. Collapse the fully-closed ones to
|
||||||
# a single line rather than raising the limit — the precedent is
|
# a single line rather than raising the limit — the precedent is
|
||||||
# LOOP-LINT's four loadability breaches, each fixed structurally.
|
# LOOP-LINT's four loadability breaches, each fixed structurally.
|
||||||
|
render_workplans(plans)
|
||||||
|
report_tail(plans)
|
||||||
|
|
||||||
|
|
||||||
|
def render_workplans(plans):
|
||||||
|
"""The workplan block. Extracted so its behaviour can be asserted on
|
||||||
|
rather than re-derived in a test (ADR-0010 D2: controls are stated
|
||||||
|
over what the tool does, not over a literal the test wrote)."""
|
||||||
print("\n workplans")
|
print("\n workplans")
|
||||||
closed = []
|
closed = []
|
||||||
for wid, title, status, tasks, _kind in plans:
|
for wid, title, status, tasks, _kind in plans:
|
||||||
|
# `cancel` is a CLOSED outcome, not an open one. Counting only
|
||||||
|
# `done` left CB-WP-0005 reading "5/8" and CB-WP-0007 "2/6" in
|
||||||
|
# every status run since they closed — permanently wrong numbers,
|
||||||
|
# which teach the reader to skip the column. The two figures are
|
||||||
|
# kept separate so a cancellation is still visible rather than
|
||||||
|
# laundered into completion.
|
||||||
done = sum(1 for _, s, _ in tasks if s == "done")
|
done = sum(1 for _, s, _ in tasks if s == "done")
|
||||||
if status == "done" and done == len(tasks):
|
cancelled = sum(1 for _, s, _ in tasks if s == "cancel")
|
||||||
|
if status == "done" and done + cancelled == len(tasks):
|
||||||
closed.append(wid.replace("CB-WP-", ""))
|
closed.append(wid.replace("CB-WP-", ""))
|
||||||
continue
|
continue
|
||||||
short = (title or "")[:44]
|
short = (title or "")[:44]
|
||||||
print(f" {wid} {status:<12} {done}/{len(tasks)} done {short}")
|
note = f", {cancelled} cancelled" if cancelled else ""
|
||||||
|
print(f" {wid} {status:<12} {done}/{len(tasks)} done{note} {short}")
|
||||||
if closed:
|
if closed:
|
||||||
print(f" {len(closed)} closed and complete: " + " ".join(closed))
|
print(f" {len(closed)} closed and complete: " + " ".join(closed))
|
||||||
|
|
||||||
|
|
||||||
|
def report_tail(plans):
|
||||||
|
"""Next task, spend, budgets, fast gates — the rest of the report."""
|
||||||
nxt = next_task(plans)
|
nxt = next_task(plans)
|
||||||
if nxt:
|
if nxt:
|
||||||
wid, tid, prio = nxt
|
wid, tid, prio = nxt
|
||||||
|
|
@ -351,6 +370,25 @@ def self_test():
|
||||||
abs(META_SOFT_PCT - 100 / TRAILING_PASSES) < 1e-9,
|
abs(META_SOFT_PCT - 100 / TRAILING_PASSES) < 1e-9,
|
||||||
f"{META_SOFT_PCT}% over {TRAILING_PASSES} passes; one meta pass at "
|
f"{META_SOFT_PCT}% over {TRAILING_PASSES} passes; one meta pass at "
|
||||||
f"parity reads {100 / TRAILING_PASSES:.0f}%")
|
f"parity reads {100 / TRAILING_PASSES:.0f}%")
|
||||||
|
# A workplan whose tasks are done-or-cancelled is CLOSED. Counting
|
||||||
|
# only `done` left two real workplans reading 5/8 and 2/6 forever.
|
||||||
|
def rendered(tasks):
|
||||||
|
out = io.StringIO()
|
||||||
|
saved, sys.stdout = sys.stdout, out
|
||||||
|
try:
|
||||||
|
render_workplans([("CB-WP-0000", "fixture", "done", tasks, "meta")])
|
||||||
|
finally:
|
||||||
|
sys.stdout = saved
|
||||||
|
return out.getvalue()
|
||||||
|
|
||||||
|
both = rendered([("T01", "done", "high"), ("T02", "cancel", "low")])
|
||||||
|
check("a done+cancelled workplan collapses to closed",
|
||||||
|
"closed and complete" in both and "1/2" not in both,
|
||||||
|
both.strip().splitlines()[-1].strip())
|
||||||
|
open_one = rendered([("T01", "done", "high"), ("T02", "todo", "low")])
|
||||||
|
check("a workplan with a real todo does NOT collapse",
|
||||||
|
"1/2 done" in open_one, open_one.strip().splitlines()[-1].strip())
|
||||||
|
|
||||||
check("the budget states what it is for",
|
check("the budget states what it is for",
|
||||||
bool(META_PURPOSE) and "task at hand" in META_PURPOSE)
|
bool(META_PURPOSE) and "task at hand" in META_PURPOSE)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue