Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.extension.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Type `@aicoach` in any VS Code chat panel for conversational access to all coach
3. Use the sidebar to navigate pages. Filter by workspace or harness at the bottom.
4. Run **AI Engineer Coach: Reload Data** to re-parse after new sessions.
5. Type `@aicoach` in VS Code chat for conversational coaching.
6. Run **AI Engineer Coach: Export Full Context Pack** to save Safe or Full Raw Markdown/JSON context for ChatGPT or a VS Code coding agent.



Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ After install:
| **Learning Center** | Personalized quizzes and code-comparison rounds generated from your actual usage |
| **Achievements** | XP-based progression with Bronze → Silver → Gold → Diamond tiers |
| **Agentic SDLC** | How you use AI across the full software-development lifecycle |
| **Share** | Generate a shareable stat card and export Markdown/JSON summaries |
| **Share** | Generate a shareable stat card, compact summaries, and full agent context packs |

The command palette includes **AI Engineer Coach: Export Full Context Pack** for creating Markdown/JSON context packs tailored to ChatGPT or VS Code coding agents. Safe mode excludes raw prompt/response turns; Full Raw mode includes bounded raw session excerpts.

---

Expand Down
7 changes: 6 additions & 1 deletion docs/content/level-up/share.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@ The generated card includes:

## Export Options

Three actions are available:
Four actions are available:

- **Download PNG** -- Save the card as an image file
- **Copy to Clipboard** -- Copy the card image to your clipboard for pasting
- **Export Summary** -- Save a Markdown report and matching JSON data file for archiving or sharing
- **Refresh** -- Regenerate the card with current data

The command palette also includes **AI Engineer Coach: Export Full Context Pack**. This writes a deeper Markdown/JSON context pack for ChatGPT or a VS Code coding agent:

- **Safe Context Pack** -- Includes all analytical findings, anti-pattern details, context health, repeated workflow opportunities, and session metadata without raw prompt/response turns.
- **Full Raw Context Pack** -- Includes the Safe data plus bounded raw prompt/response excerpts from recent sessions.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"onCommand:aiEngineerCoach.open",
"onCommand:aiEngineerCoach.reload",
"onCommand:aiEngineerCoach.exportSummary",
"onCommand:aiEngineerCoach.exportContextPack",
"onCommand:aiEngineerCoach.reviewLocalRules",
"onView:aiEngineerCoach.welcome"
],
Expand All @@ -58,6 +59,11 @@
"title": "AI Engineer Coach: Export Summary",
"icon": "$(export)"
},
{
"command": "aiEngineerCoach.exportContextPack",
"title": "AI Engineer Coach: Export Full Context Pack",
"icon": "$(export)"
},
{
"command": "aiEngineerCoach.reviewLocalRules",
"title": "AI Engineer Coach: Review Local Rule Approvals",
Expand Down
199 changes: 198 additions & 1 deletion src/core/summary-export.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@
*--------------------------------------------------------------------------------------------*/

import { describe, expect, it } from 'vitest';
import { buildSummaryExport, renderSummaryMarkdown, renderSummaryJson, getSummaryExportFilenames } from './summary-export';
import {
buildSummaryExport,
renderSummaryMarkdown,
renderSummaryJson,
getSummaryExportFilenames,
buildContextPackExport,
buildContextPackExportFromAnalyzerAsync,
renderContextPackJson,
renderContextPackMarkdown,
getContextPackExportFilenames,
} from './summary-export';
import type {
AntiPatternData,
CodeProductionData,
Expand Down Expand Up @@ -173,3 +183,190 @@ describe('summary export', () => {
});
});
});

