Project Info Panel v2 โ Grouped Sections with Rich Stats โ
Date: 2026-03-29 Status: Approved Scope: VS Code extension (tooling/vscode-extension/) Builds on: 2026-03-28-project-info-panel-design.md
Summary โ
Enhance the Project Info panel from a flat list of 5 items into a grouped, collapsible tree with 7 sections: Milestone, Issues, Pull Requests, CI Status, Branches, Activity, and Review Requests. Each group shows a summary in the collapsed description and expands to reveal detailed sub-items.
Motivation โ
The current panel shows milestone progress, branch, PR, and version. As the project grows, developers need visibility into issue/PR health, branch hygiene (stale and [gone] branches), and recent activity โ without leaving the editor or running CLI commands.
Design โ
Panel Structure โ
โผ Milestone: Prototype 11% (14/132)
Open: 118
Closed: 14
โผ Issues 118 open, 14 closed
Open: 118
Closed: 14
Unassigned: 96
โผ Pull Requests 13 open, 42 merged
Open: 13
Merged: 42
Closed (unmerged): 3
Draft: 2
โ Current: #302 โ Fix permission...
โผ CI Status โ passing
Latest: โ validate โ passed (2h ago)
Latest: โ deploy-preview โ passed (2h ago)
Latest: โ test-e2e โ failed (1h ago)
โผ Review Requests 2 awaiting review
#298 โ Add privacy policy waiting 3 days
#295 โ Refactor Discord bot waiting 5 days
โผ Branches 24 local / 18 remote
โ
Current: copilot/fix-permission...
Local: 24
Remote: 18
โ Gone (remote deleted): 5
Stale (30+ days): 3
โผ Activity 47 this week, 1,204 total
Commits (7d): 47
Commits (all time): 1,204
Contributors (7d): 3
Last commit: 2 hours ago
Version: 0.5.2
Last refreshed: 2 min agoGroup Details โ
Milestone (existing, now collapsible) โ
Same data source as v1 (gh api repos/{owner}/{repo}/milestones). The group label shows Milestone: {title} with {percent}% ({closed}/{total}) as the description. Expands to show open and closed counts. Clicking the group opens the milestone URL in the browser.
Issues โ
Summary description: {open} open, {closed} closed. Sub-items:
- Open โ count of open issues
- Closed โ count of closed issues
- Unassigned โ count of open issues with no assignee
Data source: gh api repos/{owner}/{repo}/issues?state=open&per_page=1 with response header Link for total count, or use the search API for counts:
gh api search/issues?q=repo:{owner}/{repo}+type:issue+state:openโtotal_countgh api search/issues?q=repo:{owner}/{repo}+type:issue+state:closedโtotal_countgh api search/issues?q=repo:{owner}/{repo}+type:issue+state:open+no:assigneeโtotal_count
Clicking the group opens the repo's issues page in the browser.
Pull Requests โ
Summary description: {open} open, {merged} merged. Sub-items:
- Open โ count of open PRs
- Merged โ count of merged PRs
- Closed (unmerged) โ count of PRs closed without merging
- Draft โ count of open draft PRs
- Current branch PR โ if a PR exists for the current branch, show
โ #N โ title(clickable to open PR URL)
Data source: GitHub search API for counts:
gh api search/issues?q=repo:{owner}/{repo}+type:pr+state:openโtotal_countgh api search/issues?q=repo:{owner}/{repo}+type:pr+is:mergedโtotal_countgh api search/issues?q=repo:{owner}/{repo}+type:pr+state:closed+-is:mergedโtotal_countgh api search/issues?q=repo:{owner}/{repo}+type:pr+state:open+draft:trueโtotal_count- Current branch PR: existing
fetchBranchPR()function
Clicking the group opens the repo's pull requests page in the browser.
CI Status โ
Summary description: โ passing, โ failing, or โ running based on the overall status of the latest workflow runs for the current branch. Sub-items show each workflow run:
- Per-workflow row โ
โ {name} โ passed ({time ago})orโ {name} โ failed ({time ago})
Data source: GitHub CLI:
gh run list --branch {branch} --limit 10 --json name,status,conclusion,createdAtโ latest runs per workflow
The overall summary is derived from the runs: if any run has conclusion: failure, show โ failing; if any is status: in_progress, show โ running; otherwise โ passing.
Clicking a sub-item opens the run's URL in the browser. Clicking the group opens the repo's Actions page filtered to the current branch.
Review Requests โ
Summary description: {count} awaiting review. Sub-items list each PR requesting your review:
- Per-PR row โ
#{number} โ {title}withwaiting {N} daysas description
Data source: GitHub Search API:
gh api search/issues?q=repo:{owner}/{repo}+type:pr+state:open+review-requested:@meโ returns PRs awaiting your review
Clicking a sub-item opens the PR URL in the browser. Clicking the group opens GitHub's review-requested filter page.
If the authenticated user has no pending reviews, the group shows 0 awaiting review with no sub-items.
Branches โ
Summary description: {local} local / {remote} remote. Sub-items:
- Current โ current branch name (from existing
getCurrentBranch()) - Local โ total local branch count
- Remote โ total remote tracking branch count
- Gone (remote deleted) โ branches where upstream is
[gone](candidates forclean_gone) - Stale (30+ days) โ local branches with no commits in last 30 days
Data source: All local git commands (no API calls):
git branch --listโ local countgit branch -r --listโ remote countgit branch -vvand filter for[gone]โ gone countgit for-each-ref --sort=-committerdate --format='%(refname:short) %(committerdate:unix)' refs/heads/โ stale detection
No click action on the group (no single URL to open).
Activity (7 days) โ
Summary description: {weekCommits} this week, {totalCommits} total. Sub-items:
- Commits (7d) โ commits in last 7 days across all branches
- Commits (all time) โ total commit count
- Contributors (7d) โ unique authors in last 7 days
- Last commit โ relative time since most recent commit
Data source: Local git commands:
git rev-list --count --since='7 days ago' --allโ 7-day commit countgit rev-list --count --allโ total commit countgit log --format='%ae' --since='7 days ago' --all | sort -uโ contributor countgit log -1 --format='%ci'โ last commit timestamp
No click action on the group.
Flat Items (bottom) โ
- Version โ from
readPackageJson()(unchanged) - Last refreshed โ relative timestamp (unchanged)
Tree Item Architecture โ
Replace the single InfoItem class with:
InfoGroupโ collapsible parent item (TreeItemCollapsibleState.Collapsed). Haslabel,description(summary),iconPath, optionalcommand(open URL), and stores its children.InfoItemโ leaf item (TreeItemCollapsibleState.None). Unchanged from current implementation.
The provider's getChildren(element) method:
- When
elementisundefinedโ return the top-level groups + flat items - When
elementis anInfoGroupโ return that group's children
Data Fetching โ
Split githubData.js into focused fetch functions:
| Function | Returns | Source |
|---|---|---|
fetchActiveMilestone(cwd) | milestone object | GitHub API (existing) |
fetchIssueCounts(cwd) | { open, closed, unassigned } | GitHub Search API |
fetchPRCounts(cwd) | { open, merged, closed, draft } | GitHub Search API |
fetchBranchPR(cwd, branch) | PR object or null | GitHub CLI (existing) |
fetchCIStatus(cwd, branch) | { overall, runs: [{ name, status, conclusion, url, createdAt }] } | GitHub CLI |
fetchReviewRequests(cwd) | [{ number, title, url, createdAt }] | GitHub Search API |
fetchBranchStats(cwd) | { current, local, remote, gone, stale } | Local git |
fetchActivityStats(cwd) | { weekCommits, totalCommits, contributors, lastCommit } | Local git |
All GitHub API calls use the existing execAsync wrapper with 10-second timeout. Failures return null and the group shows "unavailable".
Branch and activity stats use local git only โ no API calls, no auth required, always available.
Refresh Behavior โ
Same as v1:
- On activation: Full fetch of all data
- On branch change: Full refresh (piggybacks on existing 10-second polling)
- Manual: Refresh button in view title bar
- No periodic auto-refresh for GitHub data
All fetch functions run in parallel (Promise.all) during refresh to minimize wait time.
Error Handling โ
Same graceful degradation as v1. Each group independently handles fetch failures โ if issue counts fail but branch stats work, the Issues group shows "unavailable" while Branches works fine.
Files to Modify โ
src/lib/githubData.jsโ AddfetchIssueCounts(),fetchPRCounts(),fetchBranchStats(),fetchActivityStats()src/providers/ProjectInfoProvider.jsโ AddInfoGroupclass, refactorgetChildren()for parent/child tree, updaterefresh()to call all fetch functions
Files NOT Changed โ
package.jsonโ No new views, commands, or configuration neededsrc/extension.jsโ No changes, already wires up the provider correctly
What This Does NOT Include โ
- No click-to-cleanup for gone branches (future: could invoke
clean_goneskill) - No per-item refresh (whole panel refreshes together)
- No configuration for time windows (7 days is fixed)
- No milestone editing or switching