Skip to content

[1/7] Data model & core hierarchical grouping algorithm #177

Description

@shouze

Context

groupByTeamPrefix() in src/group.ts is flat and single-level: each prefix in the comma-separated --group-by-team-prefix list is processed sequentially against the remaining repo pool, producing a flat TeamSection[] ({ label, groups }) always ending with an "other" section. TeamSection in src/types.ts has no concept of depth or nesting. This is the foundation every other sub-issue in this EPIC builds on.

Part of EPIC #125.

Solution

  • Redesign TeamSection (src/types.ts) into a tree node, e.g. { label, groups, level, children?: TeamSection[] } (exact shape decided during implementation; keep RepoGroup/sectionLabel round-trip compatible with downstream flatten/rebuild helpers).
  • Add a new grouping entry point in src/group.ts (e.g. groupByTeamHierarchy(groups, chains)) that takes an already-structured input (array of prefix chains, each chain an array of prefix strings representing one level per depth - CLI string parsing itself is issue [6/7]'s responsibility, not this one).
  • Recursively apply the existing single-level bucket-by-count / bucket-by-combo logic (currently inlined in groupByTeamPrefix) at each depth, scoped to the parent level's group.
  • Detect team-name prefix-of relationships among the teams matching a given level (e.g. gamme-lead-client is a prefix of gamme-lead-client-p1) and nest the latter under the former automatically, instead of listing them as unrelated siblings at the same depth.
  • Decide whether groupByTeamPrefix is kept as a degenerate 1-level case or fully replaced; document the decision in the PR (backward compatibility is not required here per EPIC scope).

Example tree shape

graph TD
    R1["gamme-lead-client (level 1)"] --> N1["gamme-lead-client-p1 (nested, same level, auto-detected overlap)"]
    R1 --> N2["squad-dashboard (level 2, chain gamme-/squad-)"]
    R2["gamme-client (level 1)"] --> N3["squad-frontend (level 2)"]
    N3 --> N4["other (level 3, no chapter- match at that node)"]
    R3["chapter-backend (level 1, independent chain)"]
Loading

Acceptance Criteria

  • A 2-level chain (e.g. ["gamme-", "squad-"]) groups repos first by gamme- matches, then sub-groups each resulting bucket by squad- matches.
  • A 3-level chain behaves the same way recursively.
  • Repos matching no prefix at a given level fall into an "other" node at that depth (mirroring today's behavior).
  • Team names that overlap within one level are nested automatically (gamme-lead-client parent, gamme-lead-client-p1 child).
  • Multiple independent prefix chains (comma-separated) are each grouped independently, same as today's multi-prefix behavior.
  • Function is pure (no I/O), matching the codebase's architectural rule.

Definition of Done

  • Full unit test coverage added to src/group.test.ts: 2-level, 3-level, overlapping-name nesting, empty/no-match edge cases.
  • bun test, bun run lint, bun run format:check, bun run knip, bun run build.ts all green.
  • No CLI or rendering wiring in this PR (that's issues 2-6) - this issue only ships the pure data model + algorithm.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions