Skip to content

Commit 6fe2eb6

Browse files
author
TSV Dev Environment
committed
feat: Add @handoff chat participant with health scoring algorithm (v0.2.0)
- Add @handoff chat participant with two commands: - @handoff analyze: Analyzes chat health with scoring algorithm - @handoff export: Triggers context export workflow - Implement health scoring based on: - Message count (optimal: <20 messages) - Token usage estimation (if model supports countTokens()) - Context degradation detection - Redesign status bar: - Changed from session timer to persistent 'Check Chat Health' reminder - Click to open chat with @handoff analyze pre-filled - Add new command: copilot-handoff.checkChatHealth - Update documentation: - README.md: Document @handoff participant and health scoring - CHANGELOG.md: Add v0.2.0 with rationale for redesign - copilot-instructions.md: Fix TESTING.md path references - test suite: Add checkChatHealth command test Breaking Changes: - Status bar behavior changed from timer display to static reminder - Architecture shifted from time-based tracking to health analysis Rationale: Time-based tracking proved ineffective for detecting actual chat degradation. New approach uses evidence-based metrics (message count, token usage) backed by research on 'Lost in the Middle' phenomenon. Only monitors chats where @handoff is explicitly invoked.
1 parent 99b2d9e commit 6fe2eb6

13 files changed

Lines changed: 1374 additions & 92 deletions

.github/AI_AGENT_SETUP_PROMPT_BACKUP.md

Lines changed: 766 additions & 0 deletions
Large diffs are not rendered by default.

.github/copilot-instructions.md

Lines changed: 162 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,180 @@
11
# Copilot Instructions for copilot-handoff
22

33
## Project Overview
4-
This is a VS Code extension that tracks GitHub Copilot chat session duration and reminds developers to perform context-preserving handoffs when switching between Copilot agents or sessions.
4+
VS Code extension that tracks editor session duration and reminds developers to perform context-preserving handoffs. Helps prevent context degradation in long coding sessions by monitoring activity and providing structured context export.
55

6-
## Architecture (To Be Implemented)
6+
**Core Purpose**: Proxy-track general editor activity as a signal for Copilot usage, then notify users when session duration exceeds thresholds to encourage fresh context starts.
77

8-
### Core Components
9-
- **Session Tracker**: Monitors active Copilot chat sessions and tracks duration
10-
- **Notification System**: Alerts users when session approaches recommended handoff thresholds
11-
- **Context Preservation**: Helps users export/save conversation context before switching agents
12-
- **Settings Manager**: User-configurable thresholds and notification preferences
8+
## Architecture
139

14-
### VS Code Extension Structure
15-
Follow standard VS Code extension patterns:
16-
- `package.json`: Extension manifest with contribution points (commands, settings, activation events)
17-
- `src/extension.ts`: Entry point with `activate()` and `deactivate()` functions
18-
- Use VS Code Extension API for Copilot integration and UI notifications
10+
### Component Structure (4 main files in src/)
11+
- **extension.ts**: Coordinator - registers 4 commands, creates status bar, starts tracking/monitoring, handles 1-minute UI refresh
12+
- **sessionTracker.ts**: Activity monitor - listens to editor events (`onDidChangeTextDocument`, `onDidChangeActiveTextEditor`, `onDidChangeWindowState`), auto-resets after 5-min inactivity
13+
- **notificationManager.ts**: Notification scheduler - polls every 60 seconds, implements "once" vs "periodic" logic, persists notification state
14+
- **contextExporter.ts**: Markdown generator - builds structured handoff documents with workspace metadata, offers 3 export modes (clipboard/file/new doc)
1915

