fix(roadmap): resolve Feature nesting under Milestone/Epic#207
Open
xRiErOS wants to merge 8 commits into
Open
Conversation
- Introduce featureGroup{Feature, Items} mirroring the existing
epicGroup pattern.
- Wire Features []featureGroup (omitempty) into milestoneGroup,
epicGroup, and unscheduledGroup so a later task can populate the
Milestone -> Epic -> Feature -> Leaf chain.
- Struct-only change; no behavior change yet (all Features fields are
nil/unused until Task 2/3 wire the resolution logic).
Refs: beans-ti53
…lpers - splitByContainerType separates direct children into leafs vs feature-typed - collectLeafDescendants recursively flattens leaf beans below a feature, transparently walking nested feature containers - collectLeafDescendantsVisited guards against hand-authored parent cycles in markdown (CLI-side validation can't catch manual edits) via a visited map Refs: beans-ti53
Epics/Milestones whose only open descendants sit below a Feature child were silently dropped from 'beans roadmap' output because buildMilestoneGroup only looked at direct children. Feature is now a recognized container type, resolved recursively via buildFeatureGroup. Refs: beans-ti53
Mutation-probe review (beans-d223) found the `|| len(group.Features) > 0` inclusion check in buildRoadmap was untested — every existing feature-nesting test also had an epic sibling under the milestone, so reverting the clause left all tests green. Add a milestone-with-only-a-feature-child case to close the gap. Refs: beans-ti53
…n features Refs: beans-ti53
Refs: beans-ti53
…ng it The feature-nesting fix (beans-en7i) treats every feature-typed bean as a container: it only renders via buildFeatureGroup when it has >=1 leaf descendant, and the orphan-items loop unconditionally skips Type==feature. A feature with zero children therefore vanished from `beans roadmap` entirely instead of falling back to a flat leaf line like it did before the nesting fix. Per D01 (PO decision, beans-n8zw): a feature is a container IFF collectLeafDescendants (respecting includeDone) returns >=1 item. Add classifyFeatureChild to resolve a feature child into either a featureGroup (>=1 descendant, existing behavior) or the feature bean itself as a leaf (0 descendants), applied consistently at all three sites: buildEpicGroup, buildMilestoneGroup, and the orphan-items loop in buildRoadmap. Childless leaves go through the same archive-status filter as any other leaf, so a completed/archived childless feature is still dropped under the default !includeDone view. Refs: beans-ti53 Refs: beans-n8zw
…fyFeatureChild Refs: beans-ti53 Refs: beans-xj5d
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.
Summary
beans roadmaponly walked one level of children per epic/milestone, so any bean parented under afeature(a documented, valid parent type — seepkg/bean/bean.go:159) never appeared in the output, and epics whose only open descendants sat below a feature vanished entirely.This PR makes
roadmapresolve the fullMilestone → Epic → Feature → Leafhierarchy:featureGroupto the roadmap data model (JSON + Markdown), resolved recursively via newcollectLeafDescendants/buildFeatureGroup/buildEpicGroup/classifyFeatureChildhelpers, applied uniformly to milestone-scoped, epic-scoped, unscheduled-epic and orphan-feature cases.#### Feature:section with its nested leaves. A childless feature still renders as a flat line — parity with the previous behavior, no visibility regression.mainbaseline binary). The JSON schema change is additive only —featuresfields areomitempty.collectLeafDescendantswith avisitedset so a hand-edited cyclicparent:chain can't stack-overflow roadmap generation (the CLI'sValidateParent/cycle detection already prevents this for tool-created data; beans are hand-editable markdown).Pre-existing scope limit, unchanged by this PR:
--status/--no-statusfilter milestone selection only; leaf/feature items are filtered by archive-status, never re-filtered by--status.Test plan
internal/commands/roadmap_test.gocovering: leaf under feature under epic under milestone; epic-dropped-if-only-feature-descendants regression; milestone-direct-feature inclusion line; unscheduled epic with feature nesting; orphan feature with children; childless feature renders flat under orphan / epic / milestone; feature with only-completed children edge; hand-edited parent-cycle safety; nested-orphan-feature double-render guard.go test ./...green.go vet ./...clean;gofmtclean on the changed file.mainbaseline → byte-identical (no template whitespace regression).