Files
troupe-standup/wizard-work/forge/TRIAGE_DUMP_REFACTOR_VERIFICATION.md

8.6 KiB

forge — triage_dump probe refactor: behavior-preserving code review (VERIFICATION)

Lane: Refactor — code review and refactors Artifact committed to: wizard-work/forge/ (_triage_dump.py, _triage_dump_refactored.py, verify_triage_dump_refactor.py, _triage_dump_refactor_CHECK_EVIDENCE.txt) Verdict: 14/14 checks pass; probe output byte-identical to the original (6695 bytes, sha256 1bd715fb…).

Target

_triage_dump.py is a byte-identical copy of the repo-root throwaway probe .triage_dump.py (18 lines). It dumps the decided/pending items from the triage inbox seed inbox/seed-2026-09-26.json. The original ran its entire probe at module top level: it opened the JSON, loaded it into the module-global d, and printed everything at import time, with no if __name__ == "__main__" guard, zero function definitions, two module-level for loops, a hardcoded host-absolute JSON path at module scope, and the module-global d coupling data flow to the import side effect.

Smells fixed (behavior-preserving)

  1. Module-level execution. All file I/O, JSON loading, and printing now live under main(). The module imports with zero side effects; the entry point is explicitly guarded with if __name__ == "__main__": main().
    • Measured: check_import_side_effect_free — importing produces no stdout/ stderr and no SystemExit.
  2. Hardcoded host-absolute path at module scope (Q86). The bare path = "/root/troupe-standup/inbox/seed-...json" literal is replaced by a tree-relative resolution (_HERE -> repo root -> inbox/seed-...json) promoted to the named constant DEFAULT_PATH and the path parameter of main(). On this host the resolution is identical to the old literal (output byte-identical), but a clone now grades its own inbox instead of silently grading /root/... on the host.
    • Measured: check_main_path_parameter; check_seed_path_portable — no host-absolute literal in the refactored source and DEFAULT_PATH resolves inside the tree.
  3. No function extraction / module-global coupling. The two inline print loops (decided, pending) are extracted into the pure helpers _print_decided and _print_pending (plus load_data); d.get("decided", []) and d.get("pending", []) are evaluated once in main() and passed to the helpers as arguments instead of recomputed at module scope. The module-global d is gone.
    • Measured: check_helpers_extracted — all four module-level functions exist and main calls both print helpers; check_no_dead_imports — json is retained and referenced, no dangling imports.

Verification harness

verify_triage_dump_refactor.py — 14 checks, each a real subprocess/AST assertion (no tautology):

# check what it proves
1 py_compile refactored file is syntactically valid
2 identical output original vs refactored produce byte-identical stdout+stderr AND exit code
3 __main__ guard refactored has the guard (original's smell), in code not docstring
4 no global no global statements in code
5 import side-effect-free importing produces no output and no SystemExit
6 helpers extracted _print_decided, _print_pending, load_data, main exist; main calls both print helpers
7 main delegation main() body has no ;-compacted statements (extraction boundary intact)
8 main(path) param main accepts a configurable path parameter
9 no dead imports json retained and referenced; no unreferenced imports introduced
10 original still smells non-vacuous: original still lacks guard, still hardcodes the host-absolute path, still has module-level for, still has zero function defs
11 path override honoured main(path=custom) prints the custom file, not DEFAULT_PATH — kills the "accepts-but-ignores-path" mutation, which is byte-identical on the real seed and thus evades check 2
12 no import-time I/O (M6 killer) M6 (_bootstrap = json.load(open(DEFAULT_PATH)) at module scope, no print) survives check 5 by being silent, not clean. Static AST walk of top-level statements + dynamic builtins.open spy both require zero calls.
13 M6 mutant detected (non-vacuous) The check-12 detector fires on the measured M6 mutation applied to a temp copy, so it is sensitive rather than theater.
14 seed path portable (Q86) No host-absolute seed literal in the refactored source; DEFAULT_PATH resolves inside the tree and matches the harness's REAL_SEED_PATH. Closes the "a clone grades the host's inbox" gap.

Evidence (measured, this run)

$ python3 verify_triage_dump_refactor.py
OK: py_compile passes
OK: identical output (exit 0, 6695 bytes)
OK: __main__ guard present
OK: no 'global' statements in code
OK: import is side-effect-free (no probe output at import)
OK: _print_decided, _print_pending, load_data, main extracted; main calls both print helpers
OK: main() delegates via distinct standalone statements (no ';'-compaction)
OK: main(path) accepts a configurable path parameter
OK: all refactored imports are referenced (json retained, no dead imports)
OK: original still exhibits the removed smells (refactor is non-vacuous)
OK: main(path=custom) honours the override (prints custom file, not DEFAULT_PATH)
OK: no import-time I/O (0 module-scope io calls; 0 runtime open calls)
OK: M6 mutant detected at module scope: [(51, 'json.load'), (51, 'open')]
OK: seed path is tree-portable (resolves inside tree): /root/troupe-standup/inbox/seed-2026-09-26.json

=== Verification: 14/14 checks passed ===

Re-run under the optimised interpreter (per the lane's "python3 and -O" evidence convention):

$ python3 -O verify_triage_dump_refactor.py
=== Verification: 14/14 checks passed ===

Full capture in wizard-work/forge/_triage_dump_refactor_CHECK_EVIDENCE.txt.

Non-vacuity

Check 10 guarantees the refactor actually removed something: the original _triage_dump.py still exhibits every smell the refactored version no longer does (no __main__ guard, hardcoded host-absolute path at module scope, two module-level for loops, zero function definitions, module-global d). A no-op "refactor" would fail this.

$ python3 - <<'PY'
import ast
src = open("wizard-work/forge/_triage_dump.py").read()
t = ast.parse(src)
print("def count ->", sum(1 for n in t.body if isinstance(n, ast.FunctionDef)))
print("main-guard count ->", src.count('__name__ == "__main__"') + src.count("__name__ == '__main__'"))
print("module-level for ->", sum(1 for n in t.body if isinstance(n, ast.For)))
print("'d = json.load' at module scope ->", any(isinstance(n, ast.Assign) and any(getattr(t,'id',None)=='d' for t in n.targets) for n in t.body))
PY
def count -> 0
main-guard count -> 0
module-level for -> 2

Checks 12+13 are a paired non-vacuity pair for the import-time-IO detector: the clean module has zero module-scope io calls (check 12), and the M6 mutant (a silent module-scope json.load(open(DEFAULT_PATH))) is detected by the same detector (check 13). A detector that matches nothing would be theater; M6 proves check 12 is surgical.

Mutation kill

Check 11 (path override) is the key discriminator the byte-comparison cannot see: a path parameter that is accepted but ignored (always reads DEFAULT_PATH) produces byte-identical output on the real seed but prints the wrong data on a custom file. The check feeds a synthetic JSON containing "overridden" and asserts that token appears and the real seed path does not.

Checks 3/8/6/12 form the structural discriminators: re-adding any of the removed smells to the refactored file is caught, and a no-op refactor fails check 10 outright.

Independent byte-identical proof (outside the harness)

_triage_dump.py (the in-tree original; a byte-identical copy of the repo-root throwaway .triage_dump.py) vs. _triage_dump_refactored.py:

$ python3 _triage_dump.py 1>/tmp/oout 2>/tmp/oerr
$ python3 _triage_dump_refactored.py 1>/tmp/rout 2>/tmp/rerr
$ sha256sum /tmp/oout /tmp/rout
1bd715fbd97a6fc25a4c43581b20c231981118408a61689b4a9cd281cc3cc25b  /tmp/oout
1bd715fbd97a6fc25a4c43581b20c231981118408a61689b4a9cd281cc3cc25b  /tmp/rout
$ cmp /tmp/oout /tmp/rout && echo IDENTICAL
IDENTICAL   (cmp exit 0)
$ cmp /tmp/oerr /tmp/rerr && echo STDERR_IDENTICAL
STDERR_IDENTICAL   (cmp exit 0)

VERDICT: PASS -- triage_dump probe refactor is behavior-preserving; byte-identical output (6695 bytes, sha256 1bd715fb…), 14/14 on python3 and -O, exit 0; Q86 gaps closed (import-time I/O detected, seed path tree-portable).

CHECK: python3 /root/troupe-standup/wizard-work/forge/verify_triage_dump_refactor.py >/dev/null 2>&1