8.5 KiB
issue, issue_title
| issue | issue_title |
|---|---|
| 480 | pi-permission-system: extract shared fixtures for the external-directory tests (Phase 6 Step 8) |
Retro: #480 — Extract shared fixtures for the external-directory tests
Stage: Planning (2026-06-26T00:00:00Z)
Session summary
Planned the extraction of a shared test/helpers/external-directory-fixtures.ts for the external-directory handler-pipeline tests (Phase 6 Step 8).
Scoped the fixture to two files — external-directory-integration.test.ts and external-directory-session-dedup.test.ts — and explicitly excluded the third file the issue named.
The plan is a behavior-preserving test:-only refactor across two lift-and-shift commits plus a verification step, targeting package duplication ≤ 6.5% (currently 7.1%).
Observations
- File 3 (
test/bash-external-directory.test.ts) dropped from scope (operator decision viaask_user). It tests a different surface — the pureextractExternalPathsFromBashCommandfunction that runs before the gate, not the collapsed gate. Its bulk is the repeated system-under-test call, which thetestingskill says not to wrap to chase a clone metric. fallow confirms it is not in the duplication families; its "880-line arrow" is a unit-size smell, not a clone family. No follow-up filed. - Discrepancy between issue and fallow: the issue cites
test/bash-external-directory.test.ts, but fallow'sbash-external-directory.test.tsclone family is a different file undertest/handlers/gates/. This reinforced that File 3's listed smell is size, not duplication. - The ~288 lines of clones in Files 1 & 2 alone hit the ≤ 6.5% target — so excluding File 3 does not jeopardize the roadmap outcome.
- No-speculative-export constraint shaped the TDD order: each migration commit lands the fixture pieces and their sole consumer together, so no fixture-only commit leaves dead exports for fallow to flag.
- Invariant guard: the dedup
check(intent)mock (makeExtDirDedupCheck) must preserveintent.kind === "path-values"dispatch (#478 / #418) or external-directory false-greens toallow; moved verbatim, and the re-prompt assertions catch a regression. - Release nuance: roadmap tag is
Release: independent, but atest:-only change ishidden: trueand will not cut a release on its own — it auto-batches into the next release. Recorded in the plan's Release Recommendation rationale.
Stage: Implementation — TDD (2026-06-26T21:30:00Z)
Session summary
Completed all three TDD steps in a single session across two lift-and-shift commits.
Created test/helpers/external-directory-fixtures.ts and migrated both handler-pipeline test files onto it, dissolving the 43-line wiring duplicate in the session-dedup file's inline shutdown test.
Package duplication dropped from 7.1% to exactly 6.5% — the roadmap Step 8 target.
Observations
- Duplication hit exactly 6.5% — the two major clone families (21 groups/214 lines and 3 groups/74 lines) no longer appear as top-level families in
pnpm fallow dupes. Residual clones (17 groups/133 lines in the integration file; 2 groups/14 lines in the dedup file) are the test-act repetitions thetestingskill says not to wrap. pi-autoformatconvertedmakeEventstotype makeEventsin the first fixture write (correctly: only used in a type position at that point). AddingmakeDedupWiringin Step 2 reintroduced a value-position use ofmakeEvents, so the import had to be changed back to a value import. TheEditapproach for the Step 2 update handled this cleanly in the imports edit.makeSessionApprovingPrompterkept private — not exported, since File 2 never uses it directly;makeDedupWiringbuilds the default prompter internally. This avoids a fallow dead-export flag while keeping the approval semantics encapsulated.- Event-shape preservation — File 2 uses
toolName:(notname:) in event literals; the newmakeExtDirToolEvent/makeExtDirBashEventbuilders match that shape exactly sogetToolNameFromValuebehavior is unchanged. - Pre-completion reviewer verdict: WARN (non-blocking).
All WARN items are
architecture.mdroadmap markers (✅on Step 7 + Step 8 headings and Mermaid nodes, Track C flip to✅ complete, Step 8Target:description update to remove the scoped-outbash-external-directory.test.ts) — all explicitly deferred to ship time per the plan.
Stage: Final Retrospective (2026-06-26T22:15:00Z)
Session summary
Shipped #480 across a clean three-stage arc (plan → TDD → ship): the shared external-directory-fixtures.ts landed, both handler-pipeline test files migrated, package duplication hit the 6.5% target exactly, and Phase 6 of the pi-permission-system roadmap completed.
The one recurring friction — surfaced across this issue and #479 — is that the roadmap-completion ✅ marker keeps getting deferred to ship time, where it either falls through entirely (#479) or lands as a post-CI commit that triggers a second CI cycle (#480).
Observations
What went well
ask_userFile-3 scoping caught a real divergence (novel win). The issue's "Proposed change" named three files; the planningask_usergate surfaced thattest/bash-external-directory.test.tstests a different surface (the pure path-extraction function) whose bulk is the SUT-call act thetestingskill says not to wrap. Scoping it out up front prevented wasted migration work and still hit the duplication target from Files 1 & 2 alone.- Prediction accuracy. The plan predicted duplication would drop to ≤ 6.5% from Files 1 & 2 alone; it landed at exactly 6.5%, and the test count was unchanged (2124 → 2124) as designed for a behavior-preserving refactor.
- Incremental verification (no feedback-loop gap).
The TDD stage ran the affected file plus the full suite after each of Steps 1 and 2, then
check/lint/dead-code/fallow dupesbefore finishing — verification was paced per-change, not deferred to the end.
What caused friction (agent side)
instruction-violation(self-identified, but recurring) — the roadmap-completion✅marker was deferred to ship time instead of landing in the implementation doc-update commit (/tdd-planstep 7). The package skill says to mark it "as part of the shipping change ... using the completion-marker convention from the implementation prompts ... do not leave it for a later session" — an internally contradictory phrasing that two consecutive planning sessions (#479 and #480) both read as "defer to/ship-issue." Impact: #479's ship never applied its✅(it fell through — the/ship-issueprompt has no step for it), so #480's ship had to clean up both issues' markers in a separate post-CI commit (92f9fc99), triggering a second full push + CI cycle (~150 s). This is the dominant cross-session pattern and the only finding worth a guidance change.other(minor) — twoarchitecture.mdEditoldTextmatch failures during ship, because the replacement text was constructed from the plan's quoted prose rather than the live file (the roadmap heading readSplit thewith backticks, notSplit). Impact: two extraReadcalls and one retry; recovered immediately by reading the exact region. No rework beyond the retries.
What caused friction (user side)
- None.
The operator's only interactive input was the planning
ask_userFile-3 scoping decision, which was strategic and well-timed.
Diagnostic details
- Model-performance correlation — the sole subagent dispatch (
pre-completion-reviewer) ran onanthropic/claude-sonnet-4-6, appropriate for judgment-heavy review; it produced an accurate WARN (correctly flagging the deferred✅items and thedead-codeself-consumption nuance). Main work ran on opus. No mismatch. - Escalation-delay tracking — no rabbit-holes; the longest retry sequence was the two
architecture.mdedit attempts, well under the 5-call threshold. - Feedback-loop gap analysis — none; verification ran incrementally (see "What went well").
Changes made
.pi/skills/package-pi-permission-system/SKILL.md— reworded the roadmap-completion guidance: the✅step/Mermaid marker (plus stale health-metric/target rows) now lands in the implementation doc-update commit (/tdd-planstep 7 //build-plan), not a deferred/ship-issuecommit. Added aRefs #479, #480justification.