feat(pipeline): F4.1 — rotas GET /patterns e GET /stats (contrato C4-análise) #2415

- routes/sessions.ts: createSessionsAnalysisRouter com GET /patterns (filtros
  week/severity/key/days, paginado, Zod) e GET /stats (agregados: sessões
  totais e por dia, by_source, by_outcome, tool_top, skill_top,
  patterns_by_type, gate_blocks, avg_duration_sec, last_indexed_at,
  latest_pattern_week); montado em /api/sessions (C4) e /api (alias F4.1)
- services/sessions/db.ts: listPatterns/countPatterns/getStats +
  rowToPattern/buildPatternsWhere; gate_blocks devolve null enquanto a
  tabela gate_events não existir (F1 arco C3-gates)
- tests/sessions-analysis-route.test.ts: 15 testes (filtros, paginação,
  validação, gate_blocks condicional, não-colisão com /:id)
- inclui camada session_events pendente de v2.7.3 (db.ts/indexer.ts —
  storeSessionEvents no indexAll; rota /:id lê da BD) já em execução, para
  a árvore commitada compilar coerente

Validado contra BD real (11459 sessões, 160 padrões): curl 200 com JSON
não-vazio em /api/patterns, /api/stats, /api/sessions/patterns?week=2026-W26,
/api/sessions/stats?days=7.
This commit is contained in:
2026-07-03 06:01:22 +01:00
parent 9b2dfdc412
commit 810401e4e7
5 changed files with 511 additions and 36 deletions
+3 -1
View File
@@ -21,7 +21,7 @@ import n8nRouter from './routes/n8n.js'
import paperclipRouter from './routes/paperclip.js'
import aiRouter from './routes/ai.js'
import operationsRouter from './routes/operations.js'
import { createSessionsRouter } from './routes/sessions.js'
import { createSessionsRouter, createSessionsAnalysisRouter } from './routes/sessions.js'
import { openSessionsDb } from './services/sessions/db.js'
import { DEFAULT_DB_PATH } from './services/sessions/indexer.js'
import { collectAllServerMetrics } from './services/server-metrics.js'
@@ -139,6 +139,8 @@ app.use('/api/operations', operationsRouter)
// Observabilidade (Espelho) — sessões Claude Code
const sessionsDb = openSessionsDb(process.env.OBSERVABILIDADE_DB ?? DEFAULT_DB_PATH)
app.use('/api/sessions', createSessionsRouter(sessionsDb))
// Alias curto do contrato C4 (F4.1): /api/patterns e /api/stats
app.use('/api', createSessionsAnalysisRouter(sessionsDb))
function closeSessionsDb(): void {
try {