mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 16:45:22 +00:00
87 lines
7.5 KiB
Markdown
87 lines
7.5 KiB
Markdown
---
|
|
issue: 290
|
|
issue_title: "Reduce stripJsonComments complexity in config-loader.ts"
|
|
---
|
|
|
|
# Retro: #290 — Reduce stripJsonComments complexity in config-loader.ts
|
|
|
|
## Stage: Planning (2026-05-31T15:14:25Z)
|
|
|
|
### Session summary
|
|
|
|
Produced a numbered implementation plan to lower `stripJsonComments` cognitive complexity (31 → < 15) by replacing the five-flag single-loop scanner with a stateless dispatcher delegating to three private consume helpers (`consumeLineComment`, `consumeBlockComment`, `consumeString`), each returning a `ScanSegment` value.
|
|
The plan is behavior-preserving, adds direct unit tests for the already-exported `stripJsonComments`, and is structured as three TDD commits (`test:` pin contract → `refactor:` dispatcher → `docs:` architecture update).
|
|
|
|
### Observations
|
|
|
|
- Chose the issue's consume-helper option over the mode-discriminant step-function option: a `step(state, char)` function would mutate a shared state bag (output-argument smell) and re-encode the same five flags, so it relocates rather than removes the interleaving.
|
|
Each consume helper returns a value and owns one JSONC sub-grammar — genuine decomposition per the `code-design` heuristics.
|
|
Did not invoke `ask_user` — the choice is resolvable by project design principles and the change is small and reversible.
|
|
- `stripJsonComments` is `export`ed and consumed by both `config-loader.ts` (`loadUnifiedConfig`) and `policy-loader.ts`, but had no dedicated unit test — Step 1 pins its full contract directly before the refactor, so the new tests pass against today's implementation and act as the behavior-preservation net.
|
|
- No exports change and no symbol is renamed, so no `index.ts` barrel, package skill, or other doc needs updating — only `docs/architecture/architecture.md` (Phase 2 Step 5, findings row 5, worst-CRAP-risk line, metrics).
|
|
- `design-review` skill judged not applicable: the change is one self-contained pure function with no shared-interface or layer-wiring impact.
|
|
- Block-comment scan is planned to switch from a character loop to `indexOf("*/")` (behavior-identical, including the unterminated-to-EOF branch) — flagged as a risk with a dedicated test.
|
|
- markdownlint is not installed locally (`markdownlint-cli2` not found; no `.markdownlint*` config); relied on the `markdown-conventions` skill. `rumdl fmt` ran in the pre-commit hook and passed.
|
|
|
|
## Stage: Implementation — TDD (2026-05-31T15:23:14Z)
|
|
|
|
### Session summary
|
|
|
|
Completed all 3 TDD steps: pinned 14 direct unit tests for `stripJsonComments` (Step 1), replaced the five-flag scanner with the stateless dispatcher + three consume helpers (Step 2), and updated `docs/architecture/architecture.md` to mark Phase 2 Step 5 complete (Step 3).
|
|
Test count: 1614 → 1628 (+14).
|
|
A `style:` cleanup commit was added after the pre-completion review to fix helper ordering.
|
|
|
|
### Observations
|
|
|
|
- Step 1 required two assertion corrections: (1) the space before `//` is emitted verbatim, so the expected output was `'{ \n"k": 1}'` not `'{\n"k": 1}'`; (2) the combined JSONC round-trip test had a stray `,` after a stripped block comment rendering the output invalid JSON — restructured the document so comments are inline on value lines.
|
|
Both caught before the step 1 commit; the pre-existing implementation was never at fault.
|
|
- ESLint auto-fixed bracket notation to dot notation (`parsed["debugLog"]` → `parsed.debugLog`) during the pre-commit hook; accepted the change.
|
|
- The `refactor:` commit placed the three consume helpers *before* `stripJsonComments`, inverting the stepdown rule (plan said "placed directly below `stripJsonComments`").
|
|
The pre-completion reviewer flagged this as WARN; fixed in a `style:` commit (`4ff870a1`) after the review.
|
|
- `fallow health --targets` confirmed `config-loader.ts` / `stripJsonComments` no longer appears as a refactoring target after the refactor; architecture doc updated accordingly (targets 4 → 3).
|
|
- Pre-completion reviewer: **WARN** (one finding — stepdown order, resolved before final commit).
|
|
All deterministic checks PASS.
|
|
|
|
## Stage: Final Retrospective (2026-05-31T15:39:45Z)
|
|
|
|
### Session summary
|
|
|
|
Shipped issue #290 across three stages (plan → TDD → ship) with no logic rework: a behavior-preserving decomposition of `stripJsonComments` into a stateless dispatcher plus three pure consume helpers, with 14 new unit tests pinning the contract (1614 → 1628).
|
|
CI passed first try; no release-please PR (all commits were `test:`/`refactor:`/`style:`/`docs:`).
|
|
The single follow-up was a `style:` commit (`4ff870a1`) fixing helper ordering, prompted by the pre-completion reviewer's one WARN.
|
|
|
|
### Observations
|
|
|
|
#### What went well
|
|
|
|
1. The plan's design reasoning held up end-to-end.
|
|
The consume-helper approach (chosen over the mode-discriminant alternative) was behavior-preserving as predicted, and `fallow health --targets` confirmed `config-loader.ts` dropped off the refactoring-target list (4 → 3) exactly as the plan's Open Question anticipated.
|
|
2. Verification ran incrementally, not end-loaded.
|
|
Green baseline (`check`/`lint`/`test`) before any TDD cycle, each cycle ran the affected file red-then-green, and the full suite plus `check`/`lint`/`fallow dead-code` ran after the last step.
|
|
3. The two Step 1 test-assertion bugs were caught during the red phase, before the commit — the space-before-`//` preservation and the stray-comma invalid-JSON case were both fixed without touching committed code or the production implementation.
|
|
|
|
#### What caused friction (agent side)
|
|
|
|
1. `instruction-violation` (reviewer-caught) — the `refactor:` commit (`483be378`) placed the three consume helpers *above* `stripJsonComments`, inverting the stepdown rule.
|
|
The plan explicitly prescribed "placed directly below `stripJsonComments` per the stepdown rule," so the implementation had a written instruction and did not follow it.
|
|
Impact: one follow-up `style:` commit (`4ff870a1`), no logic rework, no user intervention.
|
|
This is the **second consecutive issue** with the identical friction: #289 fixed the same private-helper-before-export ordering in `style:` commit `55d2774a`, also reviewer-caught.
|
|
Both sessions wrote the extracted helper above its caller (a "define before use" instinct that JS/TS hoisting makes unnecessary) and relied on the pre-completion reviewer to catch the stepdown inversion.
|
|
|
|
#### What caused friction (user side)
|
|
|
|
1. None.
|
|
The design choice was resolvable from `code-design` principles, so no `ask_user` was warranted; the user's only involvement was launching each stage.
|
|
|
|
### Diagnostic details
|
|
|
|
- Model-performance correlation — the only subagent dispatch was the `pre-completion-reviewer` (pinned to `anthropic/claude-sonnet-4-6`, a valid registry alias); a judgment-heavy review on an appropriate model, no mismatch.
|
|
- Feedback-loop gap analysis — verification was incremental throughout; no end-loaded-verification flag.
|
|
- Escalation-delay and unused-tool lenses found nothing notable: the two Step 1 assertion bugs were each fixed in one edit, no sequence exceeded five tool calls on the same error, and no rabbit-holes or missing-context gaps arose that a subagent or `colgrep` would have prevented.
|
|
|
|
### Changes made
|
|
|
|
1. Appended this Final Retrospective stage entry to `packages/pi-permission-system/docs/retro/0290-decompose-strip-json-comments.md`.
|
|
2. Added a one-line note to the Stepdown rule in `.pi/skills/code-design/SKILL.md`: extracted helpers go *below* their caller, not above (hoisting makes "define before use" unnecessary).
|
|
This closes the recurring stepdown-order friction caught by the pre-completion reviewer in both #289 (`55d2774a`) and #290 (`4ff870a1`).
|