fix(observabilidade): parser extrai skills de tool_result.content (string e array)

Antes: skills_invoked vazio em 1608/1608 sessões porque detectSkillInvoked
apenas era aplicado ao text extraído de content[type=text]. A string
'Launching skill: X' vive dentro de tool_result.content (string ou array
de text blocks), que era ignorada.

Fix: adicionar helper extractResultText(r) que trata ambos os casos e
aplicar detectSkillInvoked + detectHook também ao tool_result. Após
re-indexação full, 526/1616 sessões têm agora skills detectadas e o
detector de padrões devolve 6 padrões (vs 2 baseline), incluindo
skills_with_high_error_rate reais.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 02:20:24 +01:00
parent 1eb4f246de
commit ac4e9c6f35
2 changed files with 59 additions and 3 deletions
+38
View File
@@ -67,6 +67,44 @@ describe('parseSessionFile', () => {
expect(result.meta.skills_invoked).toContain('superpowers:brainstorming')
})
it('detecta skill invocation em tool_result.content (string)', async () => {
const path = writeJsonl([
{
type: 'user',
timestamp: '2026-04-23T10:00:00Z',
message: {
role: 'user',
content: [
{ type: 'tool_result', tool_use_id: 'abc', content: 'Launching skill: infraestrutura:easypanel-monitor\nOther log output' },
],
},
},
])
const result = await parseSessionFile(path)
expect(result.meta.skills_invoked).toContain('infraestrutura:easypanel-monitor')
})
it('detecta skill invocation em tool_result.content (array de text blocks)', async () => {
const path = writeJsonl([
{
type: 'user',
timestamp: '2026-04-23T10:00:00Z',
message: {
role: 'user',
content: [
{
type: 'tool_result',
tool_use_id: 'abc',
content: [{ type: 'text', text: 'Launching skill: superpowers:brainstorming' }],
},
],
},
},
])
const result = await parseSessionFile(path)
expect(result.meta.skills_invoked).toContain('superpowers:brainstorming')
})
it('ignora linhas JSON inválidas silenciosamente', async () => {
const path = writeJsonl([
{ type: 'user', message: { role: 'user', content: [{ type: 'text', text: 'válido' }] } },