Files
my-pi/pi-permission-system/docs/retro/0342-retire-permission-system-test-catch-all.md

98 lines
9.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
issue: 342
issue_title: "Retire the permission-system.test.ts catch-all"
---
# Retro: #342 — Retire the `permission-system.test.ts` catch-all
## Stage: Planning (2026-06-08T02:08:35Z)
### Session summary
Produced a redistribution plan for the 2,785-line `permission-system.test.ts` catch-all (~86 `test()` blocks).
Inventoried every test by fixture usage (`createManager`, `createManagerWithProject`, `new PermissionManager`, and the end-to-end `createToolCallHarness`) and mapped each concern to a co-located destination.
Confirmed all prerequisites are met — Step 8 ([#341]) is closed, so the collaborators are independently constructable.
### Observations
- The catch-all cleanly splits into two families: synchronous config-resolution tests (clear homes, move verbatim) and end-to-end async `tool_call` tests (overlap with existing `makeHandler` / `makeFakePi` handler and composition-root tests).
- Used `ask_user` once on the two genuine ambiguities.
Decisions: (1) async integration tests — drop-redundant / move-unique rewritten onto `makeHandler`, not promote the heavy `createToolCallHarness`; (2) assertion fidelity — behavior-preserving (adapt to destination fixture), not byte-for-byte.
These shape the plan toward a smaller, fully co-located suite rather than a faithful-but-heavy lift-and-shift.
- Three source modules (`status.ts`, `logging.ts`, `before-agent-start-cache.ts`) have no co-located test file today; the plan creates `test/status.test.ts`, `test/logging.test.ts`, `test/before-agent-start-cache.test.ts`.
- `createManagerWithProject` (catch-all local helper, 5 callers) is promoted to `test/helpers/manager-harness.ts`.
- This is test-only and behavior-preserving — no red phase.
Plan recommends executing with `/build-plan`, not `/tdd-plan`, with migration steps as move → run-full-suite → commit (`test:`).
- The largest bucket (~43 tests) lands in `permission-manager-unified.test.ts`; split across two steps (surface-resolution, then session-aware `checkPermission`) to keep commits reviewable.
- Two deferred open questions left for execution: exact home for the unique `session_shutdown clears` case, and `config-store` vs `policy-loader` for `getResolvedPolicyPaths`.
- `design-review` skill judged not applicable — no production interface or wiring changes; only a test fixture is promoted.
- Step 9 of the Phase 4 roadmap in `docs/architecture/architecture.md` must get `✓ complete` in the final step.
[#341]: https://github.com/gotgenes/pi-packages/issues/341
## Stage: Implementation — TDD (2026-06-08T13:09:43Z)
### Session summary
Executed all 9 migration steps from the plan. 76 tests redistributed across 12 destination files; 10 redundant end-to-end async tests dropped.
The 2,785-line `permission-system.test.ts` catch-all was deleted; the suite is now fully co-located at 90 test files, 1813 tests.
### Observations
- No red phase throughout — suite stayed green at every commit, confirming the lift-and-shift approach was correct.
- `pi-autoformat` reflowed several files after edits; re-read before subsequent edits was occasionally needed (no failures resulted).
- The two deferred open questions from planning resolved cleanly: `getResolvedPolicyPaths` landed in `permission-manager-unified.test.ts` (not `config-store.test.ts`) since that file already held all other direct-`PermissionManager` integration tests; the `session_shutdown clears approvals` test landed in `external-directory-session-dedup.test.ts` with inline session wiring (not `composition-root.test.ts`), avoiding the need to set up full `piPermissionSystemExtension` + real config for one test.
- 10 redundant async tests were dropped: 5 path-bearing `tool_call` external_directory tests (covered by `external-directory-integration.test.ts`), 1 bash external_directory `deny` test (covered by `tool-call.test.ts`), 1 generic ask serialization test (rewritten onto `makeHandler`), and 3 session-approval dedup tests (covered by `external-directory-session-dedup.test.ts`).
- The reviewer flagged two documentation WARNs: (1) `package-pi-permission-system` skill didnt mention the new `createManagerWithProject` export; (2) Step 8 (#341) in `architecture.md` was missing `✓ complete`.
Both fixed before the final commit.
- `pnpm fallow dead-code` exited zero — no dead exports introduced.
- Pre-completion reviewer: PASS.
## Stage: Final Retrospective (2026-06-08T13:19:34Z)
### Session summary
Shipped issue #342 across four stages (Planning, TDD implementation, Ship, Retrospective): the 2,785-line `permission-system.test.ts` catch-all was dissolved into 12 co-located files, 10 redundant async tests dropped, and the suite is now fully co-located at 90 files / 1813 tests.
This completed Phase 4 (Step 9) of the permission-system structural roadmap.
The execution was notably clean — no rework cycles, no rabbit-holes, and the only friction was a one-shot pre-commit lint auto-fix.
### Observations
#### What went well
- The planning-stage `ask_user` decision (drop-redundant / move-unique for async tests; behavior-preserving assertions) gave the TDD stage a crisp rule to apply.
All 16 async tests were classified without mid-execution thrashing — 10 dropped, 6 moved — exactly as the rule predicted.
- Incremental verification was exemplary: every one of the 9 migration steps ran the affected test file, then the full suite, then committed.
The feedback-loop gap lens finds nothing to flag — this is the inverse of the "verify only at the end" anti-pattern.
- The `pre-completion-reviewer` subagent earned its keep: it caught two real documentation gaps (the `manager-harness.ts` skill doc missing the new `createManagerWithProject` export, and a pre-existing missing `✓ complete` on roadmap Step 8) that would otherwise have shipped stale.
- Both planning open questions resolved cleanly at execution time without re-opening the decision (`getResolvedPolicyPaths``permission-manager-unified.test.ts`; `session_shutdown clears` → inline-wired test in `external-directory-session-dedup.test.ts`).
#### What caused friction (agent side)
- `instruction-violation` (self-identified) — wrote `vi.mocked(prompter.prompt).mock.calls[0]![0]` with a non-null assertion in `test/handlers/tool-call.test.ts`; the pre-commit `eslint` hook auto-stripped the `!` (`no-unnecessary-type-assertion`, since the tsconfig does not flag the index access), modifying the file and failing the first commit attempt.
`AGENTS.md` already documents the Biome/ESLint non-null-assertion conflict.
Impact: 3 extra tool calls (lint check, `git diff`, re-commit) — ~1 min, no test-logic rework; the hook applied the fix automatically.
- `other` (no rework) — `pi-autoformat` reflowed edited files mid-stream, occasionally requiring a re-read before the next edit (already noted in the TDD stage; no failures resulted).
#### What caused friction (user side)
- The plan explicitly recommended executing with `/build-plan` (test-only, no red phase), but the session ran `/tdd-plan`.
The agent adapted cleanly — treating each step as move → verify → commit without a red phase — so no rework resulted.
Opportunity, not criticism: when a plan's execution-model recommendation and the chosen slash command diverge, the divergence was harmless here because the two prompts share the verify-and-commit spine.
### Diagnostic details
- **Model-performance correlation** — Planning ran on `anthropic/claude-opus-4-8` (judgment-heavy: inventory, the `ask_user` design decision, plan authoring) — appropriate.
TDD implementation ran on `anthropic/claude-sonnet-4-6` (mechanical lift-and-shift across 9 steps) — well-matched cost/capability for behavior-preserving moves.
Ship ran on `opencode-go/deepseek-v4-flash` (push, CI watch, issue close, release check) — mostly mechanical, but Step 4b (multi-issue sequence: release now vs. batch) and the stacked-issue close-detection are genuine judgment points; the flash model handled them correctly here only because the situation was simple (`test:`/`docs:`-only range, no release-please PR, final step of a finished phase).
Borderline fit — a more capable model would be safer on a ship step that carried a live release-please merge or sibling-issue closes.
Retrospective ran on `anthropic/claude-opus-4-8` — appropriate for synthesis.
- **Escalation-delay tracking** — no `rabbit-hole` friction; the lint auto-fix resolved in 3 tool calls, well under the 5-call threshold.
- **Unused-tool detection** — no `missing-context` gaps; `grep`/`bash` were correctly preferred over `colgrep` for the catch-all inventory (exact `test()`-block counting and fixture-usage mapping is exact-match work, not semantic search).
- **Feedback-loop gap analysis** — verification ran incrementally after every step, not just at the end; no gap to flag.
### Changes made
1. Added this Final Retrospective stage entry to `packages/pi-permission-system/docs/retro/0342-retire-permission-system-test-catch-all.md`.
No `AGENTS.md` or prompt changes — the session's single friction point is already covered by `AGENTS.md` and auto-fixed by the pre-commit hook (user confirmed: land retro only).