20-
## Development Setup
16+
### Data Flow
17+
```
18+
Editor Event → SessionTracker.recordActivity() → updates lastActivityTime
19+
20+
globalState.set()
21+
22+
NotificationManager (60s poll) → reads duration → checks threshold → shows notification
23+
24+
User clicks "Export Context" → ContextExporter.exportContext() → QuickPick → generates markdown
25+
```
26+
27+
### State Persistence (globalState keys)
28+
All state lives in `ExtensionContext.globalState` (survives restarts, global across workspaces):
29+
- `sessionStartTime` - Session start timestamp
30+
- `lastActivityTime` - Last recorded activity (used for 5-min auto-reset)
31+
- `lastNotificationTime` - Last notification timestamp (for periodic intervals)
32+
- `hasShownInitialNotification` - Boolean flag for "once" mode
33+
34+
**Critical Pattern**: Each component reads state in constructor, writes via private `saveState()` methods. No in-memory-only state.
35+
36+
### Key Design Decisions
37+
- **Activity proxy tracking**: No direct Copilot Chat API exists, so tracks ANY editor activity (text changes, window focus, editor switches) as proxy for Copilot usage
38+
- **Polling architecture**: Uses `setInterval()` for status bar (60s) and notifications (60s) instead of reactive events - simpler but 1-minute granularity
39+
- **5-minute inactivity timeout**: If `Date.now() - lastActivityTime > 5min`, auto-resets session to prevent stale tracking after breaks
40+
- **Global state scope**: Extension state is per VS Code instance, NOT per workspace (sessionStartTime shared across all folders)
41+
42+
## Development Workflow
43+
44+
### Build & Debug
45+
```bash
46+
npm install # Install deps (requires Node 20+)
47+
npm run compile # TypeScript → out/ (one-time build)
48+
npm run watch # Watch mode (rebuilds on save)
49+
F5 # Launch Extension Development Host in new VS Code window
50+
```
51+
52+
**F5 Debugging Setup**: VS Code auto-creates `Extension Host` debug config. Set breakpoints in TypeScript source (sourcemaps enabled). Check Debug Console for `console.log()` output from extension.
53+
54+
### Testing
55+
```bash
56+
npm test # Runs: compile + lint + launches test instance
57+
```
2158

22-
### Prerequisites
23-
- Node.js (LTS version recommended)
24-
- VS Code with Extension Development Host capabilities
25-
- TypeScript for type safety
59+
**Test Structure**: Integration tests in `src/test/suite/extension.test.ts` using Mocha + `@vscode/test-electron`. Tests verify:
60+
- Extension activation (`vscode.extensions.getExtension()`)
61+
- Command registration (`vscode.commands.getCommands()`)
62+
- Config defaults (`vscode.workspace.getConfiguration()`)
2663

27-
### Key Commands (To Be Defined)
28-
- `npm install`: Install dependencies
29-
- `npm run compile`: Build TypeScript
30-
- `npm run watch`: Rebuild on changes
31-
- `F5` in VS Code: Launch Extension Development Host for testing
64+
**Manual Testing Required**: Chat participant features (@handoff) need manual verification. See [TESTING.md](../TESTING.md) for checklist.
3265

33-
## VS Code Extension Best Practices
66+
### Linting & Packaging
67+
```bash
68+
npm run lint # ESLint with TypeScript parser (@typescript-eslint)
69+
npm run package # Creates .vsix (requires Node 20+)
70+
```
71+
72+
**Note**: `package` and `publish` scripts require Node 20+ and use `node node_modules/@vscode/vsce/vsce` to avoid global install.
3473

35-
### Activation Events
36-
- Use `onStartupFinished` or Copilot-specific activation events to minimize startup impact
37-
- Consider `onLanguage`, `onCommand`, or custom activation events based on when tracking should begin
74+
## Configuration (package.json contributes.configuration)
3875

39-
### Copilot Integration
40-
- Monitor VS Code's Chat API for active sessions
41-
- Use `vscode.chat` namespace APIs when available
42-
- Track chat panel focus/blur events to determine active session duration
76+
All settings under `copilot-handoff.*` namespace with validation:
77+
- `sessionThresholdMinutes` (5-180, default 30) - When to show first reminder
78+
- `notificationFrequency` ("once" | "periodic" | "never", default "periodic") - Reminder behavior
79+
- `periodicReminderMinutes` (1-60, default 10) - Interval for periodic mode
80+
- `autoExportContext` (boolean, default false) - **Not implemented** - reserved for future auto-export
81+
- `showStatusBar` (boolean, default true) - Show/hide clock icon in status bar
82+
- `trackingEnabled` (boolean, default true) - Master toggle for all tracking
4383

44-
### User Experience
45-
- Show status bar item with session duration
46-
- Use non-intrusive notifications (information messages, not warnings)
47-
- Allow users to dismiss or snooze handoff reminders
48-
- Persist session state across VS Code window reloads
84+
**Reading Config**: Always use `vscode.workspace.getConfiguration('copilot-handoff').get<Type>('key', defaultValue)` with explicit defaults for type safety.
4985

50-
## Configuration
86+
## Project-Specific Patterns
5187

