diff --git a/scripts/lib/inspection.js b/scripts/lib/inspection.js index e6f2cdf33..21d89a7b4 100644 --- a/scripts/lib/inspection.js +++ b/scripts/lib/inspection.js @@ -22,7 +22,7 @@ function normalizeFailureReason(reason) { // Strip UUIDs (already lowercased) .replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g, '') // Strip file paths - .replace(/\/[\w./-]+/g, '') + .replace(/(?:\b[a-z]:)?[\\/][\w./\\-]+/g, '') // Collapse whitespace .replace(/\s+/g, ' ') .trim(); diff --git a/tests/lib/inspection.test.js b/tests/lib/inspection.test.js index f8725f37c..bf948cf8f 100644 --- a/tests/lib/inspection.test.js +++ b/tests/lib/inspection.test.js @@ -58,9 +58,15 @@ async function runTests() { })) passed += 1; else failed += 1; if (await test('normalizeFailureReason strips file paths', async () => { - const normalized = normalizeFailureReason('File not found: /usr/local/bin/node'); - assert.ok(!normalized.includes('/usr/local')); - assert.ok(normalized.includes('')); + for (const reason of [ + 'File not found: /usr/local/bin/node', + String.raw`File not found: C:\project-a\src\one.js`, + 'File not found: D:/project-b/src/two.js', + String.raw`File not found: \\server\share\three.js`, + ]) { + assert.strictEqual(normalizeFailureReason(reason), 'file not found: '); + } + assert.strictEqual(normalizeFailureReason('Request failed: https://example.com/test'), 'request failed: https:'); })) passed += 1; else failed += 1; if (await test('normalizeFailureReason handles null and empty values', async () => { @@ -171,6 +177,19 @@ async function runTests() { assert.ok(patterns[0].normalizedReason.includes('')); })) passed += 1; else failed += 1; + if (await test('detectPatterns groups failures from different Windows paths', async () => { + const runs = [ + makeSkillRun({ id: 'r1', failureReason: String.raw`File not found: C:\project-a\one.js` }), + makeSkillRun({ id: 'r2', failureReason: 'File not found: D:/project-b/two.js' }), + makeSkillRun({ id: 'r3', failureReason: String.raw`File not found: E:\project-c\three.js` }), + ]; + const patterns = detectPatterns(runs); + assert.strictEqual(patterns.length, 1); + assert.strictEqual(patterns[0].count, 3); + assert.strictEqual(patterns[0].normalizedReason, 'file not found: '); + assert.strictEqual(generateReport(patterns).status, 'attention_needed'); + })) passed += 1; else failed += 1; + if (await test('detectPatterns tracks unique session IDs and versions', async () => { const runs = [ makeSkillRun({ id: 'r1', sessionId: 'sess-1', skillVersion: '1.0.0', failureReason: 'err' }),