vscode: Builders tree group-by-stage (action axis) with stage/area toggle (#952)#970
Merged
Conversation
…gates to active()
… prefix formatter
amrmelsayed
added a commit
that referenced
this pull request
Jun 3, 2026
amrmelsayed
added a commit
that referenced
this pull request
Jun 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PIR Review: Builders tree group-by-stage (action axis) with a stage/area toggle
Fixes #952
Summary
The VSCode Builders tree now groups by the builder's lifecycle stage (the action axis — "where do I need to act?") instead of its
area/*label, with the complementary axis shown as the row prefix. To serve reviewers who prefer the domain view, grouping is switchable via a title-bar toggle (codev.buildersGroupBy, defaultstage); area mode restores the originalarea/*grouping with a[<phase>]row prefix. Every protocol's phase ids fold into a closed 6-stage canonical set (SPECIFY → PLAN → IMPLEMENT → REVIEW → PR → VERIFIED, +UNKNOWN) so the tree is capped at a constant 7 groups regardless of how many protocols Codev adds. The two axes are expressed as aBuilderGroupingstrategy pair so the provider never branches on the mode.Preview
Group by Area
Group by Phase
Files Changed
packages/core/src/phase-grouping.ts(+137 / -0) — new:groupByStage,PHASE_TO_STAGE,STAGE_ORDER,BuilderStagepackages/core/package.json(+4 / -0) — export./phase-groupingpackages/vscode/src/views/builder-grouping.ts(+83 / -0) — new:BuilderGroupingstrategy interface +stageGrouping/areaGroupingpackages/vscode/src/views/builders.ts(+~70 / -~38) — provider delegates toactive()strategy; routing expansion wrapperpackages/vscode/src/views/builder-row.ts(+~16 / -~19) —builderRowLabelis now a pure prefix formatterpackages/vscode/src/views/area-group-expansion.ts(+~22 / -~10) — extractGroupExpansionStoreinterfacepackages/vscode/src/views/area-group-tree-item.ts(+~9 / -~9) — rename group-key fieldareaName→groupNamepackages/vscode/src/views/builder-tree-item.ts(+~14 / -~14) — axis-agnostic header; paramgroupNamepackages/vscode/src/views/backlog.ts(+1 / -1) — readelement.groupName(field rename only)packages/vscode/src/extension.ts(+19 / -0) —buildersGroupBycontext-key mirror + two toggle command handlerspackages/vscode/package.json(+33 / -0) —codev.buildersGroupBysetting, two commands, twoview/titlemenuspackages/vscode/src/__tests__/phase-grouping.test.ts(+123 / -0) — new:groupByStage/ mapping coveragepackages/vscode/src/__tests__/builder-grouping.test.ts(+83 / -0) — new: strategy coveragepackages/vscode/src/__tests__/builder-row.test.ts(~49 changed) — row label as pure formattercodev/plans/952-*.md,codev/reviews/952-*.md,codev/state/pir-952_thread.md— plan, this review, threadcodev/resources/lessons-learned.md— three lessons (see below)Commits
git log main..HEAD --oneline(implementation commits; porchchoretransition commits omitted):8bc591e0Add groupByStage core helper (closed canonical stage set)239f3e0bBuilders tree: group by lifecycle stage, area moves to row prefixcb3a26c0Tests: groupByStage coverage + area-prefix row labelb0e4feb5Extract GroupExpansionStore interface for per-mode routing0e42754cBuilders: dual-axis grouping (stage|area) with mode-aware row prefix98834bb4Add Builders group-by toggle (title-bar button + setting)6fe2eb89Tests: area-mode (phase-prefix) row label coveragedba2b667Refactor: BuilderGrouping strategy per axis, provider delegates to active()8fb6ed9eRename group-tree-item field areaName -> groupName (honest generic key)d0ba348bTests: BuilderGrouping strategies; builderRowLabel as pure prefix formatterc11aec05Use $(milestone) icon for the Group-by-Phase toggleTest Results
npm run build(porch check): ✓ passnpm test(porch check,@cluesmith/codevsuite): ✓ pass (3210 passed, 13 pre-existing skips)check-types: ✓ pass ·compile(esbuild + full-src eslint): ✓ passphase-grouping+builder-groupingsuites, reworkedbuilder-row)dev-approvalgate): ran the worktree; confirmed stage grouping, the title-bar toggle flipping both the grouping and the row prefix, per-mode collapse persistence, and Backlog unaffected.Architecture Updates
No
codev/resources/arch.mdchanges needed — this is a view-layer feature (Builders tree grouping) that introduces no new module boundary, service, or cross-package contract.arch.mdhas no Builders-tree-grouping section to amend, and per the arch-doc discipline a localized view feature doesn't belong there.Lessons Learned Updates
Three lessons added to
codev/resources/lessons-learned.md(UI/UX section), all tagged[From #952]:PHASE_TO_STAGE→ 6 stages) so the group count stays constant as the catalog grows, with a boundedunknowncatch-all.when-clauses (distinct icon per target), the VSCode built-in pattern; the single-buttontoggledproperty fits genuine on/off toggles, not a two-mode axis swap.active().Things to Look At During PR Review
PHASE_TO_STAGEmapping (phase-grouping.ts) — the design-sensitive part. Noteinvestigate → plan(architect-confirmed: pre-build diagnosis, right for BUGFIX) andverify/verified/complete → verified(in-progress verify merged with terminal). An unmapped future phase →unknown(bounded), so adding a protocol with a new phase is graceful but should add aPHASE_TO_STAGEentry to get a real bucket.pras a phase (→PRgroup); PIR/SPIR keeppras a gate on thereviewphase, so a PIR/SPIR builder awaiting merge sits underREVIEW, notPR. Intentional (faithful to each protocol's own phase model), not a bug.item.idpreserves the row's sub-state across the move. Watch the folded-destination edge (advancing into a collapsed stage hides the row until expanded).expansionrouting (builders.ts) —persistAreaGroupExpansioncaptures.expansiononce at registration, so the routing wrapper (delegating toactive().expansion) must be a stable object, not a getter. Per-axis stores use separateworkspaceStatekeys; area reuses the original key so pre-vscode: Builders tree should group by phase (action axis), not area (domain axis); area becomes the row prefix #952 collapse state survives.toggledsingle-button pattern applied to all toggles) was raised to the architect as a separatearea/vscodeitem, intentionally out of scope here.How to Test Locally
For reviewers pulling the branch:
afx dev pir-952SPECIFY → … → VERIFIED), empty stages hidden, counts accurate.[<area>] #<id> <title>; Uncategorized rows have no prefix.$(tag)(→area) in stage mode,$(milestone)(→phase) in area mode; clicking flips both the grouping and the row prefix ([area]↔[phase]).plan-approvalstays underPLANwith the warning-yellowchecklisticon.