Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pact-plugin/tests/runbooks/RUNBOOK_RUN_DATES.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,9 @@ the calibration record.
| Run date (UTC) | Operator | Plugin version | Verdict | Harness-independence evidence | Notes (corpus; controls; per-set outcomes) |
| -------------- | -------- | -------------- | ------- | ----------------------------- | ------------------------------------------ |
| 2026-07-04 | michael-wojcik | 4.4.54 installed (hooks byte-identical to origin/main 7619ba1d, verified by full `diff -r` excl. `__pycache__` + sha256 of `merge_guard_common.py`) | **26/26 PASS under BOTH interpreters (52/52 row-executions, row-identical) · DUAL-INDEPENDENT FULL CONVERGE** — #1094 branch-delete cross-leg over-block REMOVED at BOTH grades: function-grade (5 cured separator families `&&`/`;`/`\|\|`/`\|`/`&` → `is_dangerous` False + `detect` None + `extract_command_context` `{}` mint-scan clean) AND real-main subprocess grade (`git branch new-feature && echo -D` and `git branch backup ; ls -D` → pre main exit 0 ALLOW, no token present); same-leg dangerous STILL gates in every probed leg position incl. the CRITICAL `cd /repo && git branch -D temp` (function-grade True/branch-delete + real-main exit 2 `permissionDecision: deny`), quoted-separator `git commit -m "a && b" && git branch -D temp`, env-prefix, both spelled-out arm orders; classification parity (read floor == detect) asserted on EVERY row; #1094 laundering CLOSED end-to-end at the real mains (ambiguous-compound approve → post main exit 0, mints 0 → escalated single `git branch -D new-feature` DENIES exit 2); faithful round-trip §0 control (approve `git branch -D stale` → mints exactly 1 → same single AUTHORIZEs exit 0) PASSED before any REFUSE was interpreted; clustered-flag pin `cd /repo && git branch -Df temp` ungated-by-design UNCHANGED (False on installed 4.4.53 AND 4.4.54 — pre-adjudicated limitation, NOT a finding); reversed-order `echo -D && git branch new` stays ungated (pre-existing-False pin); SEC-S1 session-gate SCOPED half confirmed on the installed mains (coverage-parity rows, see Notes): mint under session A carries `session_id=sessA` in the token → authorize attempt under session B DENIES exit 2 → same-session A AUTHORIZEs exit 0, 3/3 both interpreters. No HALT. | DUAL-INDEPENDENT: a pact-security-engineer ran a BLIND parallel adversarial verify of the same installed surface (harness + results NOT shared in either direction before verdict lock; reconciliation routed through the lead) → locked verdict **CONVERGE-SAFE, zero findings** — FULL CONVERGE with this probe's 26/26×2. JOINT-COVERAGE SPLIT: SE covered the populated-TOKEN half (11 mint→authorize round trips across op/target/bound-flags axes, AUTHORIZE + mismatch-DENY); on the session-scoping sub-axis BOTH runs were INERT-half (SE empirically confirmed `get_session_id()==""` in their probe env), so the SCOPED half was added HERE post-reconciliation (S0-S2 rows) to match the v4.4.53 precedent's joint coverage. RUNTIME SPAN covered by THIS harness alone: the identical probe files run under macOS `/usr/bin/python3` 3.9.6 (runtime floor) AND pyenv 3.12.7 — 26/26 PASS both, zero row divergence (a version-specific regex/slicing divergence would have contradicted). IDENTITY GATE first: full `diff -r` of `/Users/mj/.claude/plugins/cache/pact-plugin/PACT/4.4.54/hooks` vs the worktree at 7619ba1d byte-identical (excl. `__pycache__`); probe output asserts the imported module `__file__` is under the 4.4.54 cache path (A0 row) so no repo-copy contamination is possible. Harness-fidelity control (B0 mint→authorize round trip) PASSED before interpreting any deny. | Corpus recovered VERBATIM from the merged artifacts (NOT re-derived from prose): `TestBranchDeleteLiteralArmCrossLegSweep` cured/preserved/parity/pin rows (7619ba1d) + the `\|\|`/`\|`/`&` separator-cure rows (ecde737c) + the branch-delete laundering canary shape (test_merge_guard_auth_symmetry.py). Part A = in-process import of the INSTALLED `shared/merge_guard_common.py` (function grade: `is_dangerous_command` / `detect_command_operation_type` / `extract_command_context`). Part B = REAL SUBPROCESSES of the installed `merge_guard_pre.py`/`merge_guard_post.py` mains (hooks.json `python3 <hook>.py` shape); per-scenario isolated `CLAUDE_CONFIG_DIR` (== `TOKEN_DIR`, import-time env binding) + `HOME`, no `CLAUDE_PROJECT_DIR` → `get_session_id()`=="" → session gate INERT; zero `~/.claude` contamination; dangerous literals confined to the harness `.py` + subprocess stdin (an inline `python -c` control attempt was itself DENIED by the LIVE session guard — expected behavior, harness moved to a file). **4.4.53-INSTALLED CONTROL** (both interpreters): the cured compound `git branch new-feature && echo -D` WAS `is_dangerous=True`/`OP=branch-delete` on the prior installed version — the over-block existed installed-side pre-fix, so the v4.4.54 ALLOW is the CURE (installed-side non-vacuity), and the clustered pin is False on BOTH versions (UNCHANGED — not a v4.4.54 delta). This row DISCHARGES the post-install gate for #1094 (gated-closure discipline: the fix-level certification ran worktree hooks pre-merge — suite 10595/0/0 at commit ecde737c tip; this is the installed-binary confirmation per the v4.4.45/v4.4.53 post-install standard). Residual honestly graded: none new — the mint/authorize round-trip grade WAS achieved installed-side (B0/B3 real-main subprocess), no downgrade needed. **SEC-S1 SCOPED-HALF ROWS (S0-S2, coverage-parity NOT fix certification — PR #1102 did not touch session-gate code)**: real-main subprocesses with `CLAUDE_PROJECT_DIR` set and per-session `pact-session-context.json` files pre-seeded under `{CLAUDE_CONFIG_DIR}/pact-sessions/{slug}/{session_id}/` (the sessions root derives from `get_claude_config_dir()`, NOT `Path.home()` — a first harness draft seeded `HOME/.claude/pact-sessions` and correctly produced a session-UNSCOPED token, caught by the S0 `token_sid` assertion and fixed harness-side; the hook was never wrong); asymmetric predicate verified: populated current-session honors only a matching token (`sessB` attempt vs `sessA` token → deny; `sessA` → authorize), while the main probe's B rows cover the `get_session_id()==""` INERT half — both branches of the session-scoping gate now exercised on the INSTALLED binary this cycle, matching the v4.4.53 joint-coverage standard. |

