Skip to content

Add groupByTeamHierarchy: tree-shaped multi-level team-prefix grouping - #184

Open
shouze wants to merge 2 commits into
mainfrom
feat/team-hierarchy-model
Open

Add groupByTeamHierarchy: tree-shaped multi-level team-prefix grouping#184
shouze wants to merge 2 commits into
mainfrom
feat/team-hierarchy-model

Conversation

@shouze

@shouze shouze commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a pure, tree-shaped hierarchical grouping algorithm for team-prefix
grouping, laying the data-model foundation for the rest of the "Hierarchical
team-prefix grouping" EPIC (#125).

  • Added level? and children? to TeamSection (src/types.ts) so a
    section can either own repos directly (groups, a leaf) or be subdivided
    further (children).
  • Extracted the existing single-level bucket-by-count/bucket-by-combo logic
    out of groupByTeamPrefix into a shared bucketSingleLevel helper, with
    no behavior change to groupByTeamPrefix (all 36 pre-existing tests
    pass unchanged).
  • Added groupByTeamHierarchy(groups, chains): given one or more prefix
    chains (e.g. ["gamme-", "squad-"] for a 2-level chain), recursively
    sub-groups repos at each depth, with a per-level "other" bucket for
    repos that don't match the next prefix.
  • Added automatic nesting of overlapping team names within one level (e.g.
    gamme-lead-client becomes the parent of gamme-lead-client-p1) instead
    of listing them as unrelated siblings, cascading across chains of overlaps.