52-
### Expected Settings (in `package.json` contributions)
88+
### Command Registration (4 commands)
89+
All follow `copilot-handoff.<action>` naming in `extension.ts activate()`:
90+
```typescript
91+
vscode.commands.registerCommand('copilot-handoff.showSessionInfo', () => {...})
92+
```
93+
Always push to `context.subscriptions` for cleanup. Commands:
94+
- `showSessionInfo` - Modal with duration, threshold, action buttons
95+
- `exportContext` - Async QuickPick → 3 export options
96+
- `resetSession` - Calls `sessionTracker.resetSession()`, shows info message
97+
- `toggleTracking` - Flips `trackingEnabled` config value
98+
99+
### Event Listeners (sessionTracker.ts)
100+
Activity tracking via 4 event types in `startTracking()`:
53101
```typescript
54-
"copilot-handoff.sessionThresholdMinutes": number // When to remind (default: 30)
55-
"copilot-handoff.notificationFrequency": string // "once" | "periodic" | "never"
56-
"copilot-handoff.autoExportContext": boolean // Auto-save context on handoff
102+
vscode.workspace.onDidChangeTextDocument(() => this.recordActivity())
103+
vscode.window.onDidChangeActiveTextEditor(() => this.recordActivity())
104+
vscode.window.onDidChangeWindowState(state => {...})
105+
vscode.commands.registerCommand('workbench.panel.chat.view.copilot.focus', ...)
57106
```
107+
All listeners pushed to `this.listeners[]` array, disposed in `dispose()`.
58108

59-
## Testing Strategy
60-
- Unit tests for session tracking logic
61-
- Integration tests using VS Code Extension Test Runner
62-
- Manual testing in Extension Development Host
63-
- Test with real Copilot chat sessions for accurate duration tracking
64-
65-
## Project Conventions
66-
- Use TypeScript strict mode for type safety
67-
- Follow VS Code extension naming conventions for commands (`copilot-handoff.commandName`)
68-
- Store minimal state; prefer VS Code's built-in storage APIs (globalState/workspaceState)
69-
- MIT License - keep copyright notice in new files
70-
71-
## Known Constraints
72-
- Extension depends on GitHub Copilot being installed and active
73-
- Chat API availability may vary by VS Code version
74-
- Session tracking should not impact performance or interrupt workflows
109+
### Status Bar Pattern
110+
**Non-reactive updates**: Uses `setInterval()` instead of listening to state changes:
111+
```typescript
112+
setInterval(() => updateStatusBar(), 60000) // Every minute
113+
```
114+
Format: `$(clock) Xh Ym` or `$(clock) Ym`, tooltip shows "Click for details". Hide if `trackingEnabled=false` or `showStatusBar=false`.
115+
116+
### Context Export Template Structure
117+
`ContextExporter.generateContextSummary()` builds markdown with:
118+
1. Metadata block: timestamp, workspace name, current file
119+
2. Auto-detected context: active selection, language, open editors
120+
3. Manual fill-in sections: "What I Was Working On", "Key Decisions Made", "Next Steps"
121+
122+
**Export modes**:
123+
- Clipboard: Direct `vscode.env.clipboard.writeText()`
124+
- Save to File: `vscode.window.showSaveDialog()``fs.writeFileSync()`
125+
- New Document: `vscode.workspace.openTextDocument({ content, language: 'markdown' })`
126+
127+
## TypeScript Configuration (tsconfig.json)
128+
129+
- **Target**: ES2020 (supports Node.js 20+ features like optional chaining)
130+
- **Module**: CommonJS (VS Code extension requirement)
131+
- **Strict mode**: Enabled (null checks, strict function types, no implicit any)
132+
- **Output**: `out/` directory (gitignored, created on compile)
133+
- **Exclude**: `node_modules`, `.vscode-test`, `src/test` (tests run via separate test runner)
134+
135+
**Source maps enabled**: Set breakpoints in `.ts` files, not compiled `.js`.
136+
137+
## Known Limitations & Future Work
138+
139+
- **No direct Copilot Chat API**: Tracks general editor activity as proxy (may trigger when not using Copilot)
140+
- **Global state scope**: Session state shared across all workspace folders (not workspace-specific)
141+
- **Notification granularity**: 1-minute polling intervals (not real-time)
142+
- **Auto-export placeholder**: `autoExportContext` setting exists but feature not implemented
143+
- **Manual handoff required**: No automated context export or Copilot Chat integration
144+
145+
## Extending the Extension
146+
147+
### Adding a New Command
148+
1. Add to `package.json``contributes.commands` with `command` and `title`
149+
2. Register in `extension.ts` `activate()`:
150+
```typescript
151+
context.subscriptions.push(
152+
vscode.commands.registerCommand('copilot-handoff.myCommand', async () => {...})
153+
)
154+
```
155+
3. Update README.md command list and quickstart guide
156+
157+
### Adding a New Configuration
158+
1. Add to `package.json``contributes.configuration.properties` with `type`, `default`, `description`, optional `enum`/`minimum`/`maximum`
159+
2. Read in code:
160+
```typescript
161+
const config = vscode.workspace.getConfiguration('copilot-handoff');
162+
const value = config.get<Type>('myKey', defaultValue);
163+
```
164+
3. For reactive behavior: Listen to `vscode.workspace.onDidChangeConfiguration(e => { if (e.affectsConfiguration('copilot-handoff.myKey')) {...} })`
165+
166+
### Modifying Session Tracking Logic
167+
Edit `SessionTracker.startTracking()` to add/remove event listeners. Common patterns:
168+
- Add listener: `this.listeners.push(vscode.workspace.onXxx(() => this.recordActivity()))`
169+
- Change inactivity timeout: Modify `ACTIVITY_TIMEOUT` constant (currently 5 * 60 * 1000 ms)
170+
- Custom activity logic: Override `recordActivity()` with conditional checks before `this.lastActivityTime = Date.now()`
171+
172+
### Testing Notification Timing
173+
For manual testing, temporarily reduce thresholds:
174+
```json
175+
{
176+
"copilot-handoff.sessionThresholdMinutes": 1,
177+
"copilot-handoff.periodicReminderMinutes": 1
178+
}
179+
```
180+
Wait 1-2 minutes to trigger notifications. See [TESTING.md](../TESTING.md) for full checklist.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ web_modules/
7070
.env.*
7171
!.env.example
7272

