Skip to content

Project Info Panel โ€” Interactive Actions & CI Failure Badges โ€‹

Date: 2026-03-29 Status: Approved Scope: VS Code extension (tooling/vscode-extension/) Builds on: 2026-03-29-project-info-panel-v2-design.md


Summary โ€‹

Add two capabilities to the Project Info panel: (1) interactive branch cleanup actions โ€” stale and gone branches expand to show individual branch names with delete buttons, plus a bulk cleanup Quick Pick; (2) CI failure badge on the Project Info view and a push notification to the Notifications panel when failures are detected.

Feature 1: Interactive Branch Actions โ€‹

Expandable Branch Lists โ€‹

The "Stale (30+ days)" and "Gone (remote deleted)" items become collapsible groups that expand to show individual branch names:

โ–ผ Branches                              24 local / 18 remote
    โ˜… Current: copilot/fix-permission...
    Local: 24
    Remote: 18
  โ–ผ โš  Gone (remote deleted)             5          [๐Ÿ—‘ Clean Up]
      copilot/old-feature                            [๐Ÿ—‘]
      fix/legacy-auth-bug                            [๐Ÿ—‘]
      copilot/stale-migration                        [๐Ÿ—‘]
      test/broken-experiment                         [๐Ÿ—‘]
      copilot/removed-upstream                       [๐Ÿ—‘]
  โ–ผ Stale (30+ days)                     3          [๐Ÿ—‘ Clean Up]
      copilot/early-prototype            45 days     [๐Ÿ—‘]
      fix/old-css-issue                  62 days     [๐Ÿ—‘]
      experiment/abandoned               90 days     [๐Ÿ—‘]

Individual Branch Actions โ€‹

Each branch sub-item has:

  • Label: branch name
  • Description: for stale branches, shows days since last commit (e.g., 45 days); for gone branches, no description needed
  • Inline delete button (trash icon) โ€” deletes that single branch after a confirmation dialog
  • contextValue: deletableBranch โ€” used to wire up the inline trash icon in package.json menus

Clicking the delete button shows a confirmation: Delete local branch "copilot/old-feature"? with [Delete] / [Cancel].

Deletion runs: git branch -D {branchName} (force delete since stale/gone branches may not be fully merged).

Bulk Cleanup Action โ€‹

Each parent group ("Gone" / "Stale") has an inline action button (trash icon) that opens a VSCode Quick Pick (multi-select) listing all branches in that category. The user checks which branches to delete, confirms, and they're all deleted.

Quick Pick flow:

  1. Title: "Delete stale branches (30+ days inactive)" or "Delete gone branches (remote deleted)"
  2. Items: each branch name, with description showing days since last commit (stale) or "remote deleted" (gone)
  3. canPickMany: true โ€” user selects multiple
  4. On confirm: delete each selected branch via git branch -D
  5. Show info message: "Deleted 3 branches."
  6. Trigger projectInfoProvider.refresh() to update counts

contextValue for Groups โ€‹

  • "Gone" parent group: contextValue: 'branchCleanupGone'
  • "Stale" parent group: contextValue: 'branchCleanupStale'
  • Individual branch items: contextValue: 'deletableBranch'

Data Source Changes โ€‹

fetchBranchStats currently returns counts only. It needs to also return the actual branch names:

  • gone: array of { name: string } (branch names with [gone] upstream)
  • stale: array of { name: string, daysAgo: number } (branch names with last commit > 30 days ago)

Updated return type:

{
  local: number,
  remote: number,
  goneBranches: Array<{ name: string }>,
  staleBranches: Array<{ name: string, daysAgo: number }>
}

The gone and stale counts are derived from the array lengths (no separate count needed).

Feature 2: CI Failure Badge & Notifications โ€‹

View Badge โ€‹

VSCode's TreeView API supports a badge property on the tree view object. When CI failures are detected, set the badge on the lanternControl.projectInfo tree view:

javascript
projectInfoView.badge = {
  value: failedCount,
  tooltip: `${failedCount} CI workflow${failedCount !== 1 ? 's' : ''} failing`
}

When no failures: projectInfoView.badge = undefined (removes the badge).

The badge appears as a number on the Project Info view's header in the sidebar. This requires storing the tree view reference returned by vscode.window.createTreeView() and passing it to the provider (or having the provider emit badge updates that extension.js listens to).

Badge Integration โ€‹

In extension.js, after projectInfoProvider.refresh() completes:

  1. Read projectInfoProvider.ciFailureCount (a new getter that returns the number of failing workflows, or 0)
  2. Update projectInfoView.badge accordingly

Since refresh is already triggered on activation and branch change, the badge updates automatically.

Notification Push โ€‹

When refresh() detects CI failures and the failure state is new (wasn't failing before), push a notification to the Notifications panel:

โš  CI: 2 workflows failing on copilot/fix-permission-error

This requires:

  • ProjectInfoProvider to accept the notificationsProvider as a constructor argument
  • Track previous CI state to detect transitions (passing โ†’ failing)
  • Only push on transition, not on every refresh (avoids notification spam)

The notification uses level 'error' and includes a click action that opens the GitHub Actions page for the branch:

javascript
{
  command: 'vscode.open',
  title: 'Open CI',
  arguments: [vscode.Uri.parse(`https://github.com/${repo}/actions?query=branch:${branch}`)]
}

State Transition Logic โ€‹

In refresh(), after fetching CI data:

wasFailing = this._ci?.overall === 'failing'
nowFailing = ci?.overall === 'failing'

if (nowFailing && !wasFailing) โ†’ push notification
if (nowFailing && wasFailing) โ†’ do nothing (already notified)
if (!nowFailing) โ†’ do nothing

This ensures the notification fires once per failure onset, not repeatedly.

New Commands โ€‹

CommandTitleIconContext
lanternControl.deleteBranchDelete Branch$(trash)viewItem == deletableBranch
lanternControl.cleanupGoneBranchesClean Up$(trash)viewItem == branchCleanupGone
lanternControl.cleanupStaleBranchesClean Up$(trash)viewItem == branchCleanupStale

Files to Modify โ€‹

  • src/lib/githubData.js โ€” Update fetchBranchStats to return branch name arrays instead of just counts
  • src/providers/ProjectInfoProvider.js โ€” Update Branches group to use nested InfoGroup for gone/stale with branch sub-items; add ciFailureCount getter; accept notificationsProvider in constructor; add CI transition detection in refresh()
  • src/extension.js โ€” Pass notificationsProvider to ProjectInfoProvider constructor; store tree view reference; update badge after refresh; register 3 new commands (deleteBranch, cleanupGoneBranches, cleanupStaleBranches)
  • package.json โ€” Add 3 new commands and their menu entries in view/item/context

What This Does NOT Include โ€‹

  • No automatic branch deletion (always requires user confirmation)
  • No remote branch deletion (only local branches)
  • No badge for anything other than CI failures
  • No toast/popup notifications (only badge + Notifications panel)

Built with VitePress