10 KiB
issue, issue_title
| issue | issue_title |
|---|---|
| 473 | pi-permission-system: extract the tree-sitter parser and AST node-text resolver from bash-program.ts (Phase 6 Step 1) |
Retro: #473 — Extract the tree-sitter parser and AST node-text resolver from bash-program.ts
Stage: Planning (2026-06-25T00:00:00Z)
Session summary
Produced a three-cycle plan for Phase 6 Step 1: lift the lazy tree-sitter parser (getParser, TSNode, TSParser, initParser) into src/access-intent/bash/parser.ts and the quote-aware node-text resolver (resolveNodeText, SKIP_SUBTREE_TYPES) into src/access-intent/bash/node-text.ts, leaving bash-program.ts importing both.
Pure lift-and-shift, non-breaking; the plan seeds the package's first domain directory and adds the unit tests the extraction newly enables.
Observations
- Verified the extraction is legitimate SRP decomposition, not metric-gaming procedure-splitting: the parser owns state (memoized singleton + retry semantics) and
resolveNodeTextreturns a value (pure AST transform), both leaf utilities with zero dependency on the rest of the file. TSNodemust be exported fromparser.ts(used pervasively inbash-program.tsand bynode-text.ts);TSParserandinitParserstay private to avoid a fallow dead-code flag for an export with no importer.SKIP_SUBTREE_TYPESis not used byresolveNodeTextitself — it is consumed by walkers that stay inbash-program.ts— but per the issue it moves intonode-text.tsand is imported back.createRequire(node:module) andmemoizeAsyncWithRetry(#src/async-cache) are used only by the parser block (grep-verified), so both imports become dead inbash-program.tsafter Cycle 1 and must be removed in the same commit.- Testability win: neither new module imports
#src/canonicalize-path, so their unit tests skip the canonicalize mock that any test transitively importingbash-program.tsneeds (retro 0345). - Doc/skill staleness enumerated:
docs/architecture/architecture.mdlayout tree +async-cache.tsline, and.pi/skills/package-pi-permission-system/SKILL.mdjiti note all name the parser's old home and need updating (Cycle 3). - Commit type is
refactor:(behavior-preserving). Flagged for the Step 3 ship decision:refactorishidden/non-bumping underrelease-please-config.json, so the all-refactor:batch "bash-program-decomposition" produces no release unless Step 3 carries afeat:/fix:commit. - Release marker: mid-batch — defer (batch "bash-program-decomposition", tail = Step 3 [#475]).
- Skipped the
ask-usergate: operator's own issue, unambiguous proposal with exact line targets and target paths.
Stage: Implementation — TDD (2026-06-25T11:23:00Z)
Session summary
Completed all three planned TDD cycles: extracted the tree-sitter parser block to src/access-intent/bash/parser.ts (Cycle 1), extracted the node-text resolver and SKIP_SUBTREE_TYPES to src/access-intent/bash/node-text.ts (Cycle 2), and updated docs/architecture/architecture.md plus .pi/skills/package-pi-permission-system/SKILL.md (Cycle 3).
bash-program.ts dropped from 1,143 → 1,045 LOC; test count rose from 2,069 (98 files) to 2,086 (100 files) with 17 new tests across 2 new files.
Observations
- Cycle 1 removed the
createRequireandmemoizeAsyncWithRetryimports frombash-program.tsin the same commit — confirmed dead by prior grep; the autoformatter'snoUnusedImportscheck validated the removal immediately. - The import-then-delete order (add new import, autoformat fires
noRedeclare, then remove old definitions) was the correct two-step sequence given howpi-autoformatruns after each edit; the intermediate lint error fromnoRedeclareresolved cleanly once the old block was removed. - Autoformatter reordered the new imports in
bash-program.tsalphabetically (node-textbeforeparser), which is fine — both use the#src/access-intent/bash/alias. SKIP_SUBTREE_TYPESinnode-text.tswas reformatted from a single-linenew Set([...])to a multi-line form by the autoformatter; content preserved, no behavior change.- Pre-completion reviewer: WARN (non-blocking).
- Reviewer warnings: (1) Mermaid diagram node
S1was missing✅— the heading carried it but AGENTS.md requires both; fixed by amending the docs commit; (2)node-text.test.tshad two BiomenoTemplateCurlyInStringwarnings for the intentional literal"${VAR}"strings — fixed with abiome-ignorecomment; both resolved before writing stage notes.
- Reviewer warnings: (1) Mermaid diagram node
bash-program.tsLOC fell 98 lines (1,143 → 1,045), slightly more than the plan's ~120 projection because the decorative// ── AST walker ──section header was also removed when the walker block emptied.- No deviations from the plan's Module-Level Changes list.
Stage: Final Retrospective (2026-06-25T15:35:54Z)
Session summary
Shipped Phase 6 Step 1 end-to-end in a single conversation spanning four stages (plan → TDD → ship → retro): a behavior-preserving lift-and-shift of the tree-sitter parser and node-text resolver into src/access-intent/bash/, seeding the package's first domain directory.
bash-program.ts dropped 1,143 → 1,045 LOC; +17 tests across 2 new files; CI green; release deferred per the mid-batch marker.
The execution was clean — the only reviewer findings were two minor doc/test-authoring gaps, both fixed before shipping.
Observations
What went well
- The plan's explicit "import-then-delete" sequencing plus grep-verified dead-import removal made Cycles 1 and 2 mechanical; the autoformatter's
noRedeclare/noUnusedImportschecks acted as an immediate correctness gate the moment the old block lingered. - The plan's Test Impact Analysis correctly predicted the testability win: neither new module pulls in
#src/canonicalize-path, sonode-text.test.tsruns in isolation without the canonicalize mock that anybash-program.tsimporter needs (retro 0345). - The pre-completion reviewer caught the Mermaid
✅gap that both planning and implementation missed — the fresh-context backstop worked exactly as designed. - Verification was incremental throughout:
pnpm run check+ per-filevitestafter each cycle, then full suite + lint +fallow dead-codebefore the reviewer. No end-only verification gap.
What caused friction (agent side)
instruction-violation(reviewer-caught) — the plan's Cycle 3 said "append✓ completeto the roadmap Step 1 heading line," missing the Mermaid diagram node and using the wrong marker (✓ completevs✅). Root cause: thepackage-pi-permission-systemskill (line 21) says "append✓ completeto the step line," which is inconsistent withtdd-plan.mdstep 7 ("prefix✅on both the step heading and its Mermaid diagram node"); planning followed the skill. Impact: one extra fix + a commit amend; no rework beyond that.other(edit construction) — the first Cycle 3 architecture-doc edit batch failed with "edits overlap" because it tried to flip thebash-token-classification.tstree connector (├──→└──) unnecessarily alongside thebash-program.tsdescription edit. Impact: one rejected batch + one re-read; corrected by dropping the spurious connector change.other(tool mechanics) — the Cycle 2 import-then-delete two-step surfaced intermediatenoRedeclare/noUnusedImportserrors after the import was added but before the old definitions were removed. Anticipated and handled, but it generated error noise mid-cycle. Impact: a few extra tool calls; inherent to howpi-autoformatruns after eachEdit.missing-context(minor) — planning used the wrong absolute path (/Users/chris/development/pi/pi-permission-system/..., droppingpi-packages/packages/) for oneread, hitting an external-directory denial; self-corrected on the next call. Impact: one wasted tool call.other(markdown-conventions) — the plan was first drafted with a bracketed[#473]self-reference (violating MD052/MD053); self-caught, but the corrective edit batch failed to match on the first try and took ~3 grep/read calls to reapply. Impact: ~4 extra tool calls, no content rework.
What caused friction (user side)
- None. The two user interjections ("Continue." and "Are we ready for ship-issue?") were lightweight oversight checkpoints, not corrections; the flow was largely autonomous and no earlier-context opportunity was missed.
Diagnostic details
- Model-performance correlation — Planning ran on
claude-opus-4-8(judgment-appropriate), TDD onclaude-sonnet-4-6(implementation-appropriate), and Ship onopencode-go/deepseek-v4-flash. The ship stage's stacked-release analysis (release-pleaseexclude-paths+ component-mapping reasoning) is judgment-heavy; the flash model spent 7 exploratorygrepcalls onrelease-please-config.jsonreaching a correct but meandering conclusion (the defer decision and stacked-release note were both accurate). Mild mismatch — a stronger model would have been more direct — but no rework resulted. - Escalation-delay tracking — no
rabbit-hole; no sequence exceeded 5 consecutive tool calls on the same error. The longest single-task run was the ship stacked-release investigation (7 grep calls), which was exploration, not stuck-on-an-error. - Unused-tool detection — no
missing-contextfriction warranted a subagent; the touched code was small and already understood from planning. - Feedback-loop gap analysis — none; verification was incremental after every cycle, not deferred to the end.
Changes made
.pi/skills/package-pi-permission-system/SKILL.md— de-duplicated the roadmap-completion instruction: removed the stale✓ complete-on-the-step-line restatement and pointed it at the canonical completion-marker convention in the implementation prompts (✅on both the step heading and its Mermaid diagram node), keeping only the package-specific "mark during shipping, do not defer" nuance. Root cause of the original reviewer WARN: the skill's wording conflicted withtdd-plan.mdstep 7, and planning followed the skill.packages/pi-permission-system/docs/retro/0473-extract-bash-parser-node-text.md— added this Final Retrospective stage entry.