Skip to content

fix: Detect active epics via sub-issue activity - #21

Merged
rubambiza merged 2 commits into
rossoctl:mainfrom
rubambiza:fix/weekly-report-active-epics
Jul 8, 2026
Merged

fix: Detect active epics via sub-issue activity#21
rubambiza merged 2 commits into
rossoctl:mainfrom
rubambiza:fix/weekly-report-active-epics

Conversation

@rubambiza

Copy link
Copy Markdown
Contributor

Summary

Fixes the weekly report missing active epics. The team now parks active epics in an "Epics" board column rather than "In Progress", so the previous board-Status gate silently dropped them (or showed them as "no activity").

Detection is now sub-issue-based: an epic is active if it has open sub-issues (backlog / in-progress) or a sub-issue closed within the reporting window. This uses the plain REST sub_issues endpoint and needs no read:project scope; board Status becomes display-only enrichment when available.

Epics are ranked by recency of sub-issue closure, so a single bulk-close epic does not crowd out low-volume but freshly-active epics. The list is capped (configurable via --max-epics, default 10) to keep the section a focused planning input.

Verification

Against the last report window (--since 2026-06-22 --until 2026-06-29), all three epics cited in the issue now surface in the default top-10, ranked first by recency:

Epic This Week
#1789 3 sub-issues closed, 4 open
#1435 1 sub-issue closed, 2 open
#790 2 sub-issues closed, 1 open

#1789 previously showed "no activity". Verified in fallback mode (no read:project on the local token), which is exactly the path that must work.

Scope

Also registers the github-weekly-report skill in .claude-plugin/marketplace.json and the README Skills table — both were missing it.

Fixes #18

Assisted-By: Claude Code

@rubambiza rubambiza self-assigned this Jul 2, 2026
@rubambiza rubambiza added the ready-for-ai-review Request automated AI code review from clawgenti label Jul 2, 2026

@clawgenti clawgenti left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sub-issue-based detection is a clear improvement over the board-Status gate — epics parked in custom columns will no longer be silently dropped, and the recency ranking prevents a single bulk-close epic from crowding the list.

One suggestion on API efficiency, and a minor guard nit.


Reviewed by clawgenti using github:pr-review

'latest_closed_at': '', 'total': 0}
try:
base = ['gh', 'api', f'repos/{org}/{repo}/issues/{epic_number}/sub_issues', '--paginate']
open_res = subprocess.run(base + ['--jq', open_filter], capture_output=True, text=True, timeout=20)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: get_sub_issue_activity makes 4 separate paginated API calls to the same sub_issues endpoint (open count, closed numbers, latest closed_at, total). Each call fetches all pages independently, multiplying API usage by 4x per epic. Consider fetching once into a list and filtering locally — this also eliminates the edge where the 4 calls see different snapshots if sub-issues change mid-run.


# --paginate concatenates one result per page; sum the per-page ints.
def _sum_ints(text):
return sum(int(x) for x in text.split() if x.strip().lstrip('-').isdigit())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: x.strip().lstrip('-').isdigit() admits negative integers (e.g. -5 would pass and be summed). Since length always returns >= 0 this is harmless in practice, but the intent is to sum non-negative page counts. x.strip().isdigit() is cleaner and more accurately reflects the invariant.

rubambiza added 2 commits July 8, 2026 07:34
The weekly report gated epic inclusion on the project board Status
column, so epics parked in an "Epics" column (not "In Progress") were
dropped or shown as "no activity". Detection is now sub-issue-based: an
epic is active if it has open sub-issues or a sub-issue closed within
the reporting window. This uses the plain REST sub_issues endpoint and
needs no read:project scope; board Status becomes display-only.

Epics are ranked by recency of sub-issue closure so a single bulk-close
epic does not crowd out low-volume but freshly-active epics. Also
registers the github-weekly-report skill in marketplace.json and the
README, which were missing it.

Assisted-By: Claude Code (Anthropic AI) <noreply@anthropic.com>

