9.0 KiB
issue, issue_title
| issue | issue_title |
|---|---|
| 428 | pi-permission-system: permission-system using incorrect path for `projectAgentsDir` |
Retro: #428 — pi-permission-system: permission-system using incorrect path for projectAgentsDir
Stage: Planning (2026-06-17T00:00:00Z)
Session summary
Planned the fix for derivePolicyLoaderOptions computing projectAgentsDir as <cwd>/.pi/agent/agents instead of the Pi-convention <cwd>/.pi/agents.
The plan corrects the path via a new getProjectAgentsDir(cwd) helper in config-paths.ts, adds a behavior-level regression test, and fixes the same wrong path propagated into docs/configuration.md.
Observations
- Third-party issue (author
robertpeteuil, not the operator), so the direction was confirmed throughask_userrather than assumed. - The operator initially leaned toward a shared cross-package path helper, then toward
pi-subagentsowning it. Surfaced that pi-permission-system currently has zero code dependency on pi-subagents — they couple only via the Pi event bus (channels re-declared independently per ADR-0002), so pps works standalone. Importing from pi-subagents would have introduced the first hard dependency and ended standalone use. - Reframed
<cwd>/.pi/agentsas a Pi platform convention, not pi-subagents' private knowledge: pps already independently (and correctly) encodes three sibling convention paths, including the global agents dir it shares with pi-subagents. Operator agreed on a local fix with a named helper + cross-reference comment + regression test, preserving the decoupling. - Classified as breaking (
fix!:): project-agentpermission:frontmatter, silently ignored today, starts being enforced on upgrade and can make sessions more restrictive. - Per-agent permissions apply to directly-activated agents too (via
/agents), not only pi-subagents children — so the path cannot be pushed via pi-subagents lifecycle events without missing cases. This confirmed the path belongs in pps. - Found a propagated documentation bug at
docs/configuration.md:532repeating the same wrong path; folded its correction into the plan as a separatedocs:step. - Long-term framing corrected by the operator after the initial draft: Pi is single-agent by deliberate design; multiple named agents are an external concept (pi-subagents, pi-agent-router, MasuRii packages), not Pi core.
Verified in the wiring — pps learns the active agent from a generic
<active_agent>tag injected by pi-agent-router / anactive_agentsession entry, and/agentsis a pi-subagents command; there is no agent activation independent of external tooling. So my earlier "directly-activated via/agents" justification was wrong, and both initial Open Questions (upstreamgetProjectAgentsDirto the SDK; have the core parse agent frontmatter) were withdrawn — they would push a multi-agent concept into a core that rejects it. - Corrected long-term direction now in the plan: per-agent
permission:frontmatter is an extension bridge on pps's single-agent core; a cleaner future keeps that bridge generic (the multi-agent extension supplies the active agent's overrides via an extension-agnostic channel, like the active-agent signal pps already consumes), so pps need not locate or parse agent files. Short-term fix is unchanged. - Recorded the settled part of this framing in
docs/architecture/architecture.mdat the operator's request: a new design principle 9 ("Single-agent core, multi-agent by extension") plus a framing note annotating theAgent frontmatter(AF) input in the architecture-overview diagram. The forward-looking generic-channel evolution stays in the plan's Open Questions, not the architecture doc.
Stage: Implementation — TDD (2026-06-17T14:15:00Z)
Session summary
Completed both TDD steps from the plan in one session.
Added getProjectAgentsDir(cwd) to src/config-paths.ts, wired it into derivePolicyLoaderOptions, and covered it with a unit test plus two regression tests (path-level and behavior-level).
Test count went from 2015 to 2018 (+3).
Observations
- No deviations from the plan; the one-line fix plus helper extraction went exactly as planned.
- The pre-completion reviewer returned WARN (not FAIL) with two stale path references not covered by the plan:
docs/troubleshooting.md:31(sampleconfig.resolvedlog) anddocs/decisions/0001-project-trust-adoption.md:30(code comment in ADR-0001). Both were fixed in an additionaldocs:commit before writing these notes. - After the WARN fixes, all checks are clean:
pnpm run check,pnpm run lint,pnpm run test(2018 pass),pnpm fallow dead-codeall pass. - Pre-completion reviewer verdict: WARN → resolved (both stale-path findings addressed; effectively PASS at ship time).
Stage: Final Retrospective (2026-06-17T15:30:00Z)
Session summary
Shipped a one-line path fix (<cwd>/.pi/agent/agents → <cwd>/.pi/agents) end-to-end across planning, TDD, and ship in a single continuous session, releasing @gotgenes/pi-permission-system v14.0.0.
The planning stage did the heavy lifting: three ask_user rounds converged on a decoupling-preserving local fix and surfaced the single-agent-architecture framing now recorded as architecture design principle 9.
Observations
What went well
- The
ask_userreframe loop changed the outcome. The third-party-direction question plus two helper-shape questions stopped me from building the first-ever hardpps → pi-subagentsdependency (the initial "shared helper" instinct). Verifying that pps has zero existing code dependency on pi-subagents, then reframing<cwd>/.pi/agentsas a Pi platform convention, landed the correct local fix. The gate earned its keep on a bug that looked trivial. - The pre-completion reviewer caught what planning missed.
The fresh-context reviewer (
anthropic/claude-sonnet-4-6) flagged two staleagent/agentsreferences the planning grep never checked (docs/troubleshooting.md,docs/decisions/0001-project-trust-adoption.md), turning a would-be post-release doc drift into one pre-shipdocs:commit. - Clean TDD execution. Red→green→commit ran exactly as planned with incremental verification (baseline check, per-file vitest in red/green, full suite + check + lint + fallow before the reviewer); no rework, +3 tests.
What caused friction (agent side)
missing-context— the planning-stage stale-path grep was scoped to two hand-picked files (packages/pi-permission-system/docs/configuration.mdandREADME.md) instead of the whole packagedocs/tree. Agrep -rn "agent/agents" packages/pi-permission-system/docs/would have surfacedtroubleshooting.md(sampleconfig.resolvedlog) anddocs/decisions/0001-project-trust-adoption.md(ADR code comment) at plan time. Impact: reviewer-caught (not self-identified at plan time); one extradocs:commit (95effebf) at the TDD/ship boundary.other(tool usage) — anEditbatch was rejected for carryingoldText2/newText2keys on a single edit object instead of separateedits[]entries. Impact: one retry, self-corrected, no rework.missing-context(minor) — tried to load thecolgrepskill from.pi/skills/colgrep/SKILL.md(ENOENT); the real path ispackages/pi-colgrep/skills/colgrep/SKILL.md. Impact: negligible — proceeded withgrep, which suited the exact-string search.
What caused friction (user side)
- The single-agent-architecture framing arrived as operator pushback after the plan was drafted with SDK-upstreaming Open Questions ("upstream
getProjectAgentsDirto the SDK"; "have the core parse agent frontmatter"). This is durable, reusable knowledge — Pi is single-agent by design; multiple named agents are an external-extension concept — now captured indocs/architecture/architecture.mddesign principle 9. Opportunity: thepackage-pi-permission-systemskill (loaded at the start of every planning session) does not point to it, so a future session could re-derive the same wrong framing.
Diagnostic details
- Model-performance correlation — the sole subagent dispatch (pre-completion-reviewer) ran on
anthropic/claude-sonnet-4-6, appropriate for judgment-heavy read-only review; it found two real issues. No mismatch. - Escalation-delay tracking — no
rabbit-holesequences; the only tool errors (oneEditrejection, one skill ENOENT) self-corrected on the next call. - Feedback-loop gap analysis — verification ran incrementally throughout TDD (baseline → per-file vitest → full suite + check + lint + fallow), not just at the end. No gap.
Changes made
.pi/skills/package-pi-permission-system/SKILL.md— added a### Single-agent corenote under Cross-Extension Integration (pointing to architecture design principle 9) and gave the pre-existing jiti prose a### Jiti isolationheading so the two stay separate..pi/prompts/plan-issue.md— added a Module-Level Changes grep rule: when correcting a literal value that appears in prose, grep the wholepackages/<PKG>/docs/tree, not a hand-picked subset.