describe('context pack export', () => {
const rawSession = {
sessionId: 'session-1',
workspaceId: 'workspace-1',
workspaceName: 'Coach App',
location: 'local',
harness: 'Codex',
creationDate: Date.UTC(2026, 4, 20),
lastMessageDate: Date.UTC(2026, 4, 21),
requestCount: 1,
requests: [
{
requestId: 'request-1',
timestamp: Date.UTC(2026, 4, 20, 10),
messageText: `please fix this ${'without much context '.repeat(400)}`,
responseText: `I changed the implementation ${'and explained details '.repeat(400)}`,
isCanceled: false,
agentName: 'Codex',
agentMode: 'agent',
modelId: 'gpt-5-codex',
toolsUsed: ['apply_patch'],
editedFiles: ['src/core/summary-export.ts'],
referencedFiles: ['src/core/summary-export.test.ts'],
slashCommand: '',
variableKinds: {},
customInstructions: [],
skillsUsed: ['test-driven-development'],
firstProgress: 1000,
totalElapsed: 2000,
messageLength: 6000,
responseLength: 8000,
userCode: [],
aiCode: [{ language: 'typescript', loc: 12 }],
toolConfirmations: [],
promptTokens: 100,
completionTokens: 200,
cacheReadTokens: null,
cacheWriteTokens: null,
compaction: null,
todoSnapshot: null,
workType: 'bug fix',
},
],
};

const baseInput = {
generatedAt: '2026-05-25T10:00:00.000Z',
filter: { harness: 'Codex' },
stats,
codeProduction,
dailyActivity,
workLifeBalance,
flowState,
antiPatterns: {
...antiPatterns,
patterns: antiPatterns.patterns.map(pattern => ({
...pattern,
details: [
{
sessionId: 'session-1',
workspace: 'Coach App',
timestamp: Date.UTC(2026, 4, 20, 10),
message: 'please fix this',
model: 'gpt-5-codex',
},
],
})),
},
recommendations: [{ name: 'Prompt context', score: 62, status: 'needs-improvement' }],
contextManagement: { contextHealthScore: 70, antiPatterns: [] },
configHealth: { agenticReadiness: { score: 80, checklist: [] } },
workflowOptimization: { totalRepetitions: 4, clusters: [] },
sessionList: {
total: 1,
page: 1,
pageSize: 50,
sessions: [
{
sessionId: 'session-1',
workspaceName: 'Coach App',
workspaceId: 'workspace-1',
creationDate: Date.UTC(2026, 4, 20),
lastMessageDate: Date.UTC(2026, 4, 21),
requestCount: 1,
firstMessage: 'please fix this',
},
],
},
};

it('builds a safe context pack without raw session turns', () => {
const report = buildContextPackExport({
...baseInput,
mode: 'safe',
rawSessions: [rawSession],
});

expect(report.kind).toBe('context-pack');
expect(report.mode).toBe('safe');
expect(report.summary.totals.sessions).toBe(7);
expect(report.antiPatterns.patterns).toHaveLength(2);
expect(report.antiPatterns.patterns[0].details).toHaveLength(1);
expect(report.sessions?.total).toBe(1);
expect(report.rawSessions).toBeUndefined();
});

it('builds a full context pack with bounded raw session turns', () => {
const report = buildContextPackExport({
...baseInput,
mode: 'full',
rawSessions: [rawSession],
});

expect(report.rawSessions).toHaveLength(1);
expect(report.rawSessions?.[0]?.requests).toHaveLength(1);
expect(report.rawSessions?.[0]?.requests[0]?.prompt.length).toBeLessThanOrEqual(report.limits.textCharLimit + 20);
expect(report.rawSessions?.[0]?.requests[0]?.response.length).toBeLessThanOrEqual(report.limits.textCharLimit + 20);
expect(report.rawSessions?.[0]?.requests[0]?.toolsUsed).toEqual(['apply_patch']);
});

it('renders deterministic json, agent-focused markdown, and date-stamped filenames', () => {
const report = buildContextPackExport({
...baseInput,
mode: 'safe',
});

expect(JSON.parse(renderContextPackJson(report))).toEqual(report);

const markdown = renderContextPackMarkdown(report);
expect(markdown).toContain('# AI Engineer Coach Agent Context Pack');
expect(markdown).toContain('Mode: safe');
expect(markdown).toContain('## Agent Context Prompt');
expect(markdown).toContain('Low Context Prompts');
expect(markdown).toContain('Reference the relevant files and constraints.');

expect(getContextPackExportFilenames('2026-05-25T10:00:00.000Z')).toEqual({
markdown: 'ai-engineer-coach-context-pack-2026-05-25.md',
json: 'ai-engineer-coach-context-pack-2026-05-25.json',
});
});

it('loads raw full-mode sessions through an async session loader', async () => {
const strippedSession = {
...rawSession,
requests: rawSession.requests.map(request => ({
...request,
messageText: request.messageText.slice(0, 20),
responseText: '',
})),
};
const analyzer = {
getStats: () => stats,
getCodeProduction: () => codeProduction,
getDailyActivity: () => dailyActivity,
getWorkLifeBalance: () => workLifeBalance,
getFlowState: () => flowState,
getAntiPatterns: () => antiPatterns,
getSessions: () => baseInput.sessionList,
getSessionDetail: () => strippedSession,
};

const report = await buildContextPackExportFromAnalyzerAsync(
analyzer,
'full',
undefined,
'2026-05-25T10:00:00.000Z',
async sessionId => sessionId === rawSession.sessionId ? rawSession : null,
);

expect(report.rawSessions?.[0]?.requests[0]?.prompt).toContain('without much context');
expect(report.rawSessions?.[0]?.requests[0]?.response).toContain('I changed the implementation');
});

it('explains when full mode has no raw session excerpts available', () => {
const report = buildContextPackExport({
...baseInput,
mode: 'full',
rawSessions: [],
});

const markdown = renderContextPackMarkdown(report);

expect(markdown).toContain('Full mode was requested');
expect(markdown).toContain('raw prompt/response excerpts were not available');
});
});
Loading