#!/usr/bin/env node
/**
 * Glob latency investigator — ad-hoc one-off script (Task 17).
 *
 * Brain-retro 2026-05-20 §17 noted Glob p50 = 12.7s anomaly. This script
 * parses a Claude Code session transcript (JSONL), extracts all Glob
 * tool_use → tool_result round-trips, sorts by latency desc, prints top-N
 * with the pattern (and optional path) that caused each.
 *
 * Output is intentionally compact (top-10 by default). Run on demand
 * against any session transcript when investigating Glob slowness:
 *
 *   node tools/glob-latency-investigator.mjs <path/to/transcript.jsonl> [topN]
 *
 * NOT part of production code path — never imported by parser/hook/analyzer.
 * Lives in tools/ for discoverability alongside the rest of the observer
 * infrastructure.
 *
 * Security Guidance #40: pure fs reads, no exec/execSync.
 */
import { readFileSync, existsSync } from 'fs';

const path = process.argv[2];
const topN = Number.parseInt(process.argv[3] || '10', 10);

if (!path) {
  console.error('Usage: node tools/glob-latency-investigator.mjs <transcript.jsonl> [topN=10]');
  process.exit(1);
}

if (!existsSync(path)) {
  console.error(`File not found: ${path}`);
  process.exit(1);
}

const lines = readFileSync(path, 'utf-8').split('\n').filter(Boolean);

/** Map tool_use.id → { pattern, path, ts } for Glob calls. */
const starts = new Map();
/** Collected round-trip latencies. */
const events = [];

for (const line of lines) {
  let o;
  try { o = JSON.parse(line); } catch { continue; }
  const ts = o.timestamp ? new Date(o.timestamp).getTime() : null;
  if (!ts) continue;

  if (o.type === 'assistant' && o.message && Array.isArray(o.message.content)) {
    for (const c of o.message.content) {
      if (c && c.type === 'tool_use' && c.name === 'Glob') {
        starts.set(c.id, {
          pattern: (c.input && c.input.pattern) || '(no pattern)',
          path: (c.input && c.input.path) || null,
          ts,
        });
      }
    }
  }

  if (o.type === 'user' && o.message && Array.isArray(o.message.content)) {
    for (const c of o.message.content) {
      if (c && c.type === 'tool_result' && starts.has(c.tool_use_id)) {
        const s = starts.get(c.tool_use_id);
        events.push({ pattern: s.pattern, path: s.path, latency: ts - s.ts });
      }
    }
  }
}

events.sort((a, b) => b.latency - a.latency);

const total = events.length;
const median = total > 0 ? events[Math.floor(total / 2)].latency : 0;
const p95 = total > 0 ? events[Math.floor(total * 0.05)].latency : 0;

console.log(`Glob round-trips: ${total} | median ${median}ms | p95 ${p95}ms`);
console.log(`\nTop ${Math.min(topN, total)} by latency:`);
console.log('latency_ms'.padStart(11), '  pattern (path)');
console.log('-----------', ' --------------');
for (const e of events.slice(0, topN)) {
  const where = e.path ? ` (${e.path})` : '';
  console.log(String(e.latency).padStart(11), `  ${e.pattern}${where}`);
}