## merge-guard-1100-retirement-flag-axis-post-install-live-probe (#1100 op+target+bound_flags retirement + #1110 malformed-bound_flags fail-safe; gated-closure discharge)

| Run date (UTC) | Operator | Plugin version | Verdict | Harness-independence evidence | Notes (S1–S6; fail-safe; non-vacuity; mode) |
| -------------- | -------- | -------------- | ------- | ----------------------------- | ------------------------------------------- |
| 2026-07-05 | michael-wojcik | 4.4.55 installed (both harnesses asserted the imported `merge_guard_post.__file__` resolves under `/Users/mj/.claude/plugins/cache/pact-plugin/PACT/4.4.55/hooks`, not the dev tree; the installed hook carries the #1100 flag axis + the L773 `isinstance`-list + `all(isinstance(x,str))` fail-safe guard) | **S1–S6 dual-independent CONVERGE-PASS, zero exceptions · #1100 CLOSED** — S1 friction-cure: a successful BARE `gh pr close 5` does NOT retire an approved ESCALATED `{close,5,[--delete-branch]}` token (the #1100 over-retirement cure; pre-#1100 op+target-only retirement would have burned it); S2 escalated self-consume `gh pr close 5 --delete-branch` RETIRES (renamed `.consumed`); S3 flagless `[]==[]` self-consume `gh pr close 5` RETIRES; S4a bare `gh pr merge 5` SURVIVES an escalated `{merge,5,[--admin]}` token · S4b reciprocal — `gh pr merge 5 --admin` SURVIVES a bare `{merge,5,[]}` token (symmetric non-burn on the flag axis); S5 JSON-null `bound_flags` token forced GLOB-VISITED-FIRST is SKIPPED by the fail-safe guard with NO exception AND a later valid `{close,6,[]}` token STILL retiring (definitive no-poison-the-loop proof); S6 unhashable `[{}]` list-element token SKIPPED, no exception. Zero exceptions in either harness. Security invariants intact on the shipped artifact: a genuine self-consume STILL retires (the flag axis opens no laundering/reuse window), the fail-safe never crashes the PostToolUse observer, and the sole residual is a tolerated under-retire backstopped by TTL(300s)+MAX_USES(2) — over-retire only CONSUMES a token (never authorizes), over-block is structurally impossible for a rename-after-success observer. No HALT. | DUAL independent CLEAN-ROOM harnesses driving the INSTALLED v4.4.55 `_retire_token_for_command` against a REAL on-disk token store (temp `token_dir`, `_retire_token_for_command(command, op_type, token_dir=...)`; the rename-to-`.consumed` is the observable): a SECURITY lens (emphasis: self-consume-preservation + fail-safe crash-safety + friction-cure-is-an-under-retire-not-a-wrongful-retire) + an INDEPENDENT REAL TEST lens that RE-DERIVED the on-disk token shape from the installed source (did NOT read the peer), forced malformed-first glob ordering for the S5 determinism, and added its own NON-VACUITY controls (a CTRL op-mismatch token that must SURVIVE + positive-retire controls S2/S3/S5-valid/S6-valid confirming the `.consumed` rename is genuinely reached). Each authored its own harness and LOCKED its verdict; verdicts CONVERGE with FULL per-scenario agreement across S1–S6, zero contradictions. | Post-install probe of the INSTALLED v4.4.55 `merge_guard_post.py` (not pytest); real on-disk token files in per-probe temp `token_dir`s; `sys.path` prepended with the 4.4.55 cache `hooks/` + `hooks/shared/` so the INSTALLED mains + `merge_guard_common` are imported (NOT the dev source tree — asserted via `__file__`). Mode-independent (file-on-disk token store; run under `get_session_id()==''` graceful-degradation → session gate INERT, isolating the flag axis with no session confound, per the #1031/#1032/#1097 precedent — the session-scoped half is unchanged by this PR and already jointly covered in the v4.4.53/v4.4.54 rows). This row DISCHARGES the post-install gate for #1100 (gated-closure discipline: the fix-level certification ran WORKTREE hooks pre-merge — full suite 10629 passed / 0 failed / 0 errors at HEAD `55d4507e`; dual-independent SAFE-TO-MERGE by a pact-security-engineer 8-item review + an independent 3-lens adversarial break-sweep, plus GitHub Copilot's malformed-`bound_flags` crash catch fixed + 9 regression tests; this is the installed-binary confirmation per the v4.4.45/v4.4.53/v4.4.54 post-install standard). Shipping PR: #1110 (v4.4.55, squash `fa3e876b`). No new residual: the friction-cure is a bounded under-retire (tolerated + TTL/MAX_USES-backstopped), the fail-safe is a graceful skip-not-crash (deletion left to the read arm's reaper), and the malformed-token skip is the SAFE under-retire direction. No HALT. |