@pcircle/claude-code-buddy-mcp 2.3.10 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/HookIntegration.d.ts +5 -1
- package/dist/core/HookIntegration.d.ts.map +1 -1
- package/dist/core/HookIntegration.js +73 -46
- package/dist/core/HookIntegration.js.map +1 -1
- package/dist/core/TestOutputParser.d.ts +20 -0
- package/dist/core/TestOutputParser.d.ts.map +1 -0
- package/dist/core/TestOutputParser.js +144 -0
- package/dist/core/TestOutputParser.js.map +1 -0
- package/dist/mcp/resources/best-practices.md +67 -0
- package/dist/mcp/resources/examples.md +56 -0
- package/dist/mcp/resources/quick-reference.md +73 -0
- package/dist/mcp/resources/usage-guide.md +92 -0
- package/dist/memory/ProjectAutoTracker.d.ts +13 -0
- package/dist/memory/ProjectAutoTracker.d.ts.map +1 -1
- package/dist/memory/ProjectAutoTracker.js +89 -5
- package/dist/memory/ProjectAutoTracker.js.map +1 -1
- package/package.json +3 -2
- package/plugin.json +1 -1
- package/dist/__benchmarks__/performance-fixes.bench.d.ts +0 -8
- package/dist/__benchmarks__/performance-fixes.bench.d.ts.map +0 -1
- package/dist/__benchmarks__/performance-fixes.bench.js +0 -213
- package/dist/__benchmarks__/performance-fixes.bench.js.map +0 -1
- package/dist/core/BackgroundExecutorConstants.d.ts +0 -8
- package/dist/core/BackgroundExecutorConstants.d.ts.map +0 -1
- package/dist/core/BackgroundExecutorConstants.js +0 -8
- package/dist/core/BackgroundExecutorConstants.js.map +0 -1
- package/dist/evolution/LearningManagerConstants.d.ts +0 -55
- package/dist/evolution/LearningManagerConstants.d.ts.map +0 -1
- package/dist/evolution/LearningManagerConstants.js +0 -55
- package/dist/evolution/LearningManagerConstants.js.map +0 -1
- package/dist/evolution/PerformanceTrackerConstants.d.ts +0 -5
- package/dist/evolution/PerformanceTrackerConstants.d.ts.map +0 -1
- package/dist/evolution/PerformanceTrackerConstants.js +0 -5
- package/dist/evolution/PerformanceTrackerConstants.js.map +0 -1
- package/dist/orchestrator/GlobalResourcePoolConstants.d.ts +0 -22
- package/dist/orchestrator/GlobalResourcePoolConstants.d.ts.map +0 -1
- package/dist/orchestrator/GlobalResourcePoolConstants.js +0 -22
- package/dist/orchestrator/GlobalResourcePoolConstants.js.map +0 -1
- package/dist/orchestrator/TaskAnalyzerConstants.d.ts +0 -16
- package/dist/orchestrator/TaskAnalyzerConstants.d.ts.map +0 -1
- package/dist/orchestrator/TaskAnalyzerConstants.js +0 -16
- package/dist/orchestrator/TaskAnalyzerConstants.js.map +0 -1
- package/dist/templates/git-education-templates.d.ts +0 -26
- package/dist/templates/git-education-templates.d.ts.map +0 -1
- package/dist/templates/git-education-templates.js +0 -455
- package/dist/templates/git-education-templates.js.map +0 -1
- package/dist/utils/SecureKeyStore.d.ts +0 -10
- package/dist/utils/SecureKeyStore.d.ts.map +0 -1
- package/dist/utils/SecureKeyStore.js +0 -32
- package/dist/utils/SecureKeyStore.js.map +0 -1
- package/dist/utils/cost-tracker.d.ts +0 -34
- package/dist/utils/cost-tracker.d.ts.map +0 -1
- package/dist/utils/cost-tracker.js +0 -92
- package/dist/utils/cost-tracker.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -7
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -62
- package/dist/utils/validation.js.map +0 -1
|
@@ -24,22 +24,26 @@ export declare class HookIntegration {
|
|
|
24
24
|
private triggerCallbacks;
|
|
25
25
|
private projectMemory?;
|
|
26
26
|
private lastCheckpoint?;
|
|
27
|
+
private testParser;
|
|
27
28
|
constructor(checkpointDetector: CheckpointDetector, developmentButler: DevelopmentButler);
|
|
28
29
|
initializeProjectMemory(mcp: MCPToolInterface): void;
|
|
29
30
|
detectCheckpointFromToolUse(toolData: ToolUseData): Promise<Checkpoint | null>;
|
|
30
31
|
processToolUse(toolData: ToolUseData): Promise<void>;
|
|
31
32
|
private recordToProjectMemory;
|
|
33
|
+
private static readonly TRACKED_PHASES;
|
|
32
34
|
private recordCheckpointProgress;
|
|
33
35
|
private buildCheckpointDetails;
|
|
34
36
|
private ensureProjectMemoryInitialized;
|
|
35
37
|
onButlerTrigger(callback: (context: CheckpointContext) => void): void;
|
|
38
|
+
private static readonly TEST_FILE_PATTERNS;
|
|
39
|
+
private static readonly TEST_COMMAND_PATTERNS;
|
|
36
40
|
private isTestFile;
|
|
37
41
|
private isTestCommand;
|
|
38
42
|
private isGitAddCommand;
|
|
39
43
|
private isGitCommitCommand;
|
|
40
44
|
private extractGitCommitMessage;
|
|
41
45
|
private findGitCommitSegment;
|
|
42
|
-
private
|
|
46
|
+
private isValidTestResults;
|
|
43
47
|
}
|
|
44
48
|
export {};
|
|
45
49
|
//# sourceMappingURL=HookIntegration.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HookIntegration.d.ts","sourceRoot":"","sources":["../../src/core/HookIntegration.ts"],"names":[],"mappings":"AAoDA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"HookIntegration.d.ts","sourceRoot":"","sources":["../../src/core/HookIntegration.ts"],"names":[],"mappings":"AAoDA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAyC9D,MAAM,WAAW,WAAW;IAE1B,QAAQ,EAAE,MAAM,CAAC;IAGjB,SAAS,CAAC,EAAE,OAAO,CAAC;IAGpB,OAAO,EAAE,OAAO,CAAC;IAGjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA+DD,UAAU,UAAU;IAElB,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAsBD,MAAM,WAAW,iBAAiB;IAEhC,UAAU,EAAE,MAAM,CAAC;IAGnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAG9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAsCD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,gBAAgB,CAAmD;IAC3E,OAAO,CAAC,aAAa,CAAC,CAAqB;IAC3C,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,UAAU,CAAmB;gBAoBnC,kBAAkB,EAAE,kBAAkB,EACtC,iBAAiB,EAAE,iBAAiB;IAyCtC,uBAAuB,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAmE9C,2BAA2B,CAC/B,QAAQ,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAkIvB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;YA0E5C,qBAAqB;IAyDnC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAA2E;YAKnG,wBAAwB;IAoCtC,OAAO,CAAC,sBAAsB;IAyC9B,OAAO,CAAC,8BAA8B;IA4DtC,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAKrE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAmC;IAG7E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAA2D;IAQxG,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,uBAAuB;IAoB/B,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,kBAAkB;CAoB3B"}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { ProjectAutoTracker } from '../memory/ProjectAutoTracker.js';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
import { TestOutputParser } from './TestOutputParser.js';
|
|
2
4
|
export class HookIntegration {
|
|
3
5
|
detector;
|
|
4
6
|
butler;
|
|
5
7
|
triggerCallbacks = [];
|
|
6
8
|
projectMemory;
|
|
7
9
|
lastCheckpoint;
|
|
10
|
+
testParser;
|
|
8
11
|
constructor(checkpointDetector, developmentButler) {
|
|
9
12
|
this.detector = checkpointDetector;
|
|
10
13
|
this.butler = developmentButler;
|
|
14
|
+
this.testParser = new TestOutputParser();
|
|
11
15
|
}
|
|
12
16
|
initializeProjectMemory(mcp) {
|
|
13
17
|
if (this.projectMemory) {
|
|
@@ -20,6 +24,9 @@ export class HookIntegration {
|
|
|
20
24
|
return null;
|
|
21
25
|
}
|
|
22
26
|
const { toolName, arguments: args } = toolData;
|
|
27
|
+
if (!args || typeof args !== 'object') {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
23
30
|
if (toolName === 'Write') {
|
|
24
31
|
const fileArgs = args;
|
|
25
32
|
return {
|
|
@@ -54,7 +61,7 @@ export class HookIntegration {
|
|
|
54
61
|
};
|
|
55
62
|
}
|
|
56
63
|
if (this.isTestCommand(bashArgs.command)) {
|
|
57
|
-
const testResults = this.
|
|
64
|
+
const testResults = this.testParser.parse(toolData.output || '');
|
|
58
65
|
return {
|
|
59
66
|
name: 'test-complete',
|
|
60
67
|
data: testResults,
|
|
@@ -104,32 +111,48 @@ export class HookIntegration {
|
|
|
104
111
|
await fileChangeHook(files, `Code ${type}`);
|
|
105
112
|
}
|
|
106
113
|
if (checkpoint.name === 'test-complete') {
|
|
114
|
+
if (!this.isValidTestResults(checkpoint.data)) {
|
|
115
|
+
logger.warn('Invalid test results data structure, skipping memory record', {
|
|
116
|
+
checkpoint: checkpoint.name,
|
|
117
|
+
data: checkpoint.data,
|
|
118
|
+
});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
107
121
|
const testResultHook = this.projectMemory.createTestResultHook();
|
|
108
|
-
const
|
|
122
|
+
const testResults = checkpoint.data;
|
|
123
|
+
const { total, passed, failed, failedTests } = testResults;
|
|
124
|
+
const failures = failedTests.map(test => {
|
|
125
|
+
const parts = [];
|
|
126
|
+
if (test.file) {
|
|
127
|
+
parts.push(`${test.file}:`);
|
|
128
|
+
}
|
|
129
|
+
parts.push(test.name);
|
|
130
|
+
if (test.error) {
|
|
131
|
+
parts.push(`- ${test.error}`);
|
|
132
|
+
}
|
|
133
|
+
return parts.join(' ');
|
|
134
|
+
});
|
|
109
135
|
await testResultHook({
|
|
110
136
|
total,
|
|
111
137
|
passed,
|
|
112
138
|
failed,
|
|
113
|
-
failures
|
|
139
|
+
failures,
|
|
114
140
|
});
|
|
115
141
|
}
|
|
116
142
|
}
|
|
143
|
+
static TRACKED_PHASES = new Set(['code-written', 'test-complete', 'commit-ready', 'committed']);
|
|
117
144
|
async recordCheckpointProgress(checkpoint, toolData) {
|
|
118
|
-
if (!this.projectMemory) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
const trackedPhases = new Set(['code-written', 'test-complete', 'commit-ready', 'committed']);
|
|
122
|
-
if (!trackedPhases.has(checkpoint.name)) {
|
|
145
|
+
if (!this.projectMemory || !HookIntegration.TRACKED_PHASES.has(checkpoint.name)) {
|
|
123
146
|
return;
|
|
124
147
|
}
|
|
125
148
|
if (checkpoint.name !== 'code-written' && checkpoint.name !== 'committed') {
|
|
126
149
|
await this.projectMemory.flushPendingCodeChanges(checkpoint.name);
|
|
127
150
|
}
|
|
128
151
|
if (checkpoint.name === 'committed') {
|
|
129
|
-
const
|
|
152
|
+
const { command, message } = checkpoint.data;
|
|
130
153
|
await this.projectMemory.recordCommit({
|
|
131
|
-
command
|
|
132
|
-
message:
|
|
154
|
+
command,
|
|
155
|
+
message: message ?? undefined,
|
|
133
156
|
output: toolData.output,
|
|
134
157
|
});
|
|
135
158
|
}
|
|
@@ -142,29 +165,32 @@ export class HookIntegration {
|
|
|
142
165
|
}
|
|
143
166
|
buildCheckpointDetails(checkpoint, toolData) {
|
|
144
167
|
const details = [`Trigger: ${toolData.toolName}`];
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (total > 0) {
|
|
152
|
-
details.push(`Tests: ${passed}/${total} passed`);
|
|
168
|
+
const data = checkpoint.data;
|
|
169
|
+
switch (checkpoint.name) {
|
|
170
|
+
case 'code-written': {
|
|
171
|
+
const files = data.files ?? [];
|
|
172
|
+
details.push(`Files changed: ${files.length}`);
|
|
173
|
+
break;
|
|
153
174
|
}
|
|
154
|
-
|
|
155
|
-
|
|
175
|
+
case 'test-complete': {
|
|
176
|
+
const { total, passed, failed } = data;
|
|
177
|
+
if (total > 0)
|
|
178
|
+
details.push(`Tests: ${passed}/${total} passed`);
|
|
179
|
+
if (failed > 0)
|
|
180
|
+
details.push(`Failed: ${failed}`);
|
|
181
|
+
break;
|
|
156
182
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
183
|
+
case 'commit-ready': {
|
|
184
|
+
const command = data.command;
|
|
185
|
+
if (command)
|
|
186
|
+
details.push(`Command: ${command}`);
|
|
187
|
+
break;
|
|
162
188
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
189
|
+
case 'committed': {
|
|
190
|
+
const message = data.message;
|
|
191
|
+
if (message)
|
|
192
|
+
details.push(`Message: ${message}`);
|
|
193
|
+
break;
|
|
168
194
|
}
|
|
169
195
|
}
|
|
170
196
|
if (toolData.duration) {
|
|
@@ -185,17 +211,13 @@ export class HookIntegration {
|
|
|
185
211
|
onButlerTrigger(callback) {
|
|
186
212
|
this.triggerCallbacks.push(callback);
|
|
187
213
|
}
|
|
214
|
+
static TEST_FILE_PATTERNS = ['.test.', '.spec.', '/tests/'];
|
|
215
|
+
static TEST_COMMAND_PATTERNS = ['npm test', 'npm run test', 'vitest', 'jest', 'mocha'];
|
|
188
216
|
isTestFile(filePath) {
|
|
189
|
-
return (filePath.includes(
|
|
190
|
-
filePath.includes('.spec.') ||
|
|
191
|
-
filePath.includes('/tests/'));
|
|
217
|
+
return HookIntegration.TEST_FILE_PATTERNS.some(p => filePath.includes(p));
|
|
192
218
|
}
|
|
193
219
|
isTestCommand(command) {
|
|
194
|
-
return (command.includes(
|
|
195
|
-
command.includes('npm run test') ||
|
|
196
|
-
command.includes('vitest') ||
|
|
197
|
-
command.includes('jest') ||
|
|
198
|
-
command.includes('mocha'));
|
|
220
|
+
return HookIntegration.TEST_COMMAND_PATTERNS.some(p => command.includes(p));
|
|
199
221
|
}
|
|
200
222
|
isGitAddCommand(command) {
|
|
201
223
|
return command.trim().startsWith('git add');
|
|
@@ -229,13 +251,18 @@ export class HookIntegration {
|
|
|
229
251
|
}
|
|
230
252
|
return null;
|
|
231
253
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
254
|
+
isValidTestResults(data) {
|
|
255
|
+
if (!data || typeof data !== 'object') {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
const obj = data;
|
|
259
|
+
return (typeof obj.total === 'number' &&
|
|
260
|
+
typeof obj.passed === 'number' &&
|
|
261
|
+
typeof obj.failed === 'number' &&
|
|
262
|
+
Array.isArray(obj.failedTests) &&
|
|
263
|
+
obj.failedTests.every((test) => test &&
|
|
264
|
+
typeof test === 'object' &&
|
|
265
|
+
typeof test.name === 'string'));
|
|
239
266
|
}
|
|
240
267
|
}
|
|
241
268
|
//# sourceMappingURL=HookIntegration.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HookIntegration.js","sourceRoot":"","sources":["../../src/core/HookIntegration.ts"],"names":[],"mappings":"AAsDA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"HookIntegration.js","sourceRoot":"","sources":["../../src/core/HookIntegration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface FailedTest {
|
|
2
|
+
name: string;
|
|
3
|
+
file?: string;
|
|
4
|
+
error?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface TestResults {
|
|
7
|
+
total: number;
|
|
8
|
+
passed: number;
|
|
9
|
+
failed: number;
|
|
10
|
+
failedTests: FailedTest[];
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export declare class TestOutputParser {
|
|
14
|
+
parse(output: string): TestResults;
|
|
15
|
+
private detectFramework;
|
|
16
|
+
private parseVitestFailures;
|
|
17
|
+
private parseJestFailures;
|
|
18
|
+
private parseMochaFailures;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=TestOutputParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestOutputParser.d.ts","sourceRoot":"","sources":["../../src/core/TestOutputParser.ts"],"names":[],"mappings":"AA+BA,MAAM,WAAW,UAAU;IAEzB,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,MAAM,WAAW,WAAW;IAE1B,KAAK,EAAE,MAAM,CAAC;IAGd,MAAM,EAAE,MAAM,CAAC;IAGf,MAAM,EAAE,MAAM,CAAC;IAGf,WAAW,EAAE,UAAU,EAAE,CAAC;IAG1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAUD,qBAAa,gBAAgB;IAU3B,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW;IAqClC,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,iBAAiB;IAqCzB,OAAO,CAAC,kBAAkB;CAwD3B"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
export class TestOutputParser {
|
|
2
|
+
parse(output) {
|
|
3
|
+
const passedPattern = /(\d+)\s+(?:tests?\s+)?pass(?:ed|ing)/gi;
|
|
4
|
+
const failedPattern = /(\d+)\s+(?:tests?\s+)?fail(?:ed|ing)/gi;
|
|
5
|
+
let passed = 0;
|
|
6
|
+
let failed = 0;
|
|
7
|
+
let match;
|
|
8
|
+
while ((match = passedPattern.exec(output)) !== null) {
|
|
9
|
+
passed = parseInt(match[1], 10);
|
|
10
|
+
}
|
|
11
|
+
while ((match = failedPattern.exec(output)) !== null) {
|
|
12
|
+
failed = parseInt(match[1], 10);
|
|
13
|
+
}
|
|
14
|
+
const total = passed + failed;
|
|
15
|
+
let failedTests = [];
|
|
16
|
+
if (failed > 0) {
|
|
17
|
+
const framework = this.detectFramework(output);
|
|
18
|
+
switch (framework) {
|
|
19
|
+
case 'vitest':
|
|
20
|
+
failedTests = this.parseVitestFailures(output);
|
|
21
|
+
break;
|
|
22
|
+
case 'jest':
|
|
23
|
+
failedTests = this.parseJestFailures(output);
|
|
24
|
+
break;
|
|
25
|
+
case 'mocha':
|
|
26
|
+
failedTests = this.parseMochaFailures(output);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return { total, passed, failed, failedTests };
|
|
31
|
+
}
|
|
32
|
+
detectFramework(output) {
|
|
33
|
+
if (output.includes(' > ') && output.includes('FAIL '))
|
|
34
|
+
return 'vitest';
|
|
35
|
+
if (output.includes(' ● '))
|
|
36
|
+
return 'jest';
|
|
37
|
+
if (/\d+\)/.test(output) && /\d+\s+(?:passing|failing)/.test(output))
|
|
38
|
+
return 'mocha';
|
|
39
|
+
return 'unknown';
|
|
40
|
+
}
|
|
41
|
+
parseVitestFailures(output) {
|
|
42
|
+
const failures = [];
|
|
43
|
+
const lines = output.split('\n');
|
|
44
|
+
for (let i = 0; i < lines.length; i++) {
|
|
45
|
+
const line = lines[i];
|
|
46
|
+
const failMatch = /^\s*FAIL\s+(.+?)\s+>\s+(.+?)$/.exec(line);
|
|
47
|
+
if (failMatch) {
|
|
48
|
+
const fullPath = failMatch[1].trim();
|
|
49
|
+
const testPath = failMatch[2].trim();
|
|
50
|
+
const file = fullPath.includes('>') ? fullPath.split('>')[0].trim() : fullPath;
|
|
51
|
+
const name = testPath;
|
|
52
|
+
let error;
|
|
53
|
+
if (i + 1 < lines.length) {
|
|
54
|
+
const nextLine = lines[i + 1].trim();
|
|
55
|
+
if (nextLine && !nextLine.startsWith('FAIL') && !nextLine.startsWith('Test Files')) {
|
|
56
|
+
error = nextLine;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
failures.push({ name, file, error });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return failures;
|
|
63
|
+
}
|
|
64
|
+
parseJestFailures(output) {
|
|
65
|
+
const failures = [];
|
|
66
|
+
const lines = output.split('\n');
|
|
67
|
+
const files = [];
|
|
68
|
+
for (const line of lines) {
|
|
69
|
+
const fileMatch = /^\s*FAIL\s+(.+?)$/.exec(line);
|
|
70
|
+
if (fileMatch && !line.includes('●')) {
|
|
71
|
+
files.push(fileMatch[1].trim());
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
let currentFileIndex = 0;
|
|
75
|
+
for (let i = 0; i < lines.length; i++) {
|
|
76
|
+
const line = lines[i];
|
|
77
|
+
const failMatch = /^\s*●\s+(.+?)$/.exec(line);
|
|
78
|
+
if (failMatch) {
|
|
79
|
+
const name = failMatch[1].trim();
|
|
80
|
+
const file = files[currentFileIndex];
|
|
81
|
+
let error;
|
|
82
|
+
for (let j = i + 1; j < Math.min(i + 5, lines.length); j++) {
|
|
83
|
+
const errorLine = lines[j].trim();
|
|
84
|
+
if (errorLine && !errorLine.includes('●') && !errorLine.startsWith('FAIL')) {
|
|
85
|
+
error = errorLine;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
failures.push({ name, file, error });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return failures;
|
|
93
|
+
}
|
|
94
|
+
parseMochaFailures(output) {
|
|
95
|
+
const failures = [];
|
|
96
|
+
const lines = output.split('\n');
|
|
97
|
+
let inFailingSection = false;
|
|
98
|
+
let failingSectionStart = -1;
|
|
99
|
+
for (let i = 0; i < lines.length; i++) {
|
|
100
|
+
const line = lines[i];
|
|
101
|
+
if (/\d+\s+failing/.test(line)) {
|
|
102
|
+
inFailingSection = true;
|
|
103
|
+
failingSectionStart = i;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (!inFailingSection || i <= failingSectionStart)
|
|
107
|
+
continue;
|
|
108
|
+
if (line.trim().startsWith('npm ') || line.trim().startsWith('Error: '))
|
|
109
|
+
break;
|
|
110
|
+
const singleLineMatch = /^\s*\d+\)\s+(.+?):\s*$/.exec(line);
|
|
111
|
+
if (singleLineMatch) {
|
|
112
|
+
const name = singleLineMatch[1].trim();
|
|
113
|
+
let error;
|
|
114
|
+
if (i + 1 < lines.length) {
|
|
115
|
+
const errorLine = lines[i + 1].trim();
|
|
116
|
+
if (errorLine && !errorLine.match(/^\d+\)/) && !errorLine.startsWith('at ')) {
|
|
117
|
+
error = errorLine;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
failures.push({ name, error });
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const suiteMatch = /^\s*(\d+)\)\s+(.+?)\s*$/.exec(line);
|
|
124
|
+
if (suiteMatch && i + 1 < lines.length) {
|
|
125
|
+
const suite = suiteMatch[2].trim();
|
|
126
|
+
const nextLine = lines[i + 1].trim();
|
|
127
|
+
if (nextLine.endsWith(':') && lines[i + 1].startsWith(' ')) {
|
|
128
|
+
const testName = nextLine.slice(0, -1).trim();
|
|
129
|
+
const name = `${suite} ${testName}`;
|
|
130
|
+
let error;
|
|
131
|
+
if (i + 2 < lines.length) {
|
|
132
|
+
const errorLine = lines[i + 2].trim();
|
|
133
|
+
if (errorLine && !errorLine.match(/^\d+\)/) && !errorLine.startsWith('at ')) {
|
|
134
|
+
error = errorLine;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
failures.push({ name, error });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return failures;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=TestOutputParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestOutputParser.js","sourceRoot":"","sources":["../../src/core/TestOutputParser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Claude Code Buddy Best Practices
|
|
2
|
+
|
|
3
|
+
**Version**: 2.2.0
|
|
4
|
+
|
|
5
|
+
## ✅ Write Precise Requests
|
|
6
|
+
|
|
7
|
+
- Specify files, modules, and constraints
|
|
8
|
+
- State desired behavior and edge cases
|
|
9
|
+
- Mention the tech stack when relevant
|
|
10
|
+
|
|
11
|
+
**Good**:
|
|
12
|
+
```
|
|
13
|
+
"Refactor src/auth/session.ts to remove duplication and add tests"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Avoid**:
|
|
17
|
+
```
|
|
18
|
+
"Fix auth"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## ✅ Use Capability Routing (Default)
|
|
22
|
+
|
|
23
|
+
Let `buddy-do` select the best capability. You do not need to target internal roles.
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
buddy-do "review src/api/auth.ts for security issues"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## ✅ Break Down Large Features
|
|
30
|
+
|
|
31
|
+
Use `generate-smart-plan` before large changes:
|
|
32
|
+
```
|
|
33
|
+
generate-smart-plan "add email-based login with rate limiting"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then execute tasks one by one.
|
|
37
|
+
|
|
38
|
+
## ✅ Leverage Project Memory
|
|
39
|
+
|
|
40
|
+
Use memory before large refactors or architectural changes:
|
|
41
|
+
```
|
|
42
|
+
buddy-remember "why we chose SQLite"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## ✅ Use Workflow Guidance
|
|
46
|
+
|
|
47
|
+
When you finish a phase, ask for next steps:
|
|
48
|
+
```
|
|
49
|
+
get-workflow-guidance {"phase":"test-complete"}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## ✅ Keep Sessions Healthy
|
|
53
|
+
|
|
54
|
+
Long sessions can degrade quality. Check health periodically:
|
|
55
|
+
```
|
|
56
|
+
get-session-health
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## ✅ Prefer Smaller, Testable Chunks
|
|
60
|
+
|
|
61
|
+
- Aim for 2-5 minute tasks
|
|
62
|
+
- Validate with tests before moving on
|
|
63
|
+
- Use clear commit boundaries in your VCS
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
**Remember**: Specific, focused requests yield the best outcomes.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Claude Code Buddy Examples
|
|
2
|
+
|
|
3
|
+
**Version**: 2.2.0
|
|
4
|
+
|
|
5
|
+
## Example 1: Code Review
|
|
6
|
+
|
|
7
|
+
**Request**:
|
|
8
|
+
```
|
|
9
|
+
buddy-do "review src/auth/login.ts for security issues and edge cases"
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Result**: A focused review with security checks, edge cases, and actionable fixes.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Example 2: Feature Planning
|
|
17
|
+
|
|
18
|
+
**Request**:
|
|
19
|
+
```
|
|
20
|
+
generate-smart-plan "add email-based login with rate limiting"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Result**: A structured plan with TDD-friendly steps and estimated durations.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Example 3: Debugging a Failure
|
|
28
|
+
|
|
29
|
+
**Request**:
|
|
30
|
+
```
|
|
31
|
+
buddy-do "debug why login requests return 500s in production"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Result**: Root-cause analysis with likely failure paths and verification steps.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Example 4: Memory Recall
|
|
39
|
+
|
|
40
|
+
**Request**:
|
|
41
|
+
```
|
|
42
|
+
buddy-remember "why we chose SQLite for local storage"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Result**: A concise summary of the decision and its tradeoffs.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Example 5: Workflow Guidance
|
|
50
|
+
|
|
51
|
+
**Request**:
|
|
52
|
+
```
|
|
53
|
+
get-workflow-guidance {"phase":"test-complete"}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Result**: Next-step recommendations for code review and commit readiness.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Claude Code Buddy Quick Reference
|
|
2
|
+
|
|
3
|
+
**Version**: 2.2.0
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
buddy-do "<task description>" # Smart routing (recommended)
|
|
9
|
+
buddy-remember "<query>" # Recall project memory
|
|
10
|
+
buddy-help # Command help
|
|
11
|
+
get-session-health # Session health snapshot
|
|
12
|
+
get-workflow-guidance '{"phase":"code-written"}'
|
|
13
|
+
generate-smart-plan '{"featureDescription":"..."}'
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Note: `hook-tool-use` is internal and used by Claude Code hooks.
|
|
17
|
+
|
|
18
|
+
## 🧭 Capability Keywords
|
|
19
|
+
|
|
20
|
+
| Capability | Keywords | Use For |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| Code Review | review, audit, quality | Security checks, best practices |
|
|
23
|
+
| Testing | test, coverage, TDD | Unit, integration, E2E testing |
|
|
24
|
+
| Debugging | debug, bug, error | Root-cause analysis |
|
|
25
|
+
| Refactoring | refactor, cleanup | Structural improvements |
|
|
26
|
+
| API/Backend | api, endpoint, backend | API design and backend logic |
|
|
27
|
+
| Frontend/UI | ui, component, frontend | UI, accessibility, UX |
|
|
28
|
+
| Architecture | architecture, design, scalability | System design, tradeoffs |
|
|
29
|
+
| Data/Database | database, query, schema | Query tuning, schema design |
|
|
30
|
+
| Documentation | docs, guide, readme | Technical writing |
|
|
31
|
+
|
|
32
|
+
## 🎯 Common Workflows
|
|
33
|
+
|
|
34
|
+
### Feature Development
|
|
35
|
+
```
|
|
36
|
+
1. generate-smart-plan "<feature>"
|
|
37
|
+
2. buddy-do "implement <feature>"
|
|
38
|
+
3. buddy-do "write tests for <feature>"
|
|
39
|
+
4. buddy-do "review <feature> for quality"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Bug Fixing
|
|
43
|
+
```
|
|
44
|
+
1. buddy-do "debug <issue> and find root cause"
|
|
45
|
+
2. buddy-do "fix <issue> and add regression test"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Performance Review
|
|
49
|
+
```
|
|
50
|
+
1. buddy-do "profile performance for <area>"
|
|
51
|
+
2. buddy-do "optimize slow path in <area>"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 💡 Quick Tips
|
|
55
|
+
|
|
56
|
+
✅ **DO**:
|
|
57
|
+
- Use clear, specific task descriptions
|
|
58
|
+
- Mention files, constraints, or target behaviors
|
|
59
|
+
- Use `buddy-remember` before large changes
|
|
60
|
+
|
|
61
|
+
❌ **DON'T**:
|
|
62
|
+
- Use vague descriptions ("fix bug")
|
|
63
|
+
- Skip context when it matters
|
|
64
|
+
|
|
65
|
+
## 📚 Full Documentation
|
|
66
|
+
|
|
67
|
+
- **Complete Guide**: `@claude-code-buddy://usage-guide`
|
|
68
|
+
- **Examples**: `@claude-code-buddy://examples`
|
|
69
|
+
- **Best Practices**: `@claude-code-buddy://best-practices`
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
**Remember**: The smart router learns from your patterns - the more you use it, the better it gets!
|