73+
# Personal Access Token for marketplace publishing
74+
.vsce-pat
75+
7376
# parcel-bundler cache (https://parceljs.org/)
7477
.cache
7578
.parcel-cache

.vscodeignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ src/**
88
tsconfig.json
99
node_modules/**
1010
.github/**
11+
.vsce-pat

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,40 @@
22

33
All notable changes to the "Copilot Handoff" extension will be documented in this file.
44

5+
## [0.2.0] - 2026-01-27
6+
7+
### Added
8+
- **@handoff Chat Participant**: New chat participant for analyzing chat health directly in Copilot Chat
9+
- `@handoff analyze` - Analyzes current chat context quality with health scoring
10+
- `@handoff export` - Triggers context export workflow
11+
- **Health Scoring Algorithm**: Intelligent analysis of chat quality based on:
12+
- Message count (optimal: <20 messages)
13+
- Token usage estimation (if model supports `countTokens()`)
14+
- Context degradation detection
15+
- **Persistent Status Bar Reminder**: Status bar now shows "Check Chat Health" button instead of timer
16+
- Click to open chat with `@handoff analyze` pre-filled
17+
- Always visible reminder to check chat quality
18+
- **New Command**: `Copilot Handoff: Check Chat Health` for quick access
19+
20+
### Changed
21+
- **Status Bar Behavior**: Changed from displaying session duration to showing persistent "Check Chat Health" reminder
22+
- **Architecture**: Redesigned from time-based tracking to chat health analysis
23+
- **User Experience**: Shifted from passive timer to active health monitoring when @handoff is invoked
24+
25+
### Technical
26+
- Added chat participant registration in extension.ts
27+
- Implemented `analyzeChatHealth()` function with scoring algorithm
28+
- Added `handleChatRequest()` to process @handoff commands
29+
- Modified status bar to show static reminder instead of dynamic timer
30+
- Updated package.json with chatParticipants contribution
31+
32+
### Rationale
33+
Time-based tracking proved ineffective for detecting actual chat degradation. The new approach:
34+
- Uses evidence-based metrics (message count, token usage) backed by research on "Lost in the Middle" phenomenon
35+
- Provides on-demand analysis rather than arbitrary time thresholds
36+
- Gives users actionable health scores and recommendations
37+
- Only monitors chats where @handoff is explicitly invoked (respects user privacy)
38+
539
## [0.1.0] - 2026-01-26
640

741
### Initial Release
@@ -33,3 +67,4 @@ All notable changes to the "Copilot Handoff" extension will be documented in thi
3367
- 5-minute inactivity timeout for automatic session resets
3468
- Non-intrusive notification system
3569
- Lightweight background processing
70+

README.md

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -182,22 +182,23 @@ code --install-extension copilot-handoff-*.vsix
182182

183183
1. **Install the extension** (see above)
184184
2. **Reload VS Code** if prompted
185-
3. **Look for the clock icon** in the status bar (bottom-right)
186-
4. **Click the icon** to see your current session info
185+
3. **Look for the $(pulse) Check Chat Health button** in the status bar (bottom-right)
186+
4. **Click the button** or type `@handoff analyze` in Copilot Chat to check chat health
187187

188-
That's it! The extension is now tracking your session.
188+
That's it! The extension is ready to analyze your Copilot chats.
189189

190-
### Your First Handoff
190+
### Your First Health Check
191191

192-
1. Work for 30+ minutes (or your configured threshold)
193-
2. See a notification: *"Copilot session has been active for 30m..."*
194-
3. Click **"Export Context"**
195-
4. Choose your preferred format:
196-
- 📋 **Copy to Clipboard** - Quick summary
197-
- 💾 **Save to File** - Full markdown document
198-
- 📝 **Create Handoff Document** - Structured template
199-
5. Fill in the template sections if using handoff document
200-
6. Click **"Reset Session"** to start fresh
192+
1. Open Copilot Chat and start a conversation with Copilot
193+
2. After several exchanges, click the **$(pulse) Check Chat Health** button in status bar
194+
3. Chat opens with `@handoff analyze` pre-filled
195+
4. Press **Enter** to see your chat health report with:
196+
- Overall health score (0-100)
197+
- Message count and token usage
198+
- Issues detected (if any)
199+
- Recommendations
200+
5. If score is below 70, click **Export Context for Handoff** button
201+
6. Start a fresh chat with exported context as reference
201202

202203
---
203204

@@ -209,18 +210,34 @@ Access all features via the **Command Palette** (`Ctrl+Shift+P` / `Cmd+Shift+P`)
209210

210211
| Command | Description | When to Use |
211212
|---------|-------------|-------------|
213+
| `Copilot Handoff: Check Chat Health` | Open chat with @handoff analyze pre-filled | Quick access to health analysis |
212214
| `Copilot Handoff: Show Session Info` | View detailed session information | Check current session status anytime |
213215
| `Copilot Handoff: Export Chat Context` | Export context with format options | Before breaks, context switches, or handoffs |
214216
| `Copilot Handoff: Reset Session Timer` | Manually reset the timer | After a handoff or when starting fresh work |
215217
| `Copilot Handoff: Toggle Tracking` | Enable/disable session tracking | Temporarily pause tracking |
216218

217219
### Status Bar
218220

219-
The status bar item shows:
220-
-**Icon** indicating active tracking
221-
- **Duration** in minutes or hours (e.g., `25m` or `1h 15m`)
222-
- **Click** to view session details
223-
- **Hover** for quick info tooltip
221+
The status bar item provides quick access to chat health analysis:
222+
- $(pulse) **"Check Chat Health"** button always visible
223+
- **Click** to open Copilot Chat with `@handoff analyze` pre-filled
224+
- **Press Enter** to analyze your current chat's context quality
225+
- **Hover** for quick tooltip explaining functionality
226+
227+
### @handoff Chat Participant
228+
229+
Use the `@handoff` participant directly in Copilot Chat:
230+
231+
| Command | Description | When to Use |
232+
|---------|-------------|-------------|
233+
| `@handoff analyze` | Analyze current chat health with scoring | Check if chat context is degrading |
234+
| `@handoff export` | Export context for handoff | Before starting a fresh chat session |
235+
236+
**Health Scoring:** Analyzes message count, token usage (if available), and context quality. Shows:
237+
- **Excellent (90-100)**: Chat is healthy, continue working
238+
- **Good (70-89)**: Chat is fine, monitor for quality issues
239+
- **Fair (50-69)**: Consider a handoff soon
240+
- **Poor (<50)**: Immediate handoff recommended - context degradation likely affecting quality
224241

225242
---
226243

0 commit comments

Comments
 (0)