Signed-off-by: Gloire Rubambiza <gloire@ibm.com>
Address PR review: get_sub_issue_activity made 4 separate paginated
calls to the same sub_issues endpoint (open, closed numbers, latest,
total), multiplying API usage 4x per epic and risking mid-run snapshot
skew. Fetch once, projecting only {number, state, closed_at} server-side
(keeps control-char safety for raw bodies), then filter locally via a
closed_in_window helper. Also drops the negative-admitting isdigit guard
the per-page summing needed.

Assisted-By: Claude Code (Anthropic AI) <noreply@anthropic.com>

Signed-off-by: Gloire Rubambiza <gloire@ibm.com>
@rubambiza
rubambiza force-pushed the fix/weekly-report-active-epics branch from 8d48c03 to 5b47246 Compare July 8, 2026 11:35
@rubambiza

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Addressed both in 5b47246:

  • 4x API calls: get_sub_issue_activity now makes a single --paginate call to the sub_issues endpoint, projecting only {number, state, closed_at} server-side, then filters locally. This keeps the control-char safety (raw sub-issue bodies never reach the client parser) while cutting API usage 4x per epic and eliminating the mid-run snapshot skew you noted.
  • isdigit negative guard: gone — with a single fetch there is no per-page integer summing, so the lstrip('-') helper is no longer needed. The in-window test is now a small closed_in_window helper shared by the closed-count and latest-closure logic.

Re-verified against the same window (--since 2026-06-22 --until 2026-06-29): identical ranking, the three cited epics still surface first by recency. Rebased onto current main.

Assisted-By: Claude Code

@rubambiza rubambiza added ready-for-human-review AI review passed, ready for human reviewer and removed ready-for-ai-review Request automated AI code review from clawgenti labels Jul 8, 2026

@cwiklik cwiklik left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Clean, well-documented refactor. Detection moves from board-status-gated to sub-issue-based (open sub-issues, in-window closures, or merged-PR cross-refs), so it no longer needs read:project. get_sub_issue_activity() uses a single paginated gh api call with server-side jq projection and filters locally — nice touch on avoiding both control-char parse breakage and the 4x API cost.

Correctness spot-checks all pass:

  • The mixed int/string sort tuple is type-consistent per position (no TypeError), and reverse=True ranking by latest_closed_at recency behaves as documented.
  • The ISO-8601 Z-suffixed lexical range check in closed_in_window is valid; null closed_at is correctly excluded.
  • Graceful degradation on non-zero exit / timeout / missing sub_issues endpoint (returns empty → epic simply uncounted).
  • Docs match code: --max-epics (SKILL.md) is implemented with default 10 and the cap is applied after the sort.

CI green (DCO + title check), both commits signed off. One non-blocking suggestion inline. LGTM.

Assisted-By: Claude Code

# An epic is active if it has open sub-issues (backlog / in-progress),
# a sub-issue closed this window, or a merged-PR cross-reference this
# window. Board Status is display-only enrichment — never a gate.
is_active = sub['open'] > 0 or sub['closed_recent'] > 0 or activity['prs_merged'] > 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (non-blocking): intentional behavior change worth a conscious confirm. The old fallback path included any epic updated_in_period, but is_active now requires open sub-issues, an in-window sub-issue closure, or a merged PR. An older-style epic tracked as a plain issue (no sub-issues feature) that only saw comment/label activity this week — with no merged PR — will now drop off the report. That matches the PR's stated intent of making sub-issues the primary signal, so no change needed if all active epics use sub-issues; just flagging it since the updated_in_period inclusion path is gone.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes ,that is the intended new behavior.

@rubambiza
rubambiza merged commit cce96b0 into rossoctl:main Jul 8, 2026
2 checks passed
@rubambiza
rubambiza deleted the fix/weekly-report-active-epics branch July 8, 2026 18:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human-review AI review passed, ready for human reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 Missing Active Epics from Weekly Report

3 participants