CLI parsing of the /-chain syntax, output rendering (markdown/JSON), TUI
rendering, and --pick-team support are intentionally out of scope here
and covered by the following sub-issues (#178-#182).

Closes #177

How to test

bun test src/group.test.ts

11 new tests cover: single-level parity with groupByTeamPrefix, 2-level and
3-level chains, per-level "other" buckets, multiple independent chains, and
overlapping team-name nesting (including a 3-way cascade).

Validation

  • bun test (882 pass)
  • bun run lint
  • bun run format:check
  • bun run knip
  • bun run build.ts

@shouze
shouze requested a lite review from Copilot August 23, 2026 20:26
@github-actions

Copy link
Copy Markdown

Coverage after merging feat/team-hierarchy-model into main will be

96.31%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   aggregate.ts100%100%100%100%
   api-utils.ts93.20%100%93.75%93.13%101–103, 65, 73, 86–87, 91–92
   api.ts94.74%100%100%94.07%340–344, 405, 422, 63–69
   cache.ts94.67%100%100%94.29%139–141, 39
   completions.ts99.42%100%100%99.37%270
   group.ts99.65%100%98.21%100%
   output.ts99.29%100%95.65%99.61%80
   regex.ts99.39%100%100%99.34%329
   render.ts89.82%100%88.24%89.89%172, 196–201, 203–205, 207–208, 229, 417–418, 442–444, 510–514, 526–527, 532–539, 541–549, 551–552
   scroll-cooldown.ts100%100%100%100%
   upgrade.ts88.38%100%94.44%87.89%128, 131, 133, 153, 167–168, 188–195, 198–204, 209, 214, 250–253
src/render
   filter-match.ts97.44%100%92.31%100%
   filter.ts100%100%100%100%
   highlight.ts96.63%100%90.40%99.31%284–285
   layout-constants.ts100%100%100%100%
   mouse-hit.ts100%100%100%100%
   mouse.ts100%100%100%100%
   rows.ts97.58%100%100%97.44%168, 54–55
   selection.ts100%100%100%100%
   summary.ts100%100%100%100%
   team-pick.ts100%100%100%100%
   terminal.ts100%100%100%100%

@shouze
shouze marked this pull request as ready for review August 23, 2026 20:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a new pure hierarchical team-prefix grouping algorithm (groupByTeamHierarchy) that produces a tree-shaped TeamSection model, providing the data-model foundation for EPIC #125’s multi-level team-prefix grouping work.

Changes:

  • Extended TeamSection to support hierarchy (level?, children?) alongside the existing flat grouping shape.
  • Extracted the existing single-level grouping logic into bucketSingleLevel() and reused it for both flat (groupByTeamPrefix) and hierarchical grouping.
  • Added groupByTeamHierarchy() plus new unit tests covering multi-level chains, per-level "other", multiple chains, and overlap nesting.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/types.ts Adds hierarchy fields (level, children) to TeamSection and updates its documentation.
src/group.ts Refactors single-level bucketing into a helper and adds the new hierarchical grouping implementation with overlap nesting.
src/group.test.ts Adds new unit tests covering the hierarchical grouping behavior.
Suppressed comments (1)

src/types.ts:78

  • The children field comment says it is present (non-empty) when subdivided, but the current implementation often sets children: [] on leaf nodes (including "other" and combined-label sections). Either the docs should allow empty arrays or the implementation should omit children when there are no children to traverse.
  /** Present (non-empty) when this section was subdivided further, either by
   *  the next prefix in the chain or by an auto-detected overlapping
   *  team-name relationship. Only set by `groupByTeamHierarchy`. */
  children?: TeamSection[];

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/types.ts Outdated
Comment thread src/group.ts
@github-actions

Copy link
Copy Markdown

Coverage after merging feat/team-hierarchy-model into main will be

96.32%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   aggregate.ts100%100%100%100%
   api-utils.ts93.20%100%93.75%93.13%101–103, 65, 73, 86–87, 91–92
   api.ts94.74%100%100%94.07%340–344, 405, 422, 63–69
   cache.ts94.67%100%100%94.29%139–141, 39
   completions.ts99.42%100%100%99.37%270
   group.ts99.66%100%98.25%100%
   output.ts99.29%100%95.65%99.61%80
   regex.ts99.39%100%100%99.34%329
   render.ts89.82%100%88.24%89.89%172, 196–201, 203–205, 207–208, 229, 417–418, 442–444, 510–514, 526–527, 532–539, 541–549, 551–552
   scroll-cooldown.ts100%100%100%100%
   upgrade.ts88.38%100%94.44%87.89%128, 131, 133, 153, 167–168, 188–195, 198–204, 209, 214, 250–253
src/render
   filter-match.ts97.44%100%92.31%100%
   filter.ts100%100%100%100%
   highlight.ts96.63%100%90.40%99.31%284–285
   layout-constants.ts100%100%100%100%
   mouse-hit.ts100%100%100%100%
   mouse.ts100%100%100%100%
   rows.ts97.58%100%100%97.44%168, 54–55
   selection.ts100%100%100%100%
   summary.ts100%100%100%100%
   team-pick.ts100%100%100%100%
   terminal.ts100%100%100%100%

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/group.ts:187

  • nestOverlappingLabels computes overlap parents with a nested loop over all labels (O(n²) comparisons per level). For orgs with many matching teams at a level, this can become a noticeable bottleneck in interactive mode. Consider switching to a sort+stack (prefix-chain) approach or a trie to find the longest-prefix parent in O(n log n) / O(total label length).
  for (const s of nestable) {
    let bestParent: string | undefined;
    for (const other of nestable) {
      if (other.label === s.label) continue;
      if (

Comment thread src/types.ts
shouze added a commit that referenced this pull request Aug 24, 2026
…ldren

Addresses Copilot review on PR #184:
- applyChainDepth no longer skips splitting a node's own groups by the
  next chain-level prefix just because it also has overlap-nested
  children (both can now coexist and each gets subdivided correctly).
- TeamSection docs updated: a node can have non-empty groups AND
  children at the same time (was previously documented as either/or).
- children is now omitted (not an empty array) on sections that were
  never subdivided, matching the documented invariant.
@shouze
shouze force-pushed the feat/team-hierarchy-model branch from 9e2dd78 to 847ac29 Compare August 24, 2026 00:10
@github-actions

Copy link
Copy Markdown

Coverage after merging feat/team-hierarchy-model into main will be

96.29%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   aggregate.ts100%100%100%100%
   api-utils.ts93.20%100%93.75%93.13%101–103, 65, 73, 86–87, 91–92
   api.ts94.74%100%100%94.07%340–344, 405, 422, 63–69
   cache.ts94.67%100%100%94.29%139–141, 39
   completions.ts99.42%100%100%99.37%270
   group.ts99.66%100%98.25%100%
   output.ts99.29%100%95.65%99.61%80
   regex.ts99.39%100%100%99.34%329
   render.ts89.70%100%88.24%89.76%176, 200–205, 207–209, 211–212, 233, 421–422, 446–448, 516–520, 532–533, 538–545, 547–555, 557–560
   scroll-cooldown.ts100%100%100%100%
   style.ts100%100%100%100%
   upgrade.ts88.38%100%94.44%87.89%128, 131, 133, 153, 167–168, 188–195, 198–204, 209, 214, 250–253
src/render
   filter-match.ts97.44%100%92.31%100%
   filter.ts100%100%100%100%
   highlight.ts96.63%100%90.40%99.31%284–285
   layout-constants.ts100%100%100%100%
   mouse-hit.ts100%100%100%100%
   mouse.ts100%100%100%100%
   rows.ts97.58%100%100%97.44%168, 54–55
   selection.ts100%100%100%100%
   summary.ts100%100%100%100%
   team-pick.ts100%100%100%100%
   terminal.ts100%100%100%100%

shouze added 2 commits August 24, 2026 02:10
…ldren

Addresses Copilot review on PR #184:
- applyChainDepth no longer skips splitting a node's own groups by the
  next chain-level prefix just because it also has overlap-nested
  children (both can now coexist and each gets subdivided correctly).
- TeamSection docs updated: a node can have non-empty groups AND
  children at the same time (was previously documented as either/or).
- children is now omitted (not an empty array) on sections that were
  never subdivided, matching the documented invariant.
@shouze
shouze force-pushed the feat/team-hierarchy-model branch from 847ac29 to 47377b1 Compare August 24, 2026 00:14
@github-actions

Copy link
Copy Markdown

Coverage after merging feat/team-hierarchy-model into main will be

96.29%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   aggregate.ts100%100%100%100%
   api-utils.ts93.20%100%93.75%93.13%101–103, 65, 73, 86–87, 91–92
   api.ts94.74%100%100%94.07%340–344, 405, 422, 63–69
   cache.ts94.67%100%100%94.29%139–141, 39
   completions.ts99.42%100%100%99.37%270
   group.ts99.66%100%98.25%100%
   output.ts99.29%100%95.65%99.61%80
   regex.ts99.39%100%100%99.34%329
   render.ts89.70%100%88.24%89.76%176, 200–205, 207–209, 211–212, 233, 421–422, 446–448, 516–520, 532–533, 538–545, 547–555, 557–560
   scroll-cooldown.ts100%100%100%100%
   style.ts100%100%100%100%
   upgrade.ts88.38%100%94.44%87.89%128, 131, 133, 153, 167–168, 188–195, 198–204, 209, 214, 250–253
src/render
   filter-match.ts97.44%100%92.31%100%
   filter.ts100%100%100%100%
   highlight.ts96.63%100%90.40%99.31%284–285
   layout-constants.ts100%100%100%100%
   mouse-hit.ts100%100%100%100%
   mouse.ts100%100%100%100%
   rows.ts97.58%100%100%97.44%168, 54–55
   selection.ts100%100%100%100%
   summary.ts100%100%100%100%
   team-pick.ts100%100%100%100%
   terminal.ts100%100%100%100%

@shouze shouze self-assigned this Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants