bundle-parity check is one-directional — orphan files in simplicio_loop/_bundle/ ship in the pip wheel undetected
Problem
scripts/claims_audit.py check 4 (bundle-parity) walks source → bundle only: it verifies every source file exists and matches in simplicio_loop/_bundle/, but never does the reverse pass. A renamed or deleted source file leaves an orphan copy in _bundle/ that passes the gate and gets packaged into the pip wheel.
The plugin-parity check already does this correctly in both directions — the asymmetry is the bug.
Evidence
- One-directional:
scripts/claims_audit.py:158-171 iterates source files, checks presence+content in bundle. No bundle→source walk.
- Correct reference implementation:
scripts/sync_plugin.py:107-143 does both src→dst and dst→src (orphan detection) for plugin/.
- Repro:
git mv hooks/loop_capture.py hooks/loop_capture2.py && python3 scripts/sync_plugin.py && python3 scripts/check.py → bundle keeps the old loop_capture.py copy; check 4 still passes (every current source file matches); the wheel ships a stale hook. (Revert after repro.)
Impact
- Stale/removed logic silently distributed to every
pip install simplicio-loop user.
- Worst case: a hook removed for being buggy keeps shipping and keeps being wired by stale docs.
Proposed fix
In claims_audit.py check 4, after the forward pass, walk simplicio_loop/_bundle/ (same subtrees: skills, hooks, runtime scripts, parity tests) and fail with a named list of orphans — mirroring sync_plugin.py's dst→src logic. Consider extracting the shared walk into one helper used by both (see the separate LEAN_SCRIPTS duplication issue — same theme: one source of truth for the mirror contract).
Add a gate test: create a temp orphan in _bundle/, assert check 4 fails closed, remove it.
Acceptance criteria
bundle-parity check is one-directional — orphan files in
simplicio_loop/_bundle/ship in the pip wheel undetectedProblem
scripts/claims_audit.pycheck 4 (bundle-parity) walks source → bundle only: it verifies every source file exists and matches insimplicio_loop/_bundle/, but never does the reverse pass. A renamed or deleted source file leaves an orphan copy in_bundle/that passes the gate and gets packaged into the pip wheel.The plugin-parity check already does this correctly in both directions — the asymmetry is the bug.
Evidence
scripts/claims_audit.py:158-171iterates source files, checks presence+content in bundle. No bundle→source walk.scripts/sync_plugin.py:107-143does bothsrc→dstanddst→src(orphan detection) forplugin/.git mv hooks/loop_capture.py hooks/loop_capture2.py && python3 scripts/sync_plugin.py && python3 scripts/check.py→ bundle keeps the oldloop_capture.pycopy; check 4 still passes (every current source file matches); the wheel ships a stale hook. (Revert after repro.)Impact
pip install simplicio-loopuser.Proposed fix
In
claims_audit.pycheck 4, after the forward pass, walksimplicio_loop/_bundle/(same subtrees: skills, hooks, runtime scripts, parity tests) and fail with a named list of orphans — mirroringsync_plugin.py's dst→src logic. Consider extracting the shared walk into one helper used by both (see the separate LEAN_SCRIPTS duplication issue — same theme: one source of truth for the mirror contract).Add a gate test: create a temp orphan in
_bundle/, assert check 4 fails closed, remove it.Acceptance criteria
simplicio_loop/_bundle/hooks/makespython3 scripts/check.pyfail with the orphan path named.tests/covering the orphan case.