mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 16:45:22 +00:00
feat: vendor permission system source
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
---
|
||||
issue: 362
|
||||
issue_title: "Convert `createSessionLogger` factory into a `SessionLogger` class"
|
||||
---
|
||||
|
||||
# Retro: #362 — Convert `createSessionLogger` factory into a `SessionLogger` class
|
||||
|
||||
## Stage: Planning (2026-06-09T13:22:31Z)
|
||||
|
||||
### Session summary
|
||||
|
||||
Planned Phase 5 Step 1 (Track A): converting the `createSessionLogger` factory in `src/session-logger.ts` into a state-owning class.
|
||||
Wrote `docs/plans/0362-session-logger-class.md` — a behavior-preserving reshape that lands the class, the sole `index.ts` call-site update, and the `test/session-logger.test.ts` construction updates in one `refactor:` commit.
|
||||
|
||||
### Observations
|
||||
|
||||
- Naming collision resolved via `ask_user`: the issue says "introduce a `SessionLogger` class", but `SessionLogger` is the widely-injected interface seam (`ConfigStore`, `PermissionForwarder`, `PermissionPrompter`, RPC handlers, `lifecycle.ts` all depend on it via `SessionLogger` / `DebugReviewLogger` / `ReviewLogger`).
|
||||
The package convention is interface-as-seam + distinctly-named class (`DecisionReporter`→`GateDecisionReporter`, `PermissionsService`→`LocalPermissionsService`).
|
||||
User chose `PermissionSessionLogger` (domain-qualifier style, mirroring `PermissionServiceLifecycle`).
|
||||
- Key `this`-binding check: the [#336] factory returned arrow-closure object methods, so consumers *could* pass `logger.review` bare.
|
||||
Grep confirmed all six consumers invoke through the stored object reference (`this.logger.review(...)`), never bare — so class instance methods are safe and `@typescript-eslint/unbound-method` won't fire.
|
||||
This was the main correctness risk and it's clear.
|
||||
- Scope deliberately narrow: the `index.ts` forward-reference cycle (`null as unknown as ConfigStore`, the `sessionNotify` holder, the `getRuntimeContext()?.ui.notify` reach-through) is left untouched — that's Step 2 ([#363]), which depends on this reshape.
|
||||
- Followed the [#336] convention of not editing the Phase 5 metrics table or roadmap step prose during planning (phase-start snapshot); the `✓ complete` mark goes in at ship time.
|
||||
- Single TDD step is justified: removing the `createSessionLogger` export breaks the sole call site and the test file at the type level together, so the fold-into-one-commit rule applies; the test file is mechanically updated (construction expression only), not rewritten.
|
||||
- Next stage: `/tdd-plan`.
|
||||
|
||||
## Stage: Implementation — TDD (2026-06-09T14:45:49Z)
|
||||
|
||||
### Session summary
|
||||
|
||||
Completed 1 TDD cycle: converted `createSessionLogger` factory to the `PermissionSessionLogger` class in `src/session-logger.ts`, swapped the sole call site in `src/index.ts`, and updated `test/session-logger.test.ts` (import, 11 construction expressions, top-level `describe`) — all in one `refactor:` commit per the fold-into-one rule.
|
||||
Test count was unchanged at 1900 (91 files).
|
||||
Also committed a `docs:` update to `docs/architecture/architecture.md` reflecting the new class name.
|
||||
|
||||
### Observations
|
||||
|
||||
- Autoformat ran on `session-logger.ts` after the Edit; re-read before touching the file again (autoformat note from AGENTS.md).
|
||||
- The `this`-binding risk was clear in practice: all 11 tests passed without any `.bind` adjustment, confirming grep's analysis that no consumer passes methods as bare references.
|
||||
- No deviations from the plan; the single-step fold was the right call — compiler rejected the mismatched import immediately on the red phase.
|
||||
- Pre-completion reviewer verdict: PASS — no issues found; all deterministic checks clean; test count unchanged; architecture doc correctly updated.
|
||||
|
||||
## Stage: Final Retrospective (2026-06-09T22:23:54Z)
|
||||
|
||||
### Session summary
|
||||
|
||||
Shipped #362 (Phase 5 Step 1, Track A): converted the `createSessionLogger` factory to the `PermissionSessionLogger` class across planning, one TDD cycle, and ship in a single continuous session.
|
||||
CI passed, the issue was closed, and no release-please PR was produced (the lone non-docs commit is `refactor:`, which release-please does not version).
|
||||
Execution was clean throughout — the only friction was one mangled file path during planning; no rework, no plan deviations.
|
||||
|
||||
### Observations
|
||||
|
||||
#### What went well
|
||||
|
||||
- The planning-stage `this`-binding analysis paid off exactly as predicted: grepping all six logger consumers to confirm none pass a bare `logger.review` reference de-risked the factory→class conversion upfront, and all 11 tests went green with zero `.bind` adjustments.
|
||||
A risk the plan named precisely is the cheapest kind to retire.
|
||||
- The single-step fold was correctly predicted at plan time: removing the `createSessionLogger` export breaks the sole call site (`index.ts`) and the test file together at the type level, so the compiler rejected the mismatched import the instant the red phase landed — confirming the fold-into-one-commit call rather than discovering it the hard way.
|
||||
- Incremental verification was exemplary: green baseline → red confirmed → green confirmed → `pnpm run check` before commit (correct per the shared-type rule, since the class implements a widely-injected interface) → full suite + lint + `fallow` after.
|
||||
No end-of-session surprise.
|
||||
- The release-timing question at ship was a genuine strategic checkpoint: #362 is the foundation of a serial sequence (#362 → #363 → #364), and surfacing release-now-vs-batch let the user make that call deliberately rather than defaulting.
|
||||
|
||||
#### What caused friction (agent side)
|
||||
|
||||
- `other` (path construction) — during planning, the first `Read` of `index.ts` used a hand-built absolute path (`/Users/chris/development/pi/pi-permission-system/src/index.ts`) that dropped both `pi-packages/` and `packages/`, so the `external_directory` guard denied it.
|
||||
Impact: one denied tool call, corrected in the very next batch with the right path; no rework.
|
||||
Self-identified.
|
||||
Lesson (local, not a new rule): for `Read`, prefer a CWD-relative path (`packages/pi-permission-system/src/index.ts`) over an absolute path reconstructed from memory — the relative form cannot drift and is not subject to the out-of-tree guard.
|
||||
|
||||
#### What caused friction (user side)
|
||||
|
||||
- None.
|
||||
The two user interactions (class name, release timing) were both genuine preference/strategic decisions appropriately routed through `ask_user`, not mechanical oversight.
|
||||
|
||||
### Diagnostic details
|
||||
|
||||
- Model-performance correlation — one subagent dispatched: `pre-completion-reviewer` on `anthropic/claude-sonnet-4-6` (per its agent frontmatter).
|
||||
Appropriate: review is judgment-heavy, and a sonnet-class model is the right tier; no mismatch.
|
||||
- Escalation-delay tracking — no rabbit-holes; the single denied read resolved on the next call (1 retry, well under the 5-call flag).
|
||||
- Unused-tool detection — no gaps; `grep` over `colgrep` was the correct choice for exact-symbol work (`createSessionLogger`, `SessionLoggerDeps`) per the colgrep decision table.
|
||||
- Feedback-loop gap analysis — verification ran incrementally at every boundary (baseline, red, green, pre-commit `check`, post-commit suite/lint/fallow); no lens-flagged gap.
|
||||
|
||||
### Changes made
|
||||
|
||||
1. Appended this Final Retrospective stage entry to `packages/pi-permission-system/docs/retro/0362-session-logger-class.md`.
|
||||
No prompt or `AGENTS.md` changes proposed — the session surfaced no recurring, generalizable friction worth a project-wide rule.
|
||||
Reference in New Issue
Block a user