mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 08:35:57 +00:00
feat: vendor permission system source
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
---
|
||||
issue: 318
|
||||
issue_title: "Introduce an McpTargetList value object in mcp-targets.ts"
|
||||
---
|
||||
|
||||
# Retro: #318 — Introduce an `McpTargetList` value object in `mcp-targets.ts`
|
||||
|
||||
## Stage: Planning (2026-06-02T00:00:00Z)
|
||||
|
||||
### Session summary
|
||||
|
||||
Produced the implementation plan for replacing the `pushTarget` closure in `src/mcp-targets.ts` with an `McpTargetList` value object that owns the ordered-uniqueness invariant.
|
||||
This is Track C / Step 5 of the architecture roadmap (Finding 4).
|
||||
The change is behavior-preserving — the existing `test/mcp-targets.test.ts` is the regression guard and candidate ordering is unchanged.
|
||||
|
||||
### Observations
|
||||
|
||||
- The design is unambiguous per the issue; only one decision needed surfacing: whether `McpTargetList` is exported with direct unit tests or kept module-private.
|
||||
Confirmed with the user via `ask_user` — chose **export + direct unit tests**, mirroring the existing `parseQualifiedMcpToolName` (exported + tested) precedent in the same module.
|
||||
This adds a new red→green cycle (Step 1) documenting the invariant in isolation.
|
||||
- Both Non-Goals from the issue were preserved in the plan: no MCP-naming command methods on the list (keeps ordering+uniqueness separate from the `${server}_${tool}` spelling), and no `McpInvocation`/`deriveTargets()` class (a one-shot transform in a class costume).
|
||||
- Sole production consumer is `src/input-normalizer.ts` (line 106), which spreads the result — so `toArray()` returning a defensive copy (`[...this.targets]`) instead of the live array is behavior-preserving and strictly safer.
|
||||
- The two private helpers (`pushMcpToolPermissionTargets`, `addDerivedMcpServerTargets`) already took a `pushTarget` callback, so swapping it for an injected `McpTargetList` is a clean DIP-friendly substitution with no LoD / output-argument / reverse-search concerns.
|
||||
- Grep confirmed no `src/`, `test/`, or skill file references the changed symbols beyond `input-normalizer` and the two test files; the architecture doc (Finding 4 / Step 5) is the only doc needing an update.
|
||||
- TDD order is 3 cycles: (1) `test:` add `McpTargetList` + tests, (2) `refactor:` rewrite dispatch, (3) `docs:` mark roadmap Step 5 done.
|
||||
Next step is `/tdd-plan`.
|
||||
|
||||
## Stage: Implementation — TDD (2026-06-02T17:10:00Z)
|
||||
|
||||
### Session summary
|
||||
|
||||
Completed all 3 TDD cycles from the plan: (1) exported `McpTargetList` class with 6 focused unit tests, (2) rewrote `createMcpPermissionTargets`, `pushMcpToolPermissionTargets`, and `addDerivedMcpServerTargets` to construct and tell an `McpTargetList` instead of threading a `pushTarget` callback, (3) updated `docs/architecture/architecture.md` to mark Finding 4 and Step 5 as ✅ resolved.
|
||||
Test count rose from 1753 to 1759 (+6 new `McpTargetList` invariant tests).
|
||||
All deterministic checks (check, lint, test, fallow dead-code) passed throughout.
|
||||
|
||||
### Observations
|
||||
|
||||
- No deviations from the plan.
|
||||
The two private helpers (`addDerivedMcpServerTargets`, `pushMcpToolPermissionTargets`) already accepted a `pushTarget` callback, making the swap to an injected `McpTargetList` mechanical — exactly as anticipated.
|
||||
- `toArray()` returning a defensive copy (`[...this.targets]`) was confirmed safe: the sole consumer (`input-normalizer.ts`) spreads the result, so the copy is behavior-invisible.
|
||||
- Pre-completion reviewer: **PASS**.
|
||||
One WARN noted: the stepdown ordering in `src/mcp-targets.ts` has private helpers listed above the exported caller (`createMcpPermissionTargets`) — this is pre-existing (not introduced by this PR) and left for a future cleanup.
|
||||
- Next step is `/ship-issue #318`.
|
||||
|
||||
## Stage: Final Retrospective (2026-06-02T22:09:04Z)
|
||||
|
||||
### Session summary
|
||||
|
||||
Shipped the `McpTargetList` value-object extraction across three stages (Planning → TDD → Ship) with zero deviations and a PASS pre-completion review.
|
||||
The `pushTarget` closure in `src/mcp-targets.ts` was replaced by an exported value object owning the ordered-uniqueness invariant; the per-mode dispatch now tells the list instead of asking the array via `includes`.
|
||||
CI landed green on `efee1b20`, issue #318 was closed, and no release-please PR appeared (expected — the change is `refactor:`/`test:`/`docs:` only, no `feat:`).
|
||||
|
||||
### Observations
|
||||
|
||||
#### What went well
|
||||
|
||||
- The single planning `ask_user` gate (export `McpTargetList` + direct tests vs. keep module-private) was the one genuine judgment call, and resolving it up front shaped the TDD order — it added the dedicated Step 1 red→green cycle that documents the invariant in isolation.
|
||||
A small, well-placed decision gate paid off downstream.
|
||||
- Verification ran incrementally rather than only at the end: green baseline (`check`/`lint`/`test`) before any code, per-file `vitest run test/mcp-targets.test.ts` after each red and green, then the full suite + `check` + `lint` + `fallow dead-code` after the last step.
|
||||
The red phase was genuinely observed (6 failures: `McpTargetList is not a constructor`) before implementing — a real TDD loop, not a retrofit.
|
||||
- Scope discipline held: the pre-completion reviewer flagged a pre-existing stepdown-ordering WARN (private helpers above their exported caller), and it was correctly left alone rather than opportunistically fixed inside a behavior-preserving refactor PR.
|
||||
|
||||
#### What caused friction (agent side)
|
||||
|
||||
- `other` — the `test:` (`6d4da354`) and `refactor:` (`f527ba7c`) commit subjects omitted the `(#318)` issue ref, while the surrounding `docs:` commits carried it.
|
||||
These followed the plan's suggested commit messages verbatim, which themselves lacked the ref.
|
||||
Impact: minor — at ship time the `git log --grep='#318'` filter missed two commits, so the close-comment commit list had to be built from the push range (`d509e960..HEAD`) instead.
|
||||
No rework, no wrong artifact; the `git push` output already gave the exact range.
|
||||
|
||||
#### What caused friction (user side)
|
||||
|
||||
- None.
|
||||
User involvement was limited to the one planning decision gate and stage transitions; no mid-stage corrections or redirects were needed.
|
||||
|
||||
### Diagnostic details
|
||||
|
||||
- **Model-performance correlation** — one subagent dispatch (`pre-completion-reviewer`) ran on judgment-heavy review work (acceptance criteria, code design, conventional commits, Mermaid render check) and returned a thorough, correctly-scoped PASS with one accurate pre-existing WARN.
|
||||
Appropriate task/model match; no mismatch.
|
||||
- **Feedback-loop gap analysis** — no gap.
|
||||
Verification was incremental at every step (baseline before TDD, per-file after each red/green, full gate after the last step); nothing was deferred to the end that should have run earlier.
|
||||
- **Escalation-delay / unused-tool** — not applicable; no `rabbit-hole` or `missing-context` friction points arose.
|
||||
|
||||
### Changes made
|
||||
|
||||
1. Appended this Final Retrospective entry to `packages/pi-permission-system/docs/retro/0318-introduce-mcp-target-list.md`.
|
||||
No `AGENTS.md` or `.pi/prompts/` changes — the session surfaced no friction justifying a rule change (the one cosmetic commit-ref gap is self-healing via the ship flow's push-range recovery).
|
||||
Reference in New Issue
Block a user