@titan-design/session-analytics 0.5.0 → 0.8.0

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/prices.ts","../src/price-request.ts","../src/classify-session.ts","../src/bands.ts","../src/cost-report.ts","../src/cost-report-queries.ts","../src/episodes.ts","../src/handoff-threshold.ts","../src/initiative.ts","../src/request-owner.ts","../src/roles.ts","../src/scope.ts","../src/turn-action.ts","../src/wake-episodes.ts","../src/render-text.ts","../src/cache-ttl.ts","../src/blocked-flow-merge.ts","../src/blocked-flow-denials.ts","../src/blocked-flow-idle.ts","../src/blocked-flow.ts"],"sourcesContent":["/** USD per million tokens. Fitted against 392 `cost-state` rows in the 2026-09-20 audit. */\nexport interface PriceRow {\n /** Matched at a model-id boundary: the id itself, or followed by a -YYYYMMDD or [..] suffix. */\n modelPrefix: string;\n /** ISO date. The latest row at or before a request's timestamp wins. */\n effectiveFrom: string;\n input: number;\n cacheRead: number;\n cacheWrite5m: number;\n cacheWrite1h: number;\n output: number;\n}\n\n/** Bump on any edit to PRICE_TABLE. The cost report prints it in its footer. */\nexport const PRICE_TABLE_VERSION = 2;\n\nconst OPUS = { input: 5.0, cacheRead: 0.5, cacheWrite5m: 6.25, cacheWrite1h: 10.0, output: 25.0 };\nconst OPUS_5_5 = { input: 4.0, cacheRead: 0.2, cacheWrite5m: 5.0, cacheWrite1h: 8.0, output: 20.0 };\nconst SONNET = { input: 2.0, cacheRead: 0.2, cacheWrite5m: 2.5, cacheWrite1h: 4.0, output: 10.0 };\n// Fable's cache read is 0.025 of input, not the 0.1 every other model uses. Reading it as\n// 0.1 overstated the 2026-09-20 audit by about $1,700; `fable-cache-read.test` pins the ratio.\nconst FABLE = { input: 10.0, cacheRead: 0.25, cacheWrite5m: 12.5, cacheWrite1h: 20.0, output: 50.0 };\nconst SONNET_5_5 = { input: 2.0, cacheRead: 0.2, cacheWrite5m: 2.5, cacheWrite1h: 4.0, output: 10.0 };\nconst HAIKU = { input: 1.0, cacheRead: 0.1, cacheWrite5m: 1.25, cacheWrite1h: 2.0, output: 5.0 };\nconst FREE = { input: 0, cacheRead: 0, cacheWrite5m: 0, cacheWrite1h: 0, output: 0 };\n\nconst GENESIS = \"2026-01-01\";\n\nexport const PRICE_TABLE: readonly PriceRow[] = [\n // 5.5 rows: claude-api skill shared/models.md and prompt-caching.md, bundled copy cached 2026-09-25.\n { modelPrefix: \"claude-opus-5-5\", effectiveFrom: GENESIS, ...OPUS_5_5 },\n { modelPrefix: \"claude-opus-5\", effectiveFrom: GENESIS, ...OPUS },\n { modelPrefix: \"claude-opus-4-8\", effectiveFrom: GENESIS, ...OPUS },\n { modelPrefix: \"claude-sonnet-5-5\", effectiveFrom: GENESIS, ...SONNET_5_5 },\n { modelPrefix: \"claude-sonnet-5\", effectiveFrom: GENESIS, ...SONNET },\n { modelPrefix: \"claude-fable-5-1\", effectiveFrom: GENESIS, ...FABLE },\n { modelPrefix: \"claude-fable-5\", effectiveFrom: GENESIS, ...FABLE },\n { modelPrefix: \"claude-haiku-4-5\", effectiveFrom: GENESIS, ...HAIKU },\n { modelPrefix: \"<synthetic>\", effectiveFrom: GENESIS, ...FREE },\n];\n\n/**\n * The longest prefix that matches the model at an id boundary, then the latest row effective at `ts`.\n * Returns null for a model no row covers: an unknown model is unpriced, never defaulted,\n * because a default silently prices a new model at an old model's rate.\n */\nexport function findPrice(model: string, ts: string, prices: readonly PriceRow[] = PRICE_TABLE): PriceRow | null {\n let best: PriceRow | null = null;\n for (const row of prices) {\n if (!matchesAtBoundary(model, row.modelPrefix)) continue;\n if (row.effectiveFrom > ts) continue;\n if (best && !isBetterMatch(row, best)) continue;\n best = row;\n }\n return best;\n}\n\nfunction isBetterMatch(row: PriceRow, best: PriceRow): boolean {\n if (row.modelPrefix.length !== best.modelPrefix.length) return row.modelPrefix.length > best.modelPrefix.length;\n return row.effectiveFrom > best.effectiveFrom;\n}\n\n// A bare startsWith lets claude-opus-5 price claude-opus-5-5 at the older model's rates.\nfunction matchesAtBoundary(model: string, prefix: string): boolean {\n if (!model.startsWith(prefix)) return false;\n const rest = model.slice(prefix.length);\n return rest === \"\" || rest.startsWith(\"[\") || /^-\\d{8}(\\[.*\\])?$/.test(rest);\n}\n","import type { PriceRow } from \"./prices.js\";\nimport { PRICE_TABLE, findPrice } from \"./prices.js\";\n\n/** Raw token counts for one API request, as the transcript reports them. */\nexport interface RequestTokens {\n inputTokens?: number;\n cacheReadTokens?: number;\n /** Total cache creation. Used only when the 5m/1h split is absent. */\n cacheCreationTokens?: number;\n cacheCreation5mTokens?: number;\n cacheCreation1hTokens?: number;\n outputTokens?: number;\n}\n\nexport interface PricedRequest {\n inputUsd: number;\n cacheReadUsd: number;\n cacheWrite5mUsd: number;\n cacheWrite1hUsd: number;\n outputUsd: number;\n costUsd: number;\n /** False when no price row covers the model. Every component is then zero. */\n priced: boolean;\n}\n\nconst UNPRICED: PricedRequest = {\n inputUsd: 0,\n cacheReadUsd: 0,\n cacheWrite5mUsd: 0,\n cacheWrite1hUsd: 0,\n outputUsd: 0,\n costUsd: 0,\n priced: false,\n};\n\nexport function priceRequest(\n tokens: RequestTokens,\n model: string,\n ts: string,\n prices: readonly PriceRow[] = PRICE_TABLE,\n): PricedRequest {\n const row = findPrice(model, ts, prices);\n if (!row) return { ...UNPRICED };\n\n const { write5m, write1h } = splitCacheCreation(tokens);\n const inputUsd = perMTok(tokens.inputTokens, row.input);\n const cacheReadUsd = perMTok(tokens.cacheReadTokens, row.cacheRead);\n const cacheWrite5mUsd = perMTok(write5m, row.cacheWrite5m);\n const cacheWrite1hUsd = perMTok(write1h, row.cacheWrite1h);\n const outputUsd = perMTok(tokens.outputTokens, row.output);\n const costUsd = inputUsd + cacheReadUsd + cacheWrite5mUsd + cacheWrite1hUsd + outputUsd;\n return { inputUsd, cacheReadUsd, cacheWrite5mUsd, cacheWrite1hUsd, outputUsd, costUsd, priced: true };\n}\n\n/**\n * Older transcripts carry a cache_creation total with no ttl breakdown. Charging the\n * 5m rate there under-reads rather than over-reads, and 5m is the harness default.\n */\nfunction splitCacheCreation(tokens: RequestTokens): { write5m: number; write1h: number } {\n const write5m = tokens.cacheCreation5mTokens ?? 0;\n const write1h = tokens.cacheCreation1hTokens ?? 0;\n if (write5m > 0 || write1h > 0) return { write5m, write1h };\n return { write5m: tokens.cacheCreationTokens ?? 0, write1h: 0 };\n}\n\nfunction perMTok(tokens: number | undefined, ratePerMTok: number): number {\n return ((tokens ?? 0) * ratePerMTok) / 1_000_000;\n}\n","export type SessionClass = \"agent_spawned\" | \"human_interactive\" | \"headless_sdk\" | \"other_headless\";\n\n/** Human sessions only. A coordinator drives other agents; an adhoc session does not. */\nexport type HumanRole = \"coordinator\" | \"adhoc\";\n\n/** The agent-chat spawn record for a session, as the origin resolver returns it. */\nexport interface SessionOrigin {\n depth: number;\n parentName?: string | null;\n /** \"adopted\" and \"inherited\" mark a pane the human took over, not a spawned worker. */\n originKind?: string | null;\n profile?: string | null;\n}\n\nexport interface SessionFacts {\n /** The harness entrypoint. Agent-chat workers and `-p` miners both report \"sdk-cli\". */\n startType?: string | null;\n origin?: SessionOrigin | null;\n firstUserText?: string | null;\n humanTurnCount?: number;\n inboundKinds?: readonly string[];\n signalKinds?: readonly string[];\n}\n\nexport interface SessionClassification {\n sessionClass: SessionClass;\n reason: string;\n humanRole: HumanRole | null;\n}\n\nconst COORDINATOR_SIGNALS = new Set([\"agent_spawn\", \"chat_send\"]);\n\n/**\n * Rule order matters. The origin row wins over `startType` because agent-chat workers\n * run `claude -p` and so report \"sdk-cli\" exactly like a headless miner does.\n */\nexport function classifySession(facts: SessionFacts): SessionClassification {\n const [sessionClass, reason] = classOf(facts);\n const humanRole = sessionClass === \"human_interactive\" ? humanRoleOf(facts) : null;\n return { sessionClass, reason, humanRole };\n}\n\nfunction classOf(facts: SessionFacts): [SessionClass, string] {\n const origin = facts.origin;\n if (origin) {\n if (isAdoptedPane(origin)) return [\"human_interactive\", \"origin depth 0, human or adopted parent\"];\n return [\"agent_spawned\", \"origin depth >= 1\"];\n }\n if (facts.startType === \"sdk-cli\") return [\"headless_sdk\", \"start_type sdk-cli with no origin row\"];\n if (isProgrammaticPrompt(facts)) return [\"other_headless\", \"content-block prompt with <= 2 human turns\"];\n return [\"human_interactive\", \"no origin row, no headless marker\"];\n}\n\nfunction isAdoptedPane(origin: SessionOrigin): boolean {\n if (origin.depth !== 0) return false;\n if (origin.parentName === \"human\") return true;\n if (origin.originKind === \"adopted\" || origin.originKind === \"inherited\") return true;\n return !origin.profile;\n}\n\n/** Cron and RemoteTrigger daemons inject a structured content block, never typed prose. */\nfunction isProgrammaticPrompt(facts: SessionFacts): boolean {\n const text = (facts.firstUserText ?? \"\").trimStart();\n return text.startsWith(\"[{\") && (facts.humanTurnCount ?? 0) <= 2;\n}\n\nfunction humanRoleOf(facts: SessionFacts): HumanRole {\n if (facts.inboundKinds?.includes(\"channel_message\")) return \"coordinator\";\n if (facts.signalKinds?.some((kind) => COORDINATOR_SIGNALS.has(kind))) return \"coordinator\";\n return \"adhoc\";\n}\n","/** Half-open [lo, hi) in the band's own unit. */\nexport interface Band {\n lo: number;\n hi: number;\n name: string;\n}\n\n/** Context size in tokens. From `cf_analyze.py` BANDS. */\nexport const CONTEXT_BANDS: readonly Band[] = [\n { lo: 0, hi: 50_000, name: \"<50k\" },\n { lo: 50_000, hi: 100_000, name: \"50-100k\" },\n { lo: 100_000, hi: 200_000, name: \"100-200k\" },\n { lo: 200_000, hi: Number.POSITIVE_INFINITY, name: \"200k+\" },\n];\n\n/** Idle gap in milliseconds. From `cf_analyze.py` IDLE. */\nexport const GAP_BANDS: readonly Band[] = [\n { lo: 0, hi: 5 * 60_000, name: \"<5m\" },\n { lo: 5 * 60_000, hi: 60 * 60_000, name: \"5-60m\" },\n { lo: 60 * 60_000, hi: Number.POSITIVE_INFINITY, name: \">60m\" },\n];\n\n/** Null for a value no band covers, so a caller reports the gap instead of inventing one. */\nexport function bandOf(value: number, bands: readonly Band[]): string | null {\n for (const band of bands) {\n if (value >= band.lo && value < band.hi) return band.name;\n }\n return null;\n}\n\nexport function contextBand(tokens: number): string | null {\n return bandOf(tokens, CONTEXT_BANDS);\n}\n\nexport function gapBand(millis: number): string | null {\n return bandOf(millis, GAP_BANDS);\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { z } from \"zod\";\nimport { classifySession, type SessionClass } from \"./classify-session.js\";\nimport {\n readAgentNames,\n readCompactions,\n readCostRows,\n readCoverage,\n readAgentSessions,\n readPriceTableVersion,\n readRequestEvents,\n readSessionContexts,\n readWakeEvents,\n type CompactionRow,\n type CostRow,\n type ReportWindow,\n type SessionContext,\n} from \"./cost-report-queries.js\";\nimport { assignmentCount, heuristicFor } from \"./episodes.js\";\nimport { handoffThreshold, handoffThresholdSchema, isBootAction, parseTeleportEvents, type HandoffOptions, type HandoffThreshold } from \"./handoff-threshold.js\";\nimport { sessionInitiative } from \"./initiative.js\";\nimport { readRequestToolCalls } from \"./request-owner.js\";\nimport { sessionRole } from \"./roles.js\";\nimport { scopeFilter, type ReportScope } from \"./scope.js\";\nimport {\n ACTION_CLASSES,\n DEFAULT_ACTION_RULES,\n DEFAULT_MECHANICAL_CLASSES,\n classifyRequest,\n type ActionClass,\n type ActionRule,\n} from \"./turn-action.js\";\nimport {\n DEFAULT_EPISODE_ROLES,\n DEFAULT_NO_ACTION_CLASSES,\n buildWakeEpisodes,\n episodeNames,\n summarizeWakeEpisodes,\n wakeEpisodesSchema,\n type WakeEpisodes,\n} from \"./wake-episodes.js\";\n\nconst count = z.number().int().nonnegative();\nconst bucketSchema = z.object({ key: z.string(), requests: count, sessions: count, costUsd: z.number() });\nconst wakePartSchema = bucketSchema.extend({ midLoopRequests: count, midLoopCostUsd: z.number() });\nconst cellSchema = z.object({ wakeCause: z.string(), gapBand: z.string(), requests: count, costUsd: z.number() });\nconst fraction = z.number().min(0).max(1);\nconst roleShareSchema = z.object({ role: z.string(), costUsd: z.number(), share: fraction });\n\nexport const TOKEN_CLASSES = [\"input\", \"cache_read\", \"cache_write_5m\", \"cache_write_1h\", \"output\"] as const;\nexport type TokenClass = (typeof TOKEN_CLASSES)[number];\n\nexport const costReportSchema = z.object({\n window: z.object({ since: z.string().nullable(), until: z.string().nullable() }),\n priceTableVersion: z.number().int().nullable(),\n totals: z.object({ requests: count, sessions: count, costUsd: z.number(), unpricedRequests: count }),\n byTokenClass: z.array(z.object({ tokenClass: z.enum(TOKEN_CLASSES), tokens: count, costUsd: z.number() })),\n byAccount: z.array(bucketSchema),\n byModel: z.array(bucketSchema),\n byClass: z.array(bucketSchema),\n byRole: z.array(bucketSchema),\n /** Per role, cost by the action class of each request, from the tool calls it issued. */\n byAction: z.array(z.object({ role: z.string(), buckets: z.array(bucketSchema) })),\n /** Cost of the mechanical action classes over the window total; each role's share is over that role's cost. */\n mechanicalShare: z.object({ classes: z.array(z.enum(ACTION_CLASSES)), costUsd: z.number(), share: fraction, byRole: z.array(roleShareSchema) }),\n /** Sessions by how many episodes their class's heuristic cut them into; `none` when not yet segmented. */\n byEpisodeCount: z.array(bucketSchema),\n byInitiative: z.array(bucketSchema),\n byContextBand: z.array(bucketSchema),\n byWakeCause: z.array(wakePartSchema.extend({ parts: z.array(wakePartSchema) })),\n /** Per wake episode of the episode roles: an arrival and the requests up to the next one, mid-loop deliveries included. */\n wakeEpisodes: wakeEpisodesSchema,\n /** Per role and model, the handoff threshold K that minimises boot plus cache-read cost per request. */\n handoffThreshold: handoffThresholdSchema,\n wakeCauseByGapBand: z.array(cellSchema),\n coldRebuild: z.object({ requests: count, costUsd: z.number(), byGapBandAndCause: z.array(cellSchema) }),\n compactions: z.object({ total: count, manual: count, auto: count, midLoop: count, droppedTokens: count }),\n topSessions: z.array(\n z.object({\n sessionId: z.string(),\n sessionClass: z.string(),\n role: z.string(),\n initiative: z.string(),\n account: z.string(),\n requests: count,\n costUsd: z.number(),\n }),\n ),\n unpricedModels: z.array(z.object({ model: z.string(), requests: count, tokens: count })),\n coverage: z.object({ transcriptsIndexed: count, transcriptsDiscovered: count.nullable(), facetBacklog: count }),\n});\n\nexport type CostReport = z.infer<typeof costReportSchema>;\nexport type CostBucket = z.infer<typeof bucketSchema>;\nexport type WakeCauseBucket = CostReport[\"byWakeCause\"][number];\nexport type WakeGapCell = z.infer<typeof cellSchema>;\nexport type RoleActions = CostReport[\"byAction\"][number];\nexport type MechanicalShare = CostReport[\"mechanicalShare\"];\n\nexport interface CostReportOptions {\n /** ISO timestamp or date, inclusive. Overrides `days`. */\n since?: string;\n /** ISO timestamp or date, exclusive. */\n until?: string;\n /** Window length ending at `until`, or at `now` when `until` is absent. */\n days?: number;\n now?: Date;\n /** Sessions listed in `topSessions`. */\n top?: number;\n /** Transcripts the caller discovered on disk; the graph cannot know this. */\n transcriptsDiscovered?: number;\n /** The extraction version an audit facet must reach to count as current. */\n facetVersion?: number;\n /** Action rules in precedence order; seat-specific rules belong in the caller's config. */\n actionRules?: readonly ActionRule[];\n /** Action classes counted as mechanical in `mechanicalShare`. */\n mechanicalClasses?: readonly ActionClass[];\n /** Report roles whose wakes `wakeEpisodes` cuts into episodes. */\n episodeRoles?: readonly string[];\n /** A wake is no-action when every one of its requests falls in these action classes. */\n noActionClasses?: readonly ActionClass[];\n /** The broker log's lines, read by the caller; its teleport starts give each handoff's exit fill. */\n brokerLogLines?: () => Iterable<string>;\n handoff?: HandoffOptions;\n /** Narrows every request-keyed field to some sessions; absent means all. */\n scope?: ReportScope;\n}\n\n/** AskUserQuestion answers are the human answering, so they count under `human` (decisions Q4). */\nconst HUMAN_CAUSES: readonly string[] = [\"human_typed\", \"ask_user_answer\"];\nconst NONE = \"none\";\nconst DEFAULT_TOP = 10;\nconst EPISODE_COUNT_CAP = 5;\nconst DAY_MS = 86_400_000;\n\ninterface SessionTags {\n sessionClass: SessionClass;\n role: string;\n episodeCount: string;\n initiative: string;\n account: string;\n}\n\ntype TaggedRow = CostRow & SessionTags & { action: ActionClass; bootAction: boolean };\n\n/** Reads the graph and never writes it, so a read-only connection is enough. */\nexport function costReport(db: Db, options: CostReportOptions = {}): CostReport {\n const window = resolveWindow(options);\n const rows = readTaggedRows(db, window, options.actionRules ?? DEFAULT_ACTION_RULES).filter(scopeFilter(db, options.scope));\n return {\n window,\n priceTableVersion: readPriceTableVersion(db),\n totals: { ...sumOf(rows), sessions: new Set(rows.map((row) => row.sessionId)).size, unpricedRequests: rows.filter((row) => !row.priced).length },\n byTokenClass: tokenClasses(rows),\n ...dimensionBuckets(rows),\n byAction: roleActions(rows),\n mechanicalShare: mechanicalShare(rows, options.mechanicalClasses ?? DEFAULT_MECHANICAL_CLASSES),\n byWakeCause: wakeCauses(rows),\n wakeEpisodes: wakeEpisodes(db, window, rows, options),\n handoffThreshold: handoff(db, window, rows, options),\n wakeCauseByGapBand: gapCells(rows),\n coldRebuild: coldRebuild(rows),\n compactions: compactionCounts(readCompactions(db, window)),\n topSessions: topSessions(rows, options.top ?? DEFAULT_TOP),\n unpricedModels: unpricedModels(rows),\n coverage: { ...readCoverage(db, options.facetVersion ?? null), transcriptsDiscovered: options.transcriptsDiscovered ?? null },\n };\n}\n\nfunction readTaggedRows(db: Db, window: ReportWindow, rules: readonly ActionRule[]): TaggedRow[] {\n const costRows = readCostRows(db, window);\n const tags = tagSessions(readSessionContexts(db, [...new Set(costRows.map((row) => row.sessionId))]));\n const calls = readRequestToolCalls(db, window);\n return costRows.map((row) => {\n const requestCalls = calls.get(row.requestId) ?? [];\n return { ...row, ...tags.get(row.sessionId)!, action: classifyRequest(requestCalls, rules), bootAction: isBootAction(requestCalls) };\n });\n}\n\nexport function resolveWindow(options: CostReportOptions): ReportWindow {\n const until = options.until ?? null;\n if (options.since !== undefined) return { since: options.since, until };\n if (options.days === undefined) return { since: null, until };\n const end = until ? Date.parse(until) : (options.now ?? new Date()).getTime();\n return { since: new Date(end - options.days * DAY_MS).toISOString(), until };\n}\n\nexport function tagSessions(contexts: Map<string, SessionContext>): Map<string, SessionTags> {\n const tags = new Map<string, SessionTags>();\n for (const [sessionId, context] of contexts) {\n const classification = classifySession(context.facts);\n const episodes = context.episodes.filter((episode) => episode.heuristic === heuristicFor(classification.sessionClass));\n const worker = { profile: context.facts.origin?.profile, lifetimeMs: context.lifetimeMs, assignments: assignmentCount(episodes) };\n tags.set(sessionId, {\n sessionClass: classification.sessionClass,\n role: sessionRole(classification, worker),\n episodeCount: episodeCountKey(episodes.length),\n initiative: sessionInitiative(context.tasks, context.cwd),\n account: context.account ?? \"unknown\",\n });\n }\n return tags;\n}\n\n/** The worker report's assignment buckets: 1, 2, 3, 4, 5+. */\nfunction episodeCountKey(episodes: number): string {\n if (episodes === 0) return NONE;\n return episodes >= EPISODE_COUNT_CAP ? `${EPISODE_COUNT_CAP}+` : String(episodes);\n}\n\nfunction sumOf(rows: readonly CostRow[]): { requests: number; costUsd: number } {\n return { requests: rows.length, costUsd: rows.reduce((sum, row) => sum + row.costUsd, 0) };\n}\n\nfunction tokenClasses(rows: readonly CostRow[]): CostReport[\"byTokenClass\"] {\n const pick: Record<TokenClass, (row: CostRow) => [number, number]> = {\n input: (row) => [row.inputTokens, row.inputCostUsd],\n cache_read: (row) => [row.cacheReadTokens, row.cacheReadCostUsd],\n cache_write_5m: (row) => [row.cacheWrite5mTokens, row.cacheWrite5mCostUsd],\n cache_write_1h: (row) => [row.cacheWrite1hTokens, row.cacheWrite1hCostUsd],\n output: (row) => [row.outputTokens, row.outputCostUsd],\n };\n return TOKEN_CLASSES.map((tokenClass) => {\n const pairs = rows.map(pick[tokenClass]);\n return { tokenClass, tokens: pairs.reduce((sum, [tokens]) => sum + tokens, 0), costUsd: pairs.reduce((sum, [, cost]) => sum + cost, 0) };\n });\n}\n\nfunction dimensionBuckets(rows: readonly TaggedRow[]) {\n return {\n byAccount: bucketsBy(rows, (row) => row.account),\n byModel: bucketsBy(rows, (row) => row.model),\n byClass: bucketsBy(rows, (row) => row.sessionClass),\n byRole: bucketsBy(rows, (row) => row.role),\n byEpisodeCount: bucketsBy(rows, (row) => row.episodeCount),\n byInitiative: bucketsBy(rows, (row) => row.initiative),\n byContextBand: bucketsBy(rows, (row) => row.contextBand),\n };\n}\n\n/** Roles most expensive first, the same order as `byRole`. */\nfunction roleActions(rows: readonly TaggedRow[]): RoleActions[] {\n return [...groupRows(rows, (row) => row.role)]\n .map(([role, members]) => ({ key: role, costUsd: sumOf(members).costUsd, buckets: bucketsBy(members, (row) => row.action) }))\n .sort(byCostThenKey)\n .map(({ key, buckets }) => ({ role: key, buckets }));\n}\n\nfunction mechanicalShare(rows: readonly TaggedRow[], classes: readonly ActionClass[]): MechanicalShare {\n const isMechanical = (row: TaggedRow) => classes.includes(row.action);\n const shareOf = (members: readonly TaggedRow[]) => {\n const costUsd = sumOf(members.filter(isMechanical)).costUsd;\n return { costUsd, share: ratio(costUsd, sumOf(members).costUsd) };\n };\n const byRole = [...groupRows(rows, (row) => row.role)]\n .map(([role, members]) => ({ role, ...shareOf(members) }))\n .sort((a, b) => b.costUsd - a.costUsd || a.role.localeCompare(b.role));\n return { classes: [...classes], ...shareOf(rows), byRole };\n}\n\nfunction ratio(part: number, whole: number): number {\n return whole > 0 ? Math.min(part / whole, 1) : 0;\n}\n\n/** Most expensive first; ties by key so the report is stable. */\nfunction bucketsBy<T extends CostRow>(rows: readonly T[], keyOf: (row: T) => string): CostBucket[] {\n const groups = groupRows(rows, keyOf);\n return [...groups]\n .map(([key, members]) => ({ key, ...sumOf(members), sessions: new Set(members.map((row) => row.sessionId)).size }))\n .sort(byCostThenKey);\n}\n\nfunction groupRows<T>(rows: readonly T[], keyOf: (row: T) => string): Map<string, T[]> {\n const groups = new Map<string, T[]>();\n for (const row of rows) {\n const key = keyOf(row);\n const members = groups.get(key);\n if (members) members.push(row);\n else groups.set(key, [row]);\n }\n return groups;\n}\n\nfunction byCostThenKey(a: { key: string; costUsd: number }, b: { key: string; costUsd: number }): number {\n return b.costUsd - a.costUsd || a.key.localeCompare(b.key);\n}\n\nfunction wakeCauses(rows: readonly CostRow[]): WakeCauseBucket[] {\n const causeOf = (row: CostRow) => row.wakeCause ?? NONE;\n const groupOf = (row: CostRow) => (HUMAN_CAUSES.includes(causeOf(row)) ? \"human\" : causeOf(row));\n return [...groupRows(rows, groupOf)]\n .map(([key, members]) => ({\n ...wakePart(key, members),\n parts: key === \"human\" ? [...groupRows(members, causeOf)].map(([cause, part]) => wakePart(cause, part)).sort(byCostThenKey) : [],\n }))\n .sort(byCostThenKey);\n}\n\nfunction wakeEpisodes(db: Db, window: ReportWindow, rows: readonly TaggedRow[], options: CostReportOptions): WakeEpisodes {\n const roles = options.episodeRoles ?? DEFAULT_EPISODE_ROLES;\n const noActionClasses = options.noActionClasses ?? DEFAULT_NO_ACTION_CLASSES;\n const members = rows.filter((row) => roles.includes(row.role));\n const sessionIds = [...new Set(members.map((row) => row.sessionId))];\n const eventOf = readRequestEvents(db, window, sessionIds);\n const requests = members.map((row) => ({ costUsd: row.costUsd, action: row.action, eventKey: eventOf.get(row.requestId) ?? null }));\n const episodes = buildWakeEpisodes(readWakeEvents(db, window, sessionIds), requests, episodeNames(readAgentNames(db)), noActionClasses);\n return summarizeWakeEpisodes(episodes, requests, roles, noActionClasses);\n}\n\nfunction handoff(db: Db, window: ReportWindow, rows: readonly TaggedRow[], options: CostReportOptions): HandoffThreshold {\n const inWindow = (ts: string) => (window.since === null || ts >= window.since) && (window.until === null || ts < window.until);\n const teleports = parseTeleportEvents(options.brokerLogLines?.() ?? []).filter((event) => inWindow(event.ts));\n const requests = rows\n .filter((row) => !row.isSidechain)\n .map((row) => ({\n sessionId: row.sessionId,\n role: row.role,\n model: row.model,\n ts: row.ts,\n fill: row.contextTokens,\n tokens: { inputTokens: row.inputTokens, cacheReadTokens: row.cacheReadTokens, cacheCreation5mTokens: row.cacheWrite5mTokens, cacheCreation1hTokens: row.cacheWrite1hTokens, outputTokens: row.outputTokens },\n bootAction: row.bootAction,\n }));\n return handoffThreshold(requests, teleports, readAgentSessions(db), options.handoff);\n}\n\nfunction wakePart(key: string, rows: readonly CostRow[]) {\n const midLoop = rows.filter((row) => row.wakeDelivery === \"mid_loop\");\n const sessions = new Set(rows.map((row) => row.sessionId)).size;\n return { key, ...sumOf(rows), sessions, midLoopRequests: midLoop.length, midLoopCostUsd: sumOf(midLoop).costUsd };\n}\n\nfunction gapCells(rows: readonly CostRow[]): WakeGapCell[] {\n const keyOf = (row: CostRow) => JSON.stringify([row.wakeCause ?? NONE, row.gapBand ?? NONE]);\n return [...groupRows(rows, keyOf)]\n .map(([key, members]) => {\n const [wakeCause, gapBand] = JSON.parse(key) as [string, string];\n return { wakeCause, gapBand, ...sumOf(members) };\n })\n .sort((a, b) => b.costUsd - a.costUsd || a.wakeCause.localeCompare(b.wakeCause) || a.gapBand.localeCompare(b.gapBand));\n}\n\nfunction coldRebuild(rows: readonly CostRow[]): CostReport[\"coldRebuild\"] {\n const cold = rows.filter((row) => row.isCold);\n return { ...sumOf(cold), byGapBandAndCause: gapCells(cold) };\n}\n\nfunction compactionCounts(rows: readonly CompactionRow[]): CostReport[\"compactions\"] {\n return {\n total: rows.length,\n manual: rows.filter((row) => row.trigger === \"manual\").length,\n auto: rows.filter((row) => row.trigger === \"auto\").length,\n midLoop: rows.filter((row) => row.midLoop).length,\n droppedTokens: rows.reduce((sum, row) => sum + (row.droppedTokens ?? 0), 0),\n };\n}\n\nfunction topSessions(rows: readonly TaggedRow[], top: number): CostReport[\"topSessions\"] {\n return [...groupRows(rows, (row) => row.sessionId)]\n .map(([sessionId, members]) => {\n const { sessionClass, role, initiative, account } = members[0]!;\n return { sessionId, sessionClass, role, initiative, account, ...sumOf(members) };\n })\n .sort((a, b) => b.costUsd - a.costUsd || a.sessionId.localeCompare(b.sessionId))\n .slice(0, top);\n}\n\nfunction unpricedModels(rows: readonly CostRow[]): CostReport[\"unpricedModels\"] {\n const unpriced = rows.filter((row) => !row.priced);\n return [...groupRows(unpriced, (row) => row.model)]\n .map(([model, members]) => ({ model, requests: members.length, tokens: members.reduce((sum, row) => sum + tokensOf(row), 0) }))\n .sort((a, b) => b.tokens - a.tokens || a.model.localeCompare(b.model));\n}\n\nfunction tokensOf(row: CostRow): number {\n return row.inputTokens + row.cacheReadTokens + row.cacheWrite5mTokens + row.cacheWrite1hTokens + row.outputTokens;\n}\n","import { AUDIT_FACET, EPISODE_TABLE, FACET_TABLE, KIT } from \"@titan-design/session-graph\";\nimport type { Db } from \"@titan-design/store-sqlite\";\nimport type { SessionFacts } from \"./classify-session.js\";\nimport type { TaskInitiative } from \"./initiative.js\";\n\n/** ISO bounds on request `ts`: `since` inclusive, `until` exclusive, null for open. */\nexport interface ReportWindow {\n since: string | null;\n until: string | null;\n}\n\n/** One deduplicated, priced request as the `request_cost` view returns it. */\nexport interface CostRow {\n sessionId: string;\n requestId: string;\n ts: string;\n model: string;\n /** Tokens in context at the request. */\n contextTokens: number;\n isSidechain: boolean;\n inputTokens: number;\n cacheReadTokens: number;\n cacheWrite5mTokens: number;\n cacheWrite1hTokens: number;\n outputTokens: number;\n inputCostUsd: number;\n cacheReadCostUsd: number;\n cacheWrite5mCostUsd: number;\n cacheWrite1hCostUsd: number;\n outputCostUsd: number;\n costUsd: number;\n priced: boolean;\n isCold: boolean;\n contextBand: string;\n gapBand: string | null;\n wakeCause: string | null;\n wakeDelivery: string | null;\n}\n\n/** What the report needs about one session beyond its requests. */\nexport interface SessionContext {\n facts: SessionFacts;\n cwd: string | null;\n account: string | null;\n tasks: TaskInitiative[];\n /** First to last main-thread request over the whole session, not just the window. */\n lifetimeMs: number;\n /** Stored episode rows of every heuristic, in episode order. */\n episodes: StoredEpisode[];\n}\n\nexport interface StoredEpisode {\n heuristic: string;\n openedBy: string;\n}\n\nexport interface CompactionRow {\n trigger: string | null;\n midLoop: boolean;\n droppedTokens: number | null;\n}\n\nconst IN_WINDOW = \"(@since IS NULL OR ts >= @since) AND (@until IS NULL OR ts < @until)\";\nconst IN_SESSIONS = \"session_id IN (SELECT value FROM json_each(@ids))\";\n\n// The 5m write column mirrors the view: a split-less write is billed at the 5m rate.\nconst COST_ROWS = `\n SELECT session_id AS sessionId, request_id AS requestId, ts, model, COALESCE(context_tokens, 0) AS contextTokens, is_sidechain AS isSidechain,\n input_tokens AS inputTokens, cache_read_tokens AS cacheReadTokens,\n CASE WHEN cache_creation_5m + cache_creation_1h = 0 THEN cache_creation_tokens ELSE cache_creation_5m END AS cacheWrite5mTokens,\n cache_creation_1h AS cacheWrite1hTokens, output_tokens AS outputTokens,\n input_cost_usd AS inputCostUsd, cache_read_cost_usd AS cacheReadCostUsd,\n cache_write_5m_cost_usd AS cacheWrite5mCostUsd, cache_write_1h_cost_usd AS cacheWrite1hCostUsd,\n output_cost_usd AS outputCostUsd, cost_usd AS costUsd, priced, is_cold AS isCold,\n context_band AS contextBand, gap_band AS gapBand, wake_cause AS wakeCause, wake_delivery AS wakeDelivery\n FROM request_cost WHERE ${IN_WINDOW}\n`;\n\nexport function readCostRows(db: Db, window: ReportWindow): CostRow[] {\n type Row = Omit<CostRow, \"priced\" | \"isCold\" | \"isSidechain\"> & { priced: number; isCold: number; isSidechain: number | null };\n const rows = db.prepare(COST_ROWS).all(window) as Row[];\n return rows.map((row) => ({ ...row, priced: row.priced === 1, isCold: row.isCold === 1, isSidechain: row.isSidechain === 1 }));\n}\n\nexport function readCompactions(db: Db, window: ReportWindow): CompactionRow[] {\n const sql = `SELECT trigger, mid_loop AS midLoop, dropped_tokens AS droppedTokens FROM compaction WHERE ${IN_WINDOW}`;\n const rows = db.prepare(sql).all(window) as (Omit<CompactionRow, \"midLoop\"> & { midLoop: number | null })[];\n return rows.map((row) => ({ ...row, midLoop: row.midLoop === 1 }));\n}\n\n/** The graph's own price version, which is what `request_cost` priced with; null before any price row exists. */\nexport function readPriceTableVersion(db: Db): number | null {\n return (db.prepare(\"SELECT MAX(table_version) AS version FROM price\").get() as { version: number | null }).version;\n}\n\n/** Indexed transcripts, and those whose audit facet is missing or older than `facetVersion`. */\nexport function readCoverage(db: Db, facetVersion: number | null): { transcriptsIndexed: number; facetBacklog: number } {\n const indexed = db.prepare(`SELECT COUNT(*) AS n FROM \"${KIT.watermark}\"`).get() as { n: number };\n const backlog = db\n .prepare(\n `SELECT COUNT(*) AS n FROM \"${KIT.watermark}\" t LEFT JOIN \"${FACET_TABLE}\" f\n ON f.transcript_id = t.source_id AND f.facet = @facet AND (@version IS NULL OR f.version >= @version)\n WHERE f.transcript_id IS NULL`,\n )\n .get({ facet: AUDIT_FACET, version: facetVersion }) as { n: number };\n return { transcriptsIndexed: indexed.n, facetBacklog: backlog.n };\n}\n\n/** An arrival that opens a wake episode: a turn-start record or a mid-loop `queued_command` delivery. */\nexport interface WakeEventRow {\n key: string;\n sessionId: string;\n cause: string;\n delivery: string;\n fromName: string | null;\n /** The same `msg_id` reached more than one session. */\n broadcast: boolean;\n}\n\n/** One agent-chat identity: the name a session carries and how it came to carry it. */\nexport interface AgentNameRow {\n sessionId: string;\n agentName: string;\n originKind: string | null;\n profile: string | null;\n}\n\nconst EPISODE_DELIVERIES = \"('turn_start', 'mid_loop')\";\n\n// A record with several blocks is one event; its last block decides, as the request rollup does.\nconst WAKE_EVENTS = `\n WITH event AS (\n SELECT transcript_id, byte_offset, MAX(block_index) AS block_index FROM inbound\n WHERE ${IN_SESSIONS} AND ${IN_WINDOW} AND delivery IN ${EPISODE_DELIVERIES}\n GROUP BY transcript_id, byte_offset\n ), fanout AS (\n SELECT msg_id, COUNT(DISTINCT session_id) AS receivers FROM inbound\n WHERE msg_id IN (SELECT i.msg_id FROM event JOIN inbound i USING (transcript_id, byte_offset, block_index))\n GROUP BY msg_id\n )\n SELECT i.transcript_id || ':' || i.byte_offset AS key, i.session_id AS sessionId, i.cause, i.delivery,\n i.from_name AS fromName, COALESCE(f.receivers, 1) > 1 AS broadcast\n FROM event JOIN inbound i USING (transcript_id, byte_offset, block_index)\n LEFT JOIN fanout f ON f.msg_id = i.msg_id\n ORDER BY i.transcript_id, i.byte_offset`;\n\nconst REQUEST_EVENTS = `\n SELECT d.request_id AS requestId, d.transcript_id || ':' || (\n SELECT MAX(i.byte_offset) FROM inbound i\n WHERE i.transcript_id = d.transcript_id AND i.session_id = d.session_id AND i.byte_offset < d.byte_offset\n AND i.delivery IN ${EPISODE_DELIVERIES}) AS eventKey\n FROM request_dedup d WHERE d.${IN_SESSIONS} AND (@since IS NULL OR d.ts >= @since) AND (@until IS NULL OR d.ts < @until)`;\n\nexport function readWakeEvents(db: Db, window: ReportWindow, sessionIds: readonly string[]): WakeEventRow[] {\n const rows = db.prepare(WAKE_EVENTS).all({ ...window, ids: JSON.stringify(sessionIds) }) as (Omit<WakeEventRow, \"broadcast\"> & { broadcast: number })[];\n return rows.map((row) => ({ ...row, broadcast: row.broadcast === 1 }));\n}\n\n/** The event each request in the window follows, keyed by `request_id`; null before a transcript's first event. */\nexport function readRequestEvents(db: Db, window: ReportWindow, sessionIds: readonly string[]): Map<string, string | null> {\n const rows = db.prepare(REQUEST_EVENTS).all({ ...window, ids: JSON.stringify(sessionIds) }) as { requestId: string; eventKey: string | null }[];\n return new Map(rows.map((row) => [row.requestId, row.eventKey]));\n}\n\nexport function readAgentNames(db: Db): AgentNameRow[] {\n const sql = `SELECT session_id AS sessionId, agent_name AS agentName, origin_kind AS originKind, profile FROM session_origin WHERE agent_name IS NOT NULL`;\n return db.prepare(sql).all() as AgentNameRow[];\n}\n\n/** Each agent-chat agent id to the sessions it ran as; the broker log names agents by id. */\nexport function readAgentSessions(db: Db): Map<string, string[]> {\n const sql = `SELECT agent_id AS agentId, session_id AS sessionId FROM session_origin WHERE agent_id IS NOT NULL`;\n const sessions = new Map<string, string[]>();\n for (const row of db.prepare(sql).all() as { agentId: string; sessionId: string }[]) sessions.set(row.agentId, [...(sessions.get(row.agentId) ?? []), row.sessionId]);\n return sessions;\n}\n\nexport function readSessionContexts(db: Db, sessionIds: readonly string[]): Map<string, SessionContext> {\n const ids = JSON.stringify(sessionIds);\n const contexts = new Map<string, SessionContext>(sessionIds.map((id) => [id, emptyContext()]));\n addSessionRows(db, ids, contexts);\n addOrigins(db, ids, contexts);\n addInbounds(db, ids, contexts);\n addSignals(db, ids, contexts);\n addTaskInitiatives(db, ids, contexts);\n addLifetimes(db, ids, contexts);\n addEpisodes(db, ids, contexts);\n return contexts;\n}\n\nfunction emptyContext(): SessionContext {\n return { facts: { inboundKinds: [], signalKinds: [], humanTurnCount: 0 }, cwd: null, account: null, tasks: [], lifetimeMs: 0, episodes: [] };\n}\n\nfunction addSessionRows(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, start_type AS startType, cwd, seed_prompt AS seedPrompt, account FROM session WHERE ${IN_SESSIONS}`;\n type Row = { sessionId: string; startType: string | null; cwd: string | null; seedPrompt: string | null; account: string | null };\n for (const row of db.prepare(sql).all({ ids }) as Row[]) {\n const context = contexts.get(row.sessionId)!;\n context.cwd = row.cwd;\n context.account = row.account;\n context.facts.startType = row.startType;\n context.facts.firstUserText = row.seedPrompt;\n }\n}\n\nfunction addOrigins(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, depth, parent_name AS parentName, origin_kind AS originKind, profile FROM session_origin WHERE ${IN_SESSIONS}`;\n type Row = { sessionId: string; depth: number | null; parentName: string | null; originKind: string | null; profile: string | null };\n for (const { sessionId, depth, ...origin } of db.prepare(sql).all({ ids }) as Row[]) {\n contexts.get(sessionId)!.facts.origin = { ...origin, depth: depth ?? 0 };\n }\n}\n\nfunction addInbounds(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, cause, SUM(delivery = 'turn_start') AS turnStarts FROM inbound WHERE ${IN_SESSIONS} GROUP BY session_id, cause`;\n for (const row of db.prepare(sql).all({ ids }) as { sessionId: string; cause: string; turnStarts: number }[]) {\n const facts = contexts.get(row.sessionId)!.facts;\n facts.inboundKinds = [...(facts.inboundKinds ?? []), row.cause];\n if (row.cause === \"human_typed\") facts.humanTurnCount = row.turnStarts;\n }\n}\n\nfunction addSignals(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT DISTINCT session_id AS sessionId, signal FROM session_signal WHERE ${IN_SESSIONS}`;\n for (const row of db.prepare(sql).all({ ids }) as { sessionId: string; signal: string }[]) {\n const facts = contexts.get(row.sessionId)!.facts;\n facts.signalKinds = [...(facts.signalKinds ?? []), row.signal];\n }\n}\n\nfunction addTaskInitiatives(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `\n SELECT substr(e.source_ref, 9) AS sessionId, t.initiative, COUNT(*) AS edges\n FROM \"${KIT.edge}\" e JOIN task t ON t.task_ref = e.target_ref\n WHERE e.relation = 'ran' AND e.t_expired IS NULL AND t.initiative IS NOT NULL\n AND e.source_ref IN (SELECT 'session:' || value FROM json_each(@ids))\n GROUP BY e.source_ref, t.initiative`;\n for (const row of db.prepare(sql).all({ ids }) as ({ sessionId: string } & TaskInitiative)[]) {\n contexts.get(row.sessionId)!.tasks.push({ initiative: row.initiative, edges: row.edges });\n }\n}\n\nfunction addLifetimes(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, MIN(ts) AS first, MAX(ts) AS last FROM request_dedup WHERE ${IN_SESSIONS} AND is_sidechain = 0 GROUP BY session_id`;\n for (const row of db.prepare(sql).all({ ids }) as { sessionId: string; first: string; last: string }[]) {\n contexts.get(row.sessionId)!.lifetimeMs = Date.parse(row.last) - Date.parse(row.first);\n }\n}\n\nfunction addEpisodes(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, heuristic, opened_by AS openedBy FROM \"${EPISODE_TABLE}\" WHERE ${IN_SESSIONS} ORDER BY session_id, heuristic, episode_index`;\n for (const { sessionId, ...episode } of db.prepare(sql).all({ ids }) as ({ sessionId: string } & StoredEpisode)[]) {\n contexts.get(sessionId)!.episodes.push(episode);\n }\n}\n","import { replaceEpisodes, type EpisodeRow, type SessionGraph } from \"@titan-design/session-graph\";\nimport type { Db } from \"@titan-design/store-sqlite\";\nimport { classifySession, type SessionClass } from \"./classify-session.js\";\nimport { readSessionContexts } from \"./cost-report-queries.js\";\n\n/** Two rule sets on purpose (design section 18): workers segment by assignment, coordinators by work phase. */\nexport type Heuristic = \"worker-v1\" | \"coordinator-v1\";\nexport const HEURISTIC_VERSIONS: Readonly<Record<Heuristic, number>> = { \"worker-v1\": 1, \"coordinator-v1\": 1 };\n\nexport interface EpisodeRequest {\n offset: number;\n ts: string;\n transcriptId: number;\n contextTokens: number;\n wakeCause: string | null;\n}\nexport interface EpisodeInbound {\n offset: number;\n ts: string;\n transcriptId: number;\n cause: string;\n}\nexport interface EpisodeSignal {\n offset: number;\n ts: string;\n transcriptId: number;\n signal: string;\n}\nexport interface EpisodeInput {\n requests: readonly EpisodeRequest[];\n inbounds: readonly EpisodeInbound[];\n signals: readonly EpisodeSignal[];\n /** An agent-chat spawn has a brief; anything else opens at `session_start`. */\n spawned: boolean;\n}\n\nconst MINUTE_MS = 60_000;\nexport const IDLE_GAP_MS = 30 * MINUTE_MS;\nexport const CHANNEL_CLUSTER_MS = 10 * MINUTE_MS;\nexport const COORDINATOR_MIN_EPISODE_REQUESTS = 8;\nexport const COORDINATOR_MERGE_DEDUPE_REQUESTS = 15;\nexport const COORDINATOR_WAVE_QUIET_REQUESTS = 15;\nexport const CONTEXT_RESET_TOKENS = 20_000;\nconst DELIVERABLE_SIGNALS = new Set([\"status_report\", \"pr_create\", \"commit\", \"doc_written\", \"task_wrap\"]);\nconst ASSIGNMENT_OPENERS = new Set([\"brief\", \"channel_followup\"]);\n\n/** Pure: the same rows always cut the same way. Rows come back in episode order. */\nexport function buildEpisodes(input: EpisodeInput, heuristic: Heuristic): EpisodeRow[] {\n return heuristic === \"worker-v1\" ? workerEpisodes(input) : coordinatorEpisodes(input);\n}\n\n/** Workers are segmented; human sessions get the coordinator rule; headless runs get none. */\nexport function heuristicFor(sessionClass: SessionClass): Heuristic | null {\n if (sessionClass === \"agent_spawned\") return \"worker-v1\";\n if (sessionClass === \"human_interactive\") return \"coordinator-v1\";\n return null;\n}\n\n/** The worker report's `n_assignments`: episodes an assignment opened, which is what the standing-peer overlay counts. */\nexport function assignmentCount(rows: readonly Pick<EpisodeRow, \"openedBy\">[]): number {\n return rows.filter((row) => ASSIGNMENT_OPENERS.has(row.openedBy)).length;\n}\n\n// ---------------------------------------------------------------- worker-v1\n\ntype Event =\n | { kind: \"request\"; offset: number; ts: string; ms: number; transcriptId: number }\n | { kind: \"inbound\"; offset: number; ts: string; ms: number; transcriptId: number; cause: string }\n | { kind: \"signal\"; offset: number; ts: string; ms: number; transcriptId: number; signal: string };\n\ninterface Draft {\n row: EpisodeRow;\n hasRequest: boolean;\n}\n\ninterface WorkerState {\n drafts: Draft[];\n lastRequestMs: number | null;\n lastChannelMs: number | null;\n}\n\n/** worker-forensics-report.md section 5 and wf_analyze.py:241-251, with the status-report trigger from design section 9. */\nfunction workerEpisodes(input: EpisodeInput): EpisodeRow[] {\n const state: WorkerState = { drafts: [], lastRequestMs: null, lastChannelMs: null };\n for (const event of timeline(input)) {\n const current = state.drafts.at(-1);\n const reason = current ? workerBoundary(event, current, state) : input.spawned ? \"brief\" : \"session_start\";\n if (reason && (!current || current.hasRequest)) state.drafts.push(openDraft(event, reason, state.drafts.length));\n absorb(state.drafts.at(-1)!, event);\n if (event.kind === \"request\") state.lastRequestMs = event.ms;\n if (isChannel(event)) state.lastChannelMs = event.ms;\n }\n return state.drafts.map((draft) => draft.row);\n}\n\nfunction workerBoundary(event: Event, current: Draft, state: WorkerState): string | null {\n if (event.kind === \"request\" && state.lastRequestMs !== null && event.ms - state.lastRequestMs >= IDLE_GAP_MS) return \"idle_gap\";\n if (!isChannel(event)) return null;\n const startsCluster = state.lastChannelMs === null || event.ms - state.lastChannelMs > CHANNEL_CLUSTER_MS;\n return startsCluster && current.row.firstStatusOffset != null ? \"channel_followup\" : null;\n}\n\nfunction isChannel(event: Event): boolean {\n return event.kind === \"inbound\" && event.cause === \"channel_message\";\n}\n\nfunction openDraft(event: Event, openedBy: string, episodeIndex: number): Draft {\n const assignment = ASSIGNMENT_OPENERS.has(openedBy) && event.kind === \"inbound\" ? event.offset : null;\n const row: EpisodeRow = {\n episodeIndex,\n heuristicVersion: HEURISTIC_VERSIONS[\"worker-v1\"],\n startedAt: event.ts,\n endedAt: event.ts,\n startOffset: event.offset,\n endOffset: event.offset,\n openedBy,\n startTranscriptId: event.transcriptId,\n endTranscriptId: event.transcriptId,\n assignmentOffset: assignment,\n firstDeliverableOffset: null,\n firstDeliverableSignal: null,\n firstStatusOffset: null,\n };\n return { row, hasRequest: false };\n}\n\n/** The first commit is recorded as a deliverable but not as a report: commit fires early for implementers (221 of 411). */\nfunction absorb(draft: Draft, event: Event): void {\n draft.row.endedAt = event.ts;\n draft.row.endOffset = event.offset;\n draft.row.endTranscriptId = event.transcriptId;\n if (event.kind === \"request\") draft.hasRequest = true;\n if (event.kind !== \"signal\") return;\n if (draft.row.firstDeliverableOffset == null && DELIVERABLE_SIGNALS.has(event.signal)) {\n draft.row.firstDeliverableOffset = event.offset;\n draft.row.firstDeliverableSignal = event.signal;\n }\n if (draft.row.firstStatusOffset == null && event.signal === \"status_report\") draft.row.firstStatusOffset = event.offset;\n}\n\n/**\n * Offsets only order events inside one transcript, so time orders first, then the transcript a\n * session resumed into, then the offset breaks ties within it.\n */\nfunction timeline(input: EpisodeInput): Event[] {\n const events: Event[] = [\n ...input.requests.map((r) => ({ kind: \"request\" as const, offset: r.offset, ts: r.ts, ms: Date.parse(r.ts), transcriptId: r.transcriptId })),\n ...input.inbounds.map((i) => ({ kind: \"inbound\" as const, offset: i.offset, ts: i.ts, ms: Date.parse(i.ts), transcriptId: i.transcriptId, cause: i.cause })),\n ...input.signals.map((s) => ({ kind: \"signal\" as const, offset: s.offset, ts: s.ts, ms: Date.parse(s.ts), transcriptId: s.transcriptId, signal: s.signal })),\n ];\n return events.sort((a, b) => a.ms - b.ms || a.transcriptId - b.transcriptId || a.offset - b.offset);\n}\n\n// ---------------------------------------------------------------- coordinator-v1\n\ninterface Turn {\n request: EpisodeRequest;\n ms: number;\n signals: Set<string>;\n}\n\ninterface Boundary {\n at: number;\n reason: string;\n}\n\n/** coordinator-forensics-report.md section 1, ported from co_analyze.py `segment` with `merge_lag` 0. */\nfunction coordinatorEpisodes(input: EpisodeInput): EpisodeRow[] {\n const turns = toTurns(input);\n if (turns.length === 0) return [];\n const opens = [{ at: 0, reason: \"session_start\" }, ...dropShort(coordinatorBoundaries(turns), turns.length)];\n return opens.map((open, index) => {\n const first = turns[open.at]!.request;\n const last = turns[(opens[index + 1]?.at ?? turns.length) - 1]!.request;\n return {\n episodeIndex: index,\n heuristicVersion: HEURISTIC_VERSIONS[\"coordinator-v1\"],\n startedAt: first.ts,\n endedAt: last.ts,\n startOffset: first.offset,\n endOffset: last.offset,\n startTranscriptId: first.transcriptId,\n endTranscriptId: last.transcriptId,\n openedBy: open.reason,\n };\n });\n}\n\nfunction coordinatorBoundaries(turns: readonly Turn[]): Boundary[] {\n const bounds: Boundary[] = [];\n let spawnedSince = false;\n let lastMerge = -Infinity;\n for (let i = 1; i < turns.length; i++) {\n const reason = coordinatorTrigger(turns, i, lastMerge) ?? (spawnedSince && waveComplete(turns, i) ? \"spawn_wave_complete\" : null);\n if (turns[i - 1]!.signals.has(\"pr_merge\")) lastMerge = i;\n if (reason) {\n bounds.push({ at: i, reason });\n spawnedSince = false;\n }\n if (turns[i]!.signals.has(\"agent_spawn\")) spawnedSince = true;\n }\n return bounds;\n}\n\n/** Checked in the source's order; the first that fires names the boundary. */\nfunction coordinatorTrigger(turns: readonly Turn[], i: number, lastMerge: number): string | null {\n const [a, b] = [turns[i - 1]!, turns[i]!];\n if (b.ms - a.ms >= IDLE_GAP_MS) return \"idle_gap\";\n if (a.signals.has(\"pr_merge\") && i - lastMerge > COORDINATOR_MERGE_DEDUPE_REQUESTS) return \"pr_merge\";\n if (a.signals.has(\"task_wrap\") || a.signals.has(\"task_done\")) return \"task_wrap\";\n const drop = a.request.contextTokens - b.request.contextTokens;\n if (a.request.contextTokens > 0 && drop > CONTEXT_RESET_TOKENS) return \"context_reset\";\n return null;\n}\n\n/** The last agent-chat traffic before a quiet run; the source also counted any agent-chat tool call, which only reaches the graph as `chat_send` or `agent_spawn`. */\nfunction waveComplete(turns: readonly Turn[], i: number): boolean {\n return hasChatTraffic(turns[i - 1]!) && !turns.slice(i, i + COORDINATOR_WAVE_QUIET_REQUESTS).some(hasChatTraffic);\n}\n\nfunction hasChatTraffic(turn: Turn): boolean {\n return turn.request.wakeCause === \"channel_message\" || turn.signals.has(\"chat_send\") || turn.signals.has(\"agent_spawn\");\n}\n\n/** No episode shorter than the minimum, at either end of the session. */\nfunction dropShort(bounds: readonly Boundary[], total: number): Boundary[] {\n const kept: Boundary[] = [];\n let last = 0;\n for (const bound of bounds) {\n if (bound.at - last < COORDINATOR_MIN_EPISODE_REQUESTS || total - bound.at < COORDINATOR_MIN_EPISODE_REQUESTS) continue;\n kept.push(bound);\n last = bound.at;\n }\n return kept;\n}\n\n/** A signal belongs to the latest request at or before it; one before any request goes to the first. */\nfunction toTurns(input: EpisodeInput): Turn[] {\n const turns = input.requests\n .map((request) => ({ request, ms: Date.parse(request.ts), signals: new Set<string>() }))\n .sort((a, b) => a.ms - b.ms || a.request.transcriptId - b.request.transcriptId || a.request.offset - b.request.offset);\n for (const signal of input.signals) ownerOf(turns, signal)?.signals.add(signal.signal);\n return turns;\n}\n\nfunction ownerOf(turns: readonly Turn[], signal: EpisodeSignal): Turn | undefined {\n const ms = Date.parse(signal.ts);\n for (let i = turns.length - 1; i >= 0; i--) {\n const turn = turns[i]!;\n if (turn.ms < ms || (turn.ms === ms && turn.request.offset <= signal.offset)) return turn;\n }\n return turns[0];\n}\n\n// ---------------------------------------------------------------- graph I/O\n\nconst IN_SESSION = \"session_id = ?\";\n\n/**\n * `request_dedup` for one session without ranking every request: SQLite cannot push the session filter\n * through the view's window. Copies of a request can sit in other sessions, so the rank still covers\n * every copy of each request id the session holds.\n */\nconst SESSION_REQUEST_DEDUP = `\n SELECT * FROM (\n SELECT r.*, ROW_NUMBER() OVER (PARTITION BY r.request_id ORDER BY r.ts, r.transcript_id) AS copy_rank\n FROM request r WHERE r.request_id IN (SELECT request_id FROM request WHERE session_id = @sessionId)\n ) WHERE copy_rank = 1 AND session_id = @sessionId`;\n\n/** Main-thread requests only: a sidechain's requests belong to its subagent, not to the session's episodes. */\nexport const EPISODE_REQUESTS_SQL = `\n SELECT byte_offset AS offset, ts, transcript_id AS transcriptId, context_tokens AS contextTokens, wake_cause AS wakeCause\n FROM (${SESSION_REQUEST_DEDUP}) WHERE is_sidechain = 0`;\n\nexport function readEpisodeInput(db: Db, sessionId: string, spawned: boolean): EpisodeInput {\n const requests = db.prepare(EPISODE_REQUESTS_SQL).all({ sessionId }) as EpisodeRequest[];\n const inbounds = db\n .prepare(`SELECT byte_offset AS offset, ts, transcript_id AS transcriptId, cause FROM inbound WHERE ${IN_SESSION}`)\n .all(sessionId) as EpisodeInbound[];\n const signals = db\n .prepare(`SELECT byte_offset AS offset, ts, transcript_id AS transcriptId, signal FROM session_signal WHERE ${IN_SESSION}`)\n .all(sessionId) as EpisodeSignal[];\n return { requests, inbounds, signals, spawned };\n}\n\nexport interface WrittenEpisodes {\n sessionId: string;\n heuristic: Heuristic;\n episodes: number;\n}\n\n/** Segments each session with its class's heuristic and replaces that heuristic's rows. Headless sessions are skipped. */\nexport function writeEpisodes(graph: SessionGraph, sessionIds: readonly string[]): WrittenEpisodes[] {\n const written: WrittenEpisodes[] = [];\n for (const [sessionId, context] of readSessionContexts(graph.db, sessionIds)) {\n const { sessionClass } = classifySession(context.facts);\n const heuristic = heuristicFor(sessionClass);\n if (!heuristic) continue;\n const rows = buildEpisodes(readEpisodeInput(graph.db, sessionId, sessionClass === \"agent_spawned\"), heuristic);\n written.push({ sessionId, heuristic, episodes: replaceEpisodes(graph, sessionId, heuristic, rows) });\n }\n return written;\n}\n","import { z } from \"zod\";\nimport { priceRequest, type RequestTokens } from \"./price-request.js\";\nimport { PRICE_TABLE, findPrice, type PriceRow } from \"./prices.js\";\nimport type { ActionCall } from \"./turn-action.js\";\n\n/** A dispatch or a send; with any file write, the first such request ends a session's boot. */\nexport const BOOT_TOOL = /(agent_(spawn|resume)|chat_(send|broadcast))$/;\n\n/** The charter's `teleport_k` and `retire_k` at the time of the TP-499 plan; callers pass their own. */\nexport const DEFAULT_CONFIGURED_K: readonly number[] = [170_000, 250_000];\nexport const DEFAULT_K_SWEEP = { fromK: 20_000, toK: 1_000_000, stepK: 5_000 } as const;\nexport const DEFAULT_REVIEWER_ROLE = \"worker:reviewer\";\nexport const DEFAULT_STANDING_ROLE = \"worker:standing_peer\";\nexport const DEFAULT_REVIEWER_PRS = 10;\n/** The broker logs this when a seat starts handing over; `from` is the outgoing agent id. */\nexport const TELEPORT_EVENT = \"teleport_started\";\n\nconst MTOK = 1_000_000;\nconst count = z.number().int().nonnegative();\nconst kCostSchema = z.object({ k: count, costPerRequest: z.number().nullable(), deltaPerRequest: z.number().nullable() });\nconst sweepResultSchema = z.object({ bestK: count.nullable(), bestCostPerRequest: z.number().nullable(), atConfigured: z.array(kCostSchema) });\nconst paramsSchema = z.object({ bootCostUsd: z.number(), bootFill: z.number(), growthPerRequest: z.number(), readPricePerMTok: z.number() });\n\nconst sessionSchema = paramsSchema.extend({\n sessionId: z.string(),\n role: z.string(),\n model: z.string(),\n requests: count,\n bootRequests: count,\n exitFill: count,\n /** Timestamp of the session's last request; orders reviewer cohorts by recency. */\n lastTs: z.string(),\n bestK: count.nullable(),\n});\nconst cohortSchema = paramsSchema.extend({\n role: z.string(),\n model: z.string(),\n sessions: count,\n ...sweepResultSchema.shape,\n /** The same sweep when only half the boot is overhead the next session pays again. */\n halfBoot: sweepResultSchema,\n});\nconst teleportSchema = z.object({\n ts: z.string(),\n name: z.string().nullable(),\n sessionId: z.string(),\n role: z.string(),\n model: z.string(),\n exitFill: count,\n bestK: count.nullable(),\n /** Exit fill minus each configured K; positive means the seat left late. */\n overConfigured: z.array(z.object({ k: count, over: z.number() })),\n});\n/** `requestsFrom` when the report has no reviewer session at all, so requests per PR is 0. */\nexport const POOLED_REVIEWERS = \"pooled\";\nconst reviewerCostSchema = z.object({\n role: z.string(),\n model: z.string(),\n sessions: count,\n /** Mean requests after boot of a per-PR reviewer: the work each PR adds. */\n requestsPerPr: z.number(),\n /** The reviewer model whose sessions give `requestsPerPr`: the row's own, else the newest reviewer cohort; `pooled` with none. */\n requestsFrom: z.string(),\n costUsd: z.number(),\n});\nconst reviewerSchema = z.object({ prs: count, fresh: z.array(reviewerCostSchema), standing: z.array(reviewerCostSchema) });\n\nexport const handoffThresholdSchema = z.object({\n configuredK: z.array(count),\n sweep: z.object({ fromK: count, toK: count, stepK: count }),\n cohorts: z.array(cohortSchema),\n sessions: z.array(sessionSchema),\n /** Sessions with no dispatch, send or write, or none priced: they have no boot to measure. */\n unbootedSessions: count,\n teleports: z.array(teleportSchema),\n unmatchedTeleports: count,\n /** Boot and cache reads for `prs` reviews: a fresh reviewer per PR against one standing reviewer. */\n reviewers: reviewerSchema,\n});\n\nexport type HandoffThreshold = z.infer<typeof handoffThresholdSchema>;\nexport type HandoffCohort = z.infer<typeof cohortSchema>;\nexport type HandoffSession = z.infer<typeof sessionSchema>;\nexport type HandoffTeleport = z.infer<typeof teleportSchema>;\nexport type ReviewerComparison = z.infer<typeof reviewerSchema>;\nexport type CycleParams = z.infer<typeof paramsSchema>;\nexport type KSweep = HandoffThreshold[\"sweep\"];\n\n/** One main-thread request as the handoff model needs it. */\nexport interface HandoffRequestRow {\n sessionId: string;\n role: string;\n model: string;\n ts: string;\n /** Tokens in context: input, cache reads and cache writes. */\n fill: number;\n tokens: RequestTokens;\n bootAction: boolean;\n}\n\nexport interface TeleportEvent {\n ts: string;\n name: string | null;\n fromAgentId: string;\n}\n\nexport interface HandoffOptions {\n configuredK?: readonly number[];\n sweep?: KSweep;\n reviewerRole?: string;\n /** The role whose boot, fill and growth price a reviewer that stays up across PRs. */\n standingRole?: string;\n reviewerPrs?: number;\n /** Prices every request and the read rate; the package table, not the graph's stored one. */\n prices?: readonly PriceRow[];\n}\n\nexport function isBootAction(calls: readonly ActionCall[]): boolean {\n return calls.some((call) => BOOT_TOOL.test(call.tool) || (call.writePaths?.length ?? 0) > 0);\n}\n\n/** Broker log lines to teleport starts; any other line, or one that is not JSON, is skipped. */\nexport function parseTeleportEvents(lines: Iterable<string>): TeleportEvent[] {\n const events: TeleportEvent[] = [];\n for (const line of lines) {\n const entry = parseJson(line);\n if (entry?.event !== TELEPORT_EVENT || typeof entry.from !== \"string\" || typeof entry.ts !== \"string\") continue;\n events.push({ ts: entry.ts, name: typeof entry.name === \"string\" ? entry.name : null, fromAgentId: entry.from });\n }\n return events;\n}\n\nfunction parseJson(line: string): Record<string, unknown> | null {\n try {\n const value: unknown = JSON.parse(line);\n return typeof value === \"object\" && value !== null ? (value as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\n/** One cycle boots to f0 and grows g per request up to K: boot/n + read price x mean fill, with n = (K - f0) / g. */\nexport function costPerRequest(params: CycleParams, k: number): number | null {\n const requests = (k - params.bootFill) / params.growthPerRequest;\n if (!(params.growthPerRequest > 0) || requests < 1) return null;\n return params.bootCostUsd / requests + (params.readPricePerMTok / MTOK) * ((params.bootFill + k) / 2);\n}\n\n/** The cheapest K on the sweep grid, then each configured K against it. */\nexport function sweepK(params: CycleParams, sweep: KSweep, configuredK: readonly number[]): z.infer<typeof sweepResultSchema> {\n let best: { k: number; cost: number } | null = null;\n for (let k = sweep.fromK; k <= sweep.toK; k += sweep.stepK) {\n const cost = costPerRequest(params, k);\n if (cost !== null && (best === null || cost < best.cost)) best = { k, cost };\n }\n const atConfigured = configuredK.map((k) => {\n const cost = costPerRequest(params, k);\n return { k, costPerRequest: cost, deltaPerRequest: cost === null || best === null ? null : cost - best.cost };\n });\n return { bestK: best?.k ?? null, bestCostPerRequest: best?.cost ?? null, atConfigured };\n}\n\n/** Per role and model: boot cost and fill, fill growth and read price from the requests, then the K sweep. */\nexport function handoffThreshold(rows: readonly HandoffRequestRow[], teleports: readonly TeleportEvent[], agentSessions: ReadonlyMap<string, readonly string[]>, options: HandoffOptions = {}): HandoffThreshold {\n const configuredK = [...(options.configuredK ?? DEFAULT_CONFIGURED_K)];\n const sweep = { ...(options.sweep ?? DEFAULT_K_SWEEP) };\n const bySession = groupBy(rows, (row) => row.sessionId);\n const fits = [...bySession.values()].map((requests) => fitSession(requests, options.prices ?? PRICE_TABLE, sweep));\n const sessions = fits.filter((fit): fit is HandoffSession => fit !== null).sort((a, b) => a.sessionId.localeCompare(b.sessionId));\n const cohorts = cohortsOf(sessions, sweep, configuredK);\n const matched = teleports.map((event) => teleportExit(event, agentSessions, bySession, cohorts, configuredK)).filter((t): t is HandoffTeleport => t !== null);\n return {\n configuredK,\n sweep,\n cohorts,\n sessions,\n unbootedSessions: fits.length - sessions.length,\n teleports: matched.sort((a, b) => a.ts.localeCompare(b.ts)),\n unmatchedTeleports: teleports.length - matched.length,\n reviewers: reviewerComparison(sessions, options.reviewerRole ?? DEFAULT_REVIEWER_ROLE, options.standingRole ?? DEFAULT_STANDING_ROLE, options.reviewerPrs ?? DEFAULT_REVIEWER_PRS),\n };\n}\n\nfunction fitSession(unsorted: readonly HandoffRequestRow[], prices: readonly PriceRow[], sweep: KSweep): HandoffSession | null {\n const requests = [...unsorted].sort((a, b) => a.ts.localeCompare(b.ts));\n const first = requests[0]!;\n const bootIndex = requests.findIndex((row) => row.bootAction);\n const price = findPrice(first.model, first.ts, prices);\n if (bootIndex < 0 || price === null) return null;\n const params: CycleParams = {\n bootCostUsd: requests.slice(0, bootIndex + 1).reduce((sum, row) => sum + priceRequest(row.tokens, row.model, row.ts, prices).costUsd, 0),\n bootFill: requests[bootIndex]!.fill,\n growthPerRequest: meanGrowth(requests.slice(bootIndex).map((row) => row.fill)),\n readPricePerMTok: price.cacheRead,\n };\n const { sessionId, role, model } = first;\n const last = requests[requests.length - 1]!;\n return { sessionId, role, model, requests: requests.length, bootRequests: bootIndex + 1, exitFill: last.fill, lastTs: last.ts, ...params, bestK: sweepK(params, sweep, []).bestK };\n}\n\n/** Rises only, so a compaction's drop does not cancel the growth before it; zero with no request after boot. */\nfunction meanGrowth(fills: readonly number[]): number {\n if (fills.length < 2) return 0;\n let rise = 0;\n for (let i = 1; i < fills.length; i += 1) rise += Math.max(0, fills[i]! - fills[i - 1]!);\n return rise / (fills.length - 1);\n}\n\n/** Session means per role and model; a model's read price differs, so it splits the role. */\nfunction cohortsOf(sessions: readonly HandoffSession[], sweep: KSweep, configuredK: readonly number[]): HandoffCohort[] {\n return [...groupBy(sessions, (s) => JSON.stringify([s.role, s.model]))]\n .map(([, members]) => {\n const params = meanParams(members);\n return {\n role: members[0]!.role,\n model: members[0]!.model,\n sessions: members.length,\n ...params,\n ...sweepK(params, sweep, configuredK),\n halfBoot: sweepK({ ...params, bootCostUsd: params.bootCostUsd / 2 }, sweep, configuredK),\n };\n })\n .sort((a, b) => a.role.localeCompare(b.role) || a.model.localeCompare(b.model));\n}\n\nfunction meanParams(sessions: readonly HandoffSession[]): CycleParams {\n const mean = (pick: (s: HandoffSession) => number) => sessions.reduce((sum, s) => sum + pick(s), 0) / sessions.length;\n return {\n bootCostUsd: mean((s) => s.bootCostUsd),\n bootFill: mean((s) => s.bootFill),\n growthPerRequest: meanGrowthOf(sessions),\n readPricePerMTok: mean((s) => s.readPricePerMTok),\n };\n}\n\n/** Sessions with no request after boot have g = 0; counting them would dilute the growth of those that grew. */\nfunction meanGrowthOf(sessions: readonly HandoffSession[]): number {\n const grown = sessions.filter((s) => s.growthPerRequest > 0);\n return grown.length === 0 ? 0 : grown.reduce((sum, s) => sum + s.growthPerRequest, 0) / grown.length;\n}\n\n/** The fill of the outgoing session's last request at or before the teleport. */\nfunction teleportExit(\n event: TeleportEvent,\n agentSessions: ReadonlyMap<string, readonly string[]>,\n bySession: ReadonlyMap<string, readonly HandoffRequestRow[]>,\n cohorts: readonly HandoffCohort[],\n configuredK: readonly number[],\n): HandoffTeleport | null {\n const candidates = (agentSessions.get(event.fromAgentId) ?? []).flatMap((id) => bySession.get(id) ?? []);\n const exit = candidates.filter((row) => row.ts <= event.ts).sort((a, b) => b.ts.localeCompare(a.ts))[0];\n if (!exit) return null;\n const cohort = cohorts.find((c) => c.role === exit.role && c.model === exit.model);\n return {\n ts: event.ts,\n name: event.name,\n sessionId: exit.sessionId,\n role: exit.role,\n model: exit.model,\n exitFill: exit.fill,\n bestK: cohort?.bestK ?? null,\n overConfigured: configuredK.map((k) => ({ k, over: exit.fill - k })),\n };\n}\n\n/** Reads over m requests from f0 growing g each: m f0 + g m(m + 1) / 2 tokens at the read price. */\nfunction readCost(params: CycleParams, requests: number): number {\n return ((requests * params.bootFill + (params.growthPerRequest * requests * (requests + 1)) / 2) * params.readPricePerMTok) / MTOK;\n}\n\n/** Fresh: every PR pays a boot and its own reads. Standing: one boot, then every PR's requests read the context the earlier ones left. */\nfunction reviewerComparison(sessions: readonly HandoffSession[], reviewerRole: string, standingRole: string, prs: number): ReviewerComparison {\n const cohorts = (role: string) => [...groupBy(sessions.filter((s) => s.role === role), (s) => s.model)].sort(([a], [b]) => a.localeCompare(b));\n const reviewers = cohorts(reviewerRole);\n const perPr = new Map(reviewers.map(([model, members]) => [model, meanRequestsAfterBoot(members)]));\n const newest = newestCohort(reviewers);\n const priced = (role: string, costOf: (params: CycleParams, requests: number) => number) =>\n cohorts(role).map(([model, members]) => {\n const from = perPr.has(model) ? model : newest;\n const requestsPerPr = from === null ? 0 : perPr.get(from)!;\n return { role, model, sessions: members.length, requestsPerPr, requestsFrom: from ?? POOLED_REVIEWERS, costUsd: costOf(meanParams(members), requestsPerPr) };\n });\n return {\n prs,\n fresh: priced(reviewerRole, (params, requests) => prs * (params.bootCostUsd + readCost(params, requests))),\n standing: priced(standingRole, (params, requests) => params.bootCostUsd + readCost(params, prs * requests)),\n };\n}\n\n/** The reviewer model whose latest session is newest; a tie goes to the later model name. */\nfunction newestCohort(reviewers: readonly (readonly [string, readonly HandoffSession[]])[]): string | null {\n const latest = reviewers.map(([model, members]) => ({ model, ts: members.reduce((max, s) => (s.lastTs > max ? s.lastTs : max), \"\") }));\n latest.sort((a, b) => b.ts.localeCompare(a.ts) || b.model.localeCompare(a.model));\n return latest[0]?.model ?? null;\n}\n\nfunction meanRequestsAfterBoot(sessions: readonly HandoffSession[]): number {\n return sessions.length === 0 ? 0 : sessions.reduce((sum, s) => sum + s.requests - s.bootRequests, 0) / sessions.length;\n}\n\nfunction groupBy<T>(rows: readonly T[], keyOf: (row: T) => string): Map<string, T[]> {\n const groups = new Map<string, T[]>();\n for (const row of rows) {\n const key = keyOf(row);\n const members = groups.get(key);\n if (members) members.push(row);\n else groups.set(key, [row]);\n }\n return groups;\n}\n","/** Initiatives a session's task edges name, with how many edges name each. */\nexport interface TaskInitiative {\n initiative: string;\n edges: number;\n}\n\n/**\n * A task edge names the initiative outright, so it wins over the cwd guess. Among several,\n * the most-named initiative wins and a tie goes to the alphabetically first, for a stable report.\n */\nexport function sessionInitiative(tasks: readonly TaskInitiative[], cwd: string | null | undefined): string {\n const best = [...tasks].sort((a, b) => b.edges - a.edges || a.initiative.localeCompare(b.initiative))[0];\n return best ? best.initiative : initiativeFromCwd(cwd);\n}\n\n/** The cwd rule from `cf_analyze.py` `initiative()`. A worktree under a repo counts as that repo. */\nexport function initiativeFromCwd(cwd: string | null | undefined): string {\n if (!cwd) return \"unknown\";\n const repo = /\\/projects\\/([^/]+)/.exec(cwd);\n if (repo) return `repo:${repo[1]}`;\n const activeWork = /active-work\\/([^/]+)/.exec(cwd);\n if (activeWork) return `active-work:${activeWork[1]}`;\n if (/ac-fork-\\w+/.test(cwd)) return \"ac-fork(tmp)\";\n const trimmed = cwd.replace(/\\/+$/, \"\");\n return `other:${trimmed.slice(trimmed.lastIndexOf(\"/\") + 1)}`;\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport type { ReportWindow } from \"./cost-report-queries.js\";\nimport type { ActionCall } from \"./turn-action.js\";\n\n/** The signals session-read extracts per tool use that the action classifier reads. */\nconst CALL_SIGNALS = { command_heads: \"heads\", file_read: \"readPaths\", file_write: \"writePaths\" } as const;\ntype CallSignal = keyof typeof CALL_SIGNALS;\n\n/**\n * A tool_use line follows the first line of the request that issued it, so the owner is the latest\n * request at or before it; context_contribution maps the other way, to the request it feeds.\n * Joining owners to request_dedup drops every fan-out copy along with its tool calls.\n */\nconst OWNED_CALLS = `\n WITH scope AS (\n SELECT DISTINCT transcript_id FROM request_dedup\n WHERE (@since IS NULL OR ts >= @since) AND (@until IS NULL OR ts < @until)\n ), stream AS (\n SELECT transcript_id, byte_offset, -1 AS lane, 0 AS block_index, request_id, NULL AS tool_use_id, NULL AS name\n FROM request WHERE transcript_id IN (SELECT transcript_id FROM scope)\n UNION ALL\n SELECT transcript_id, byte_offset, 0, block_index, NULL, tool_use_id, name\n FROM tool_call WHERE transcript_id IN (SELECT transcript_id FROM scope)\n ), ordered AS (\n SELECT *, COUNT(request_id) OVER (PARTITION BY transcript_id ORDER BY byte_offset, lane, block_index ROWS UNBOUNDED PRECEDING) AS requests_seen\n FROM stream\n ), owned AS (\n SELECT c.transcript_id, c.byte_offset, c.block_index, c.tool_use_id, c.name, r.request_id\n FROM ordered c JOIN ordered r ON r.transcript_id = c.transcript_id AND r.lane = -1 AND r.requests_seen = c.requests_seen\n WHERE c.lane = 0\n )\n SELECT o.request_id AS requestId, o.transcript_id || ':' || o.byte_offset || ':' || o.block_index AS callKey, o.name AS tool, s.signal, s.detail\n FROM owned o\n JOIN request_dedup d ON d.transcript_id = o.transcript_id AND d.request_id = o.request_id\n LEFT JOIN session_signal s ON s.transcript_id = o.transcript_id AND s.tool_use_id = o.tool_use_id\n AND s.signal IN ('command_heads', 'file_read', 'file_write')\n WHERE (@since IS NULL OR d.ts >= @since) AND (@until IS NULL OR d.ts < @until)\n ORDER BY o.transcript_id, o.byte_offset, o.block_index\n`;\n\ninterface OwnedRow {\n requestId: string;\n callKey: string;\n tool: string;\n signal: CallSignal | null;\n detail: string | null;\n}\n\n/** The tool calls each request in the window issued, keyed by `request_id`; a request with none is absent. */\nexport function readRequestToolCalls(db: Db, window: ReportWindow): Map<string, ActionCall[]> {\n const byRequest = new Map<string, Map<string, ActionCall>>();\n for (const row of db.prepare(OWNED_CALLS).all(window) as OwnedRow[]) {\n const calls = byRequest.get(row.requestId) ?? new Map<string, ActionCall>();\n byRequest.set(row.requestId, calls);\n const call = calls.get(row.callKey) ?? { tool: row.tool };\n calls.set(row.callKey, row.signal ? withSignal(call, row.signal, row.detail ?? \"\") : call);\n }\n return new Map([...byRequest].map(([requestId, calls]) => [requestId, [...calls.values()]]));\n}\n\n/** `command_heads` is one `;`-joined string per Bash call; file signals carry one path each. */\nfunction withSignal(call: ActionCall, signal: CallSignal, detail: string): ActionCall {\n const field = CALL_SIGNALS[signal];\n const values = signal === \"command_heads\" ? detail.split(\";\").filter(Boolean) : [detail];\n return { ...call, [field]: [...(call[field] ?? []), ...values] };\n}\n","import type { SessionClassification } from \"./classify-session.js\";\n\n/** worker-v1's role vocabulary, from worker-forensics-report.md section 2. */\nexport type WorkerRole = \"implementer\" | \"reviewer\" | \"researcher\" | \"planner\" | \"coordinator\" | \"standing_peer\" | \"unknown\";\n\n/** Spawn profile to role, as the worker report's table (wf_analyze.py:79-91) maps it. */\nexport const PROFILE_ROLES: Readonly<Record<string, WorkerRole>> = {\n implementer: \"implementer\",\n \"implementer-lite\": \"implementer\",\n \"relay-implementer\": \"implementer\",\n \"beat-builder\": \"implementer\",\n \"fable-optimizer\": \"implementer\",\n \"bd-implementer\": \"implementer\",\n \"bd-implementer-lite\": \"implementer\",\n reviewer: \"reviewer\",\n \"relay-reviewer\": \"reviewer\",\n \"bd-reviewer\": \"reviewer\",\n researcher: \"researcher\",\n explorer: \"researcher\",\n \"fable-architect\": \"planner\",\n planner: \"planner\",\n \"bd-planner\": \"planner\",\n \"fable-coordinator\": \"coordinator\",\n \"opus-coordinator\": \"coordinator\",\n peer: \"standing_peer\",\n};\n\nexport const STANDING_PEER_MIN_HOURS = 12;\nexport const STANDING_PEER_MIN_ASSIGNMENTS = 2;\nconst HOUR_MS = 3_600_000;\n\nexport interface WorkerFacts {\n profile?: string | null;\n /** First request to last request, over the whole session rather than a report window. */\n lifetimeMs: number;\n /** worker-v1 episodes opened by an assignment (the brief or a channel follow-up), not by an idle gap. */\n assignments: number;\n}\n\nexport function roleFromProfile(profile: string | null | undefined): WorkerRole {\n return PROFILE_ROLES[(profile ?? \"\").toLowerCase()] ?? \"unknown\";\n}\n\n/** A worker that outlives its first assignment is a standing peer whatever it was spawned as (wf_analyze.py:94-103). */\nexport function workerRole(facts: WorkerFacts): WorkerRole {\n const outlived = facts.lifetimeMs >= STANDING_PEER_MIN_HOURS * HOUR_MS && facts.assignments >= STANDING_PEER_MIN_ASSIGNMENTS;\n return outlived ? \"standing_peer\" : roleFromProfile(facts.profile);\n}\n\n/** The report's role key: `coordinator` or `adhoc` for humans, `worker:<role>` for spawned agents, else the class. */\nexport function sessionRole(classification: SessionClassification, worker: WorkerFacts): string {\n if (classification.humanRole) return classification.humanRole;\n if (classification.sessionClass === \"agent_spawned\") return `worker:${workerRole(worker)}`;\n return classification.sessionClass;\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { readAgentNames } from \"./cost-report-queries.js\";\n\n/**\n * Narrows a report to some sessions. Every field left out matches all, and fields combine with AND.\n * Compactions and coverage stay window-wide: the graph does not key them to a request.\n */\nexport interface ReportScope {\n sessionIds?: readonly string[];\n /** Keeps sessions whose agent-chat agent name starts with it. */\n agentPrefix?: string;\n /** Report roles, as `byRole` names them. */\n roles?: readonly string[];\n}\n\n/** A predicate over a request's session and role; with no scope every request passes. */\nexport function scopeFilter(db: Db, scope: ReportScope = {}): (row: { sessionId: string; role: string }) => boolean {\n const ids = scope.sessionIds ? new Set(scope.sessionIds) : null;\n const named = scope.agentPrefix === undefined ? null : agentSessions(db, scope.agentPrefix);\n const roles = scope.roles ? new Set(scope.roles) : null;\n return (row) => (!ids || ids.has(row.sessionId)) && (!named || named.has(row.sessionId)) && (!roles || roles.has(row.role));\n}\n\nfunction agentSessions(db: Db, prefix: string): Set<string> {\n return new Set(readAgentNames(db).filter((row) => row.agentName.startsWith(prefix)).map((row) => row.sessionId));\n}\n","export const ACTION_CLASSES = [\n \"journal-write\",\n \"pr-ci-check\",\n \"merge\",\n \"dispatch\",\n \"retire\",\n \"task-state\",\n \"budget-status\",\n \"scorer\",\n \"message\",\n \"read-investigate\",\n \"text-only\",\n \"other\",\n] as const;\n\nexport type ActionClass = (typeof ACTION_CLASSES)[number];\n\n/** One tool call of a request, with the signals session-read extracted for it. */\nexport interface ActionCall {\n tool: string;\n /** Command heads of a Bash call, such as `gh pr checks`. */\n heads?: readonly string[];\n readPaths?: readonly string[];\n writePaths?: readonly string[];\n}\n\n/** A rule matches a call when every field it sets matches; list order is the precedence. */\nexport interface ActionRule {\n cls: ActionClass;\n tool?: RegExp;\n head?: RegExp;\n readPath?: RegExp;\n writePath?: RegExp;\n}\n\n/** A basename naming a log, journal or event file, so `catalog.md`, `CHANGELOG.md` and `fixture.jsonl` stay out. */\nconst JOURNAL_BASENAME = String.raw`(?:(?:[^/]*[-_.])?(?:log|journal|events?)(?:[-_.][^/]*)?\\.(?:md|jsonl)|[^/]*journal[^/]*)$`;\nconst INTERPRETER = String.raw`(?:(?:python3?|node|tsx|bash|sh) )?`;\n\nexport const DEFAULT_ACTION_RULES: readonly ActionRule[] = [\n { cls: \"journal-write\", writePath: new RegExp(String.raw`(?:^|/)${JOURNAL_BASENAME}`, \"i\") },\n { cls: \"journal-write\", head: new RegExp(`^>(?:[^/]*/)?${JOURNAL_BASENAME}`, \"i\") },\n { cls: \"pr-ci-check\", head: /^gh pr (checks|view)\\b/ },\n { cls: \"pr-ci-check\", head: /^gh run\\b/ },\n { cls: \"pr-ci-check\", head: /^git merge-tree\\b/ },\n { cls: \"pr-ci-check\", head: /^gh api GET commits\\/check-runs$/ },\n { cls: \"pr-ci-check\", head: /^gh api GET commits\\/status$/ },\n { cls: \"merge\", head: /^gh pr merge\\b/ },\n { cls: \"merge\", head: /^gh api PUT pulls\\/merge$/ },\n { cls: \"dispatch\", tool: /agent_(spawn|resume)$/ },\n { cls: \"retire\", head: /^(agent-chat )?agent retire\\b/ },\n { cls: \"task-state\", head: /^active-work task\\b/ },\n { cls: \"budget-status\", tool: /(session_budget|chat_status)$/ },\n { cls: \"budget-status\", head: /^(agent-chat )?agent list\\b/ },\n { cls: \"budget-status\", head: /^(agent-chat )?agent (ls|budget|worktrees)\\b/ },\n { cls: \"budget-status\", head: /^git worktree list\\b/ },\n { cls: \"budget-status\", tool: /(agent_list|chat_list|ListAgents)$/ },\n { cls: \"scorer\", tool: /(^|__)scor/i },\n { cls: \"scorer\", head: new RegExp(`^${INTERPRETER}[\\\\w.-]*scor`, \"i\") },\n { cls: \"message\", tool: /chat_send$/ },\n { cls: \"message\", tool: /(chat_ask|chat_inbox|chat_claim|chat_release)$/ },\n { cls: \"read-investigate\", tool: /^(Read|Grep|Glob)$/ },\n { cls: \"read-investigate\", head: /^(cat|ls|grep|rg|head|tail|find|wc|git (log|diff|show|status))\\b/ },\n];\n\n/** Dispatch is judgment about what to hand out, so it stays out of the mechanical list. */\nexport const DEFAULT_MECHANICAL_CLASSES: readonly ActionClass[] = [\n \"journal-write\",\n \"pr-ci-check\",\n \"task-state\",\n \"budget-status\",\n \"retire\",\n \"merge\",\n \"scorer\",\n];\n\nfunction callMatches(call: ActionCall, rule: ActionRule): boolean {\n if (rule.tool && !rule.tool.test(call.tool)) return false;\n if (rule.head && !(call.heads ?? []).some((h) => rule.head?.test(h))) return false;\n if (rule.readPath && !(call.readPaths ?? []).some((p) => rule.readPath?.test(p))) return false;\n if (rule.writePath && !(call.writePaths ?? []).some((p) => rule.writePath?.test(p))) return false;\n return true;\n}\n\nexport function classifyRequest(\n calls: readonly ActionCall[],\n rules: readonly ActionRule[] = DEFAULT_ACTION_RULES,\n): ActionClass {\n if (calls.length === 0) return \"text-only\";\n const hit = rules.find((rule) => calls.some((call) => callMatches(call, rule)));\n return hit?.cls ?? \"other\";\n}\n","import { z } from \"zod\";\nimport type { AgentNameRow, WakeEventRow } from \"./cost-report-queries.js\";\nimport { roleFromProfile } from \"./roles.js\";\nimport { ACTION_CLASSES, type ActionClass } from \"./turn-action.js\";\n\nexport const WAKE_FROM_KINDS = [\"seat\", \"agent\", \"broadcast\", \"broker\", \"none\"] as const;\nexport type WakeFromKind = (typeof WAKE_FROM_KINDS)[number];\n\n/** Report roles whose wakes are cut into episodes: a human coordinator and a spawned coordinator seat. */\nexport const DEFAULT_EPISODE_ROLES: readonly string[] = [\"coordinator\", \"worker:coordinator\"];\n\n/** A wake whose requests only read, answer in text, or call tools no rule names changed nothing outside the session. */\nexport const DEFAULT_NO_ACTION_CLASSES: readonly ActionClass[] = [\"read-investigate\", \"text-only\", \"other\"];\n\n/** agent-chat's own name on the notices it writes, such as the agent lifecycle notice. */\nexport const BROKER_SENDER = \"agent-chat\";\nexport const AGENT_LIFECYCLE = \"agent_lifecycle\";\nconst UNNAMED = \"unnamed\";\n\nconst count = z.number().int().nonnegative();\nconst costFields = { episodes: count, requests: count, costUsd: z.number(), noActionEpisodes: count, noActionCostUsd: z.number() };\nconst fromSchema = z.object({ key: z.enum(WAKE_FROM_KINDS), ...costFields });\nconst causeSchema = z.object({\n key: z.string(),\n ...costFields,\n midLoopEpisodes: count,\n requestsPerEpisode: z.number(),\n costPerEpisode: z.number(),\n byFrom: z.array(fromSchema),\n});\nconst pairSchema = z.object({ from: z.string(), fromKind: z.enum(WAKE_FROM_KINDS), to: z.string(), ...costFields });\n\nexport const wakeEpisodesSchema = z.object({\n roles: z.array(z.string()),\n noActionClasses: z.array(z.enum(ACTION_CLASSES)),\n ...costFields,\n /** Requests in the window that follow no event in it: the work an earlier arrival started. */\n unattributed: z.object({ requests: count, costUsd: z.number() }),\n byCause: z.array(causeSchema),\n /** Sender by receiver; a seat is named, every other sender is its kind. */\n pairs: z.array(pairSchema),\n});\n\nexport type WakeEpisodes = z.infer<typeof wakeEpisodesSchema>;\nexport type WakeCauseEpisodes = z.infer<typeof causeSchema>;\nexport type WakePair = z.infer<typeof pairSchema>;\n\n/** One request as the episode view needs it. */\nexport interface EpisodeRequestRow {\n costUsd: number;\n action: ActionClass;\n eventKey: string | null;\n}\n\nexport interface WakeEpisode {\n key: string;\n cause: string;\n midLoop: boolean;\n fromKind: WakeFromKind;\n from: string;\n to: string;\n requests: number;\n costUsd: number;\n noAction: boolean;\n}\n\nexport interface EpisodeNames {\n seats: ReadonlySet<string>;\n /** Each receiving session's agent-chat name. */\n receivers: ReadonlyMap<string, string>;\n}\n\n/** A seat is a name some top-level session carries, or one a coordinator profile was spawned under. */\nexport function episodeNames(rows: readonly AgentNameRow[]): EpisodeNames {\n const isSeat = (row: AgentNameRow) => row.originKind !== \"spawned\" || roleFromProfile(row.profile) === \"coordinator\";\n return {\n seats: new Set(rows.filter(isSeat).map((row) => row.agentName)),\n receivers: new Map(rows.map((row) => [row.sessionId, row.agentName])),\n };\n}\n\n/** The lifecycle notice is session-read's `channel_system`; every other cause keeps its name. */\nexport function episodeCause(cause: string): string {\n return cause === \"channel_system\" ? AGENT_LIFECYCLE : cause;\n}\n\nexport function fromKindOf(event: WakeEventRow, seats: ReadonlySet<string>): WakeFromKind {\n if (!event.cause.startsWith(\"channel_\") || event.fromName === null) return \"none\";\n if (event.fromName === BROKER_SENDER) return \"broker\";\n if (event.broadcast) return \"broadcast\";\n return seats.has(event.fromName) ? \"seat\" : \"agent\";\n}\n\n/** Each event with the requests that followed it, flagged no-action when every request's class is listed. */\nexport function buildWakeEpisodes(\n events: readonly WakeEventRow[],\n requests: readonly EpisodeRequestRow[],\n names: EpisodeNames,\n noActionClasses: readonly ActionClass[],\n): WakeEpisode[] {\n const byEvent = groupBy(requests, (request) => request.eventKey ?? \"\");\n return events.map((event) => {\n const members = byEvent.get(event.key) ?? [];\n const fromKind = fromKindOf(event, names.seats);\n return {\n key: event.key,\n cause: episodeCause(event.cause),\n midLoop: event.delivery === \"mid_loop\",\n fromKind,\n from: pairSender(fromKind, event.fromName, names.seats),\n to: names.receivers.get(event.sessionId) ?? UNNAMED,\n requests: members.length,\n costUsd: members.reduce((sum, row) => sum + row.costUsd, 0),\n noAction: members.every((row) => noActionClasses.includes(row.action)),\n };\n });\n}\n\n/** Spawned agents have one-off names, so they collapse to `agent`; a seat broadcasting keeps its name. */\nfunction pairSender(kind: WakeFromKind, name: string | null, seats: ReadonlySet<string>): string {\n if (kind === \"seat\" || (kind === \"broadcast\" && name !== null && seats.has(name))) return name!;\n return kind === \"broadcast\" ? \"agent\" : kind;\n}\n\nexport function summarizeWakeEpisodes(\n episodes: readonly WakeEpisode[],\n requests: readonly EpisodeRequestRow[],\n roles: readonly string[],\n noActionClasses: readonly ActionClass[],\n): WakeEpisodes {\n const keys = new Set(episodes.map((episode) => episode.key));\n const unattributed = requests.filter((row) => row.eventKey === null || !keys.has(row.eventKey));\n return {\n roles: [...roles],\n noActionClasses: [...noActionClasses],\n ...costOf(episodes),\n unattributed: { requests: unattributed.length, costUsd: unattributed.reduce((sum, row) => sum + row.costUsd, 0) },\n byCause: causeBuckets(episodes),\n pairs: pairBuckets(episodes),\n };\n}\n\nfunction costOf(episodes: readonly WakeEpisode[]) {\n const noAction = episodes.filter((episode) => episode.noAction);\n const sum = (list: readonly WakeEpisode[], pick: (episode: WakeEpisode) => number) => list.reduce((total, episode) => total + pick(episode), 0);\n return {\n episodes: episodes.length,\n requests: sum(episodes, (episode) => episode.requests),\n costUsd: sum(episodes, (episode) => episode.costUsd),\n noActionEpisodes: noAction.length,\n noActionCostUsd: sum(noAction, (episode) => episode.costUsd),\n };\n}\n\n/** Most expensive first; ties by key so the report is stable. */\nfunction causeBuckets(episodes: readonly WakeEpisode[]): WakeCauseEpisodes[] {\n return [...groupBy(episodes, (episode) => episode.cause)]\n .map(([key, members]) => {\n const cost = costOf(members);\n return {\n key,\n ...cost,\n midLoopEpisodes: members.filter((episode) => episode.midLoop).length,\n requestsPerEpisode: cost.requests / cost.episodes,\n costPerEpisode: cost.costUsd / cost.episodes,\n byFrom: [...groupBy(members, (episode) => episode.fromKind)].map(([kind, part]) => ({ key: kind as WakeFromKind, ...costOf(part) })).sort(byCostThenKey),\n };\n })\n .sort(byCostThenKey);\n}\n\nfunction pairBuckets(episodes: readonly WakeEpisode[]): WakePair[] {\n const sent = episodes.filter((episode) => episode.fromKind !== \"none\");\n return [...groupBy(sent, (episode) => JSON.stringify([episode.from, episode.fromKind, episode.to]))]\n .map(([key, members]) => {\n const [from, fromKind, to] = JSON.parse(key) as [string, WakeFromKind, string];\n return { from, fromKind, to, ...costOf(members) };\n })\n .sort((a, b) => b.costUsd - a.costUsd || a.from.localeCompare(b.from) || a.to.localeCompare(b.to));\n}\n\nfunction groupBy<T>(rows: readonly T[], keyOf: (row: T) => string): Map<string, T[]> {\n const groups = new Map<string, T[]>();\n for (const row of rows) {\n const key = keyOf(row);\n const members = groups.get(key);\n if (members) members.push(row);\n else groups.set(key, [row]);\n }\n return groups;\n}\n\nfunction byCostThenKey(a: { key: string; costUsd: number }, b: { key: string; costUsd: number }): number {\n return b.costUsd - a.costUsd || a.key.localeCompare(b.key);\n}\n","import type { CostBucket, CostReport, MechanicalShare, RoleActions, WakeGapCell } from \"./cost-report.js\";\nimport type { HandoffThreshold } from \"./handoff-threshold.js\";\nimport { PRICE_TABLE_VERSION } from \"./prices.js\";\nimport type { WakeEpisodes } from \"./wake-episodes.js\";\n\nexport const LIST_PRICE_CAVEAT =\n \"List prices, not a bill: the accounts behind these sessions may run on subscription plans. Rankings hold; the absolute figure is not what you paid.\";\n\ntype Cell = string | number;\n\n/** Wake causes and sender pairs the text shows; the JSON carries all of them. */\nexport const TOP_WAKE_ROWS = 10;\n\n/** The same report as plain-text tables, one section per report field, caveat and footer last. */\nexport function renderCostReportText(report: CostReport): string {\n const sections = [\n header(report),\n table(\"By token class\", [\"class\", \"tokens\", \"cost\"], report.byTokenClass.map((row) => [row.tokenClass, row.tokens, usd(row.costUsd)])),\n bucketTable(\"By account\", report.byAccount, report.totals.costUsd),\n bucketTable(\"By model\", report.byModel, report.totals.costUsd),\n bucketTable(\"By class\", report.byClass, report.totals.costUsd),\n bucketTable(\"By role\", report.byRole, report.totals.costUsd),\n actionTable(report.byAction),\n mechanicalTable(report.mechanicalShare),\n bucketTable(\"By episode count\", report.byEpisodeCount, report.totals.costUsd),\n bucketTable(\"By initiative\", report.byInitiative, report.totals.costUsd),\n bucketTable(\"By context band\", report.byContextBand, report.totals.costUsd),\n wakeCauseTable(report),\n episodeTable(report.wakeEpisodes),\n pairTable(report.wakeEpisodes),\n handoffTable(report.handoffThreshold),\n teleportTable(report.handoffThreshold),\n reviewerTable(report.handoffThreshold),\n cellTable(\"Wake cause by gap band\", report.wakeCauseByGapBand),\n cellTable(`Cold rebuilds: ${report.coldRebuild.requests} requests, ${usd(report.coldRebuild.costUsd)}`, report.coldRebuild.byGapBandAndCause),\n compactionTable(report.compactions),\n topSessionTable(report.topSessions),\n unpricedTable(report.unpricedModels),\n [LIST_PRICE_CAVEAT, footer(report)].join(\"\\n\"),\n ];\n return sections.join(\"\\n\\n\") + \"\\n\";\n}\n\n/** The report's sections a caller may render alone, keyed by the field each one shows. */\nexport const COST_REPORT_SECTIONS = {\n byRole: (report: CostReport) => bucketTable(\"By role\", report.byRole, report.totals.costUsd),\n byAction: (report: CostReport) => actionTable(report.byAction),\n mechanicalShare: (report: CostReport) => mechanicalTable(report.mechanicalShare),\n byWakeCause: (report: CostReport) => wakeCauseTable(report),\n wakeEpisodes: (report: CostReport) => episodeTable(report.wakeEpisodes),\n wakePairs: (report: CostReport) => pairTable(report.wakeEpisodes),\n handoff: (report: CostReport) => handoffTable(report.handoffThreshold),\n teleports: (report: CostReport) => teleportTable(report.handoffThreshold),\n reviewers: (report: CostReport) => reviewerTable(report.handoffThreshold),\n} as const;\n\nexport type CostReportSection = keyof typeof COST_REPORT_SECTIONS;\n\n/** Some sections of the report under its header, with the caveat and footer last as in the full text. */\nexport function renderCostReportSections(report: CostReport, sections: readonly CostReportSection[]): string {\n const body = sections.map((section) => COST_REPORT_SECTIONS[section](report));\n return [header(report), ...body, [LIST_PRICE_CAVEAT, footer(report)].join(\"\\n\")].join(\"\\n\\n\") + \"\\n\";\n}\n\nfunction header(report: CostReport): string {\n const { since, until } = report.window;\n const { requests, sessions, costUsd } = report.totals;\n return `Cost report, ${since ?? \"beginning\"} to ${until ?? \"now\"}\\nTotal ${usd(costUsd)} over ${requests} requests in ${sessions} sessions`;\n}\n\nfunction bucketTable(title: string, buckets: readonly CostBucket[], total: number): string {\n const rows = buckets.map((b) => [b.key, b.requests, b.sessions, usd(b.costUsd), share(b.costUsd, total)]);\n return table(title, [\"key\", \"requests\", \"sessions\", \"cost\", \"share\"], rows);\n}\n\n/** Each role's row carries its total; its action classes sit indented beneath, sharing that total. */\nfunction actionTable(roles: readonly RoleActions[]): string {\n const rows = roles.flatMap(({ role, buckets }) => {\n const total = buckets.reduce((sum, b) => sum + b.costUsd, 0);\n const requests = buckets.reduce((sum, b) => sum + b.requests, 0);\n return [[role, requests, usd(total), share(total, total)], ...buckets.map((b) => [` ${b.key}`, b.requests, usd(b.costUsd), share(b.costUsd, total)])];\n });\n return table(\"By action per role\", [\"role / action\", \"requests\", \"cost\", \"share\"], rows);\n}\n\nfunction mechanicalTable(m: MechanicalShare): string {\n const title = `Mechanical share: ${percent(m.share)} (${usd(m.costUsd)}) of total; classes ${m.classes.join(\", \") || \"none\"}`;\n return table(title, [\"role\", \"mechanical cost\", \"share of role\"], m.byRole.map((r) => [r.role, usd(r.costUsd), percent(r.share)]));\n}\n\n/** Q4: answers sit under `human`, with typed text and answers indented one level down. */\nfunction wakeCauseTable(report: CostReport): string {\n const rows = report.byWakeCause.flatMap((group) => [\n [group.key, group.requests, usd(group.costUsd), group.midLoopRequests, usd(group.midLoopCostUsd)],\n ...group.parts.map((part) => [` ${part.key}`, part.requests, usd(part.costUsd), part.midLoopRequests, usd(part.midLoopCostUsd)]),\n ]);\n return table(\"By wake cause\", [\"cause\", \"requests\", \"cost\", \"mid-loop\", \"mid-loop cost\"], rows);\n}\n\n/** Q4: the costliest causes per episode first, each with its senders indented beneath. */\nfunction episodeTable(w: WakeEpisodes): string {\n const title = `Wake episodes of ${w.roles.join(\", \")}: ${w.episodes} episodes, ${w.requests} requests, ${usd(w.costUsd)}; no-action means only ${w.noActionClasses.join(\", \")}`;\n const causes = [...w.byCause].sort((a, b) => b.costPerEpisode - a.costPerEpisode || a.key.localeCompare(b.key)).slice(0, TOP_WAKE_ROWS);\n const rows = causes.flatMap((c) => [\n [c.key, c.episodes, c.midLoopEpisodes, c.requests, c.requestsPerEpisode.toFixed(1), usd(c.costUsd), usd(c.costPerEpisode), noActionCell(c)],\n ...c.byFrom.map((f) => [` from ${f.key}`, f.episodes, \"\", f.requests, (f.requests / f.episodes).toFixed(1), usd(f.costUsd), usd(f.costUsd / f.episodes), noActionCell(f)]),\n ]);\n return table(title, [\"cause\", \"episodes\", \"mid-loop\", \"requests\", \"req/ep\", \"cost\", \"cost/ep\", \"no-action\"], rows);\n}\n\nfunction noActionCell(bucket: { episodes: number; noActionEpisodes: number }): string {\n return `${bucket.noActionEpisodes} (${share(bucket.noActionEpisodes, bucket.episodes)})`;\n}\n\nfunction pairTable(w: WakeEpisodes): string {\n const rows = w.pairs.slice(0, TOP_WAKE_ROWS).map((p) => [p.from, p.fromKind, p.to, p.episodes, p.requests, usd(p.costUsd), noActionCell(p)]);\n return table(\"Wake senders by receiver\", [\"from\", \"kind\", \"to\", \"episodes\", \"requests\", \"cost\", \"no-action\"], rows);\n}\n\n/** Q2: per role and model, the fitted boot, fill and growth, the best K, and each configured K's extra cost per request. */\nfunction handoffTable(h: HandoffThreshold): string {\n const title = `Handoff threshold per role, priced at package table v${PRICE_TABLE_VERSION}: best K over ${kilo(h.sweep.fromK)}-${kilo(h.sweep.toK)}, half-boot K in brackets`;\n const head = [\"role\", \"model\", \"sessions\", \"boot\", \"boot fill\", \"growth/req\", \"read $/MTok\", \"best K\", \"$/req\", ...h.configuredK.map((k) => `+$/req @${kilo(k)}`)];\n const rows = h.cohorts.map((c) => [\n c.role,\n c.model,\n c.sessions,\n usd(c.bootCostUsd),\n kilo(c.bootFill),\n Math.round(c.growthPerRequest),\n c.readPricePerMTok.toFixed(3),\n `${kiloOrDash(c.bestK)} (${kiloOrDash(c.halfBoot.bestK)})`,\n c.bestCostPerRequest === null ? \"-\" : `$${c.bestCostPerRequest.toFixed(4)}`,\n ...c.atConfigured.map((at) => (at.deltaPerRequest === null ? \"-\" : `$${at.deltaPerRequest.toFixed(4)}`)),\n ]);\n return table(title, head, rows);\n}\n\nfunction teleportTable(h: HandoffThreshold): string {\n const title = `Teleport exit fill: ${h.teleports.length} matched, ${h.unmatchedTeleports} unmatched; the latest ${TOP_WAKE_ROWS}`;\n const head = [\"ts\", \"name\", \"role\", \"exit fill\", \"best K\", ...h.configuredK.map((k) => `over ${kilo(k)}`)];\n const rows = h.teleports.slice(-TOP_WAKE_ROWS).map((t) => [t.ts, t.name ?? \"-\", t.role, kilo(t.exitFill), kiloOrDash(t.bestK), ...t.overConfigured.map((o) => kilo(o.over))]);\n return table(title, head, rows);\n}\n\nfunction reviewerTable(h: HandoffThreshold): string {\n const row = (kind: string) => (c: HandoffThreshold[\"reviewers\"][\"fresh\"][number]) => [kind, c.role, c.model, c.sessions, c.requestsPerPr.toFixed(1), c.requestsFrom, usd(c.costUsd)];\n const rows = [...h.reviewers.fresh.map(row(\"fresh per PR\")), ...h.reviewers.standing.map(row(\"standing\"))];\n return table(`Reviewers over ${h.reviewers.prs} PRs, boot and reads: fresh per PR against one standing`, [\"reviewer\", \"role\", \"model\", \"sessions\", \"req/PR\", \"req/PR from\", \"cost\"], rows);\n}\n\nfunction kilo(tokens: number): string {\n return `${Math.round(tokens / 1_000)}k`;\n}\n\nfunction kiloOrDash(tokens: number | null): string {\n return tokens === null ? \"-\" : kilo(tokens);\n}\n\nfunction cellTable(title: string, cells: readonly WakeGapCell[]): string {\n return table(title, [\"cause\", \"gap\", \"requests\", \"cost\"], cells.map((c) => [c.wakeCause, c.gapBand, c.requests, usd(c.costUsd)]));\n}\n\nfunction compactionTable(c: CostReport[\"compactions\"]): string {\n return table(\"Compactions\", [\"total\", \"manual\", \"auto\", \"mid-loop\", \"dropped tokens\"], [[c.total, c.manual, c.auto, c.midLoop, c.droppedTokens]]);\n}\n\nfunction topSessionTable(sessions: CostReport[\"topSessions\"]): string {\n const rows = sessions.map((s) => [s.sessionId, s.sessionClass, s.role, s.initiative, s.requests, usd(s.costUsd)]);\n return table(\"Top sessions\", [\"session\", \"class\", \"role\", \"initiative\", \"requests\", \"cost\"], rows);\n}\n\nfunction unpricedTable(models: CostReport[\"unpricedModels\"]): string {\n if (models.length === 0) return \"Unpriced models: none\";\n return table(\"Unpriced models (counted at zero cost)\", [\"model\", \"requests\", \"tokens\"], models.map((m) => [m.model, m.requests, m.tokens]));\n}\n\nfunction footer(report: CostReport): string {\n const { transcriptsIndexed, transcriptsDiscovered, facetBacklog } = report.coverage;\n const discovered = transcriptsDiscovered === null ? \"\" : ` of ${transcriptsDiscovered} discovered`;\n const version = report.priceTableVersion === null ? \"none\" : `v${report.priceTableVersion}`;\n const stale = report.priceTableVersion !== null && report.priceTableVersion !== PRICE_TABLE_VERSION ? ` (package has v${PRICE_TABLE_VERSION})` : \"\";\n return `Price table ${version}${stale}. Coverage: ${transcriptsIndexed} transcripts indexed${discovered}, facet backlog ${facetBacklog}.`;\n}\n\nexport function table(title: string, head: readonly string[], rows: readonly (readonly Cell[])[]): string {\n if (rows.length === 0) return `${title}: none`;\n const text = [head, ...rows].map((row) => row.map(String));\n const widths = head.map((_, i) => Math.max(...text.map((row) => row[i]!.length)));\n const rightAligned = head.map((_, i) => rows.every((row) => isNumeric(row[i]!)));\n const pad = (cell: string, i: number) => (rightAligned[i] ? cell.padStart(widths[i]!) : cell.padEnd(widths[i]!));\n const lines = text.map((row) => row.map(pad).join(\" \").trimEnd());\n return [title, ...lines].join(\"\\n\");\n}\n\nfunction isNumeric(cell: Cell): boolean {\n return typeof cell === \"number\" || /^\\$|%$/.test(cell);\n}\n\nexport function usd(value: number): string {\n return `$${value.toFixed(2)}`;\n}\n\nfunction share(value: number, total: number): string {\n return total > 0 ? percent(value / total) : \"-\";\n}\n\nfunction percent(fraction: number): string {\n return `${(fraction * 100).toFixed(1)}%`;\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { z } from \"zod\";\nimport { GAP_BANDS, gapBand } from \"./bands.js\";\nimport { readSessionContexts, type ReportWindow } from \"./cost-report-queries.js\";\nimport { resolveWindow, tagSessions, type CostReportOptions } from \"./cost-report.js\";\nimport { PRICE_TABLE, PRICE_TABLE_VERSION, findPrice, type PriceRow } from \"./prices.js\";\nimport { LIST_PRICE_CAVEAT, table, usd } from \"./render-text.js\";\nimport { scopeFilter } from \"./scope.js\";\n\nconst FIVE_MINUTES_MS = 5 * 60_000;\nconst MTOK = 1e6;\nconst NO_PROFILE = \"none\";\n\n/** Gap bands past a 5-minute TTL: the next request finds the cache gone. */\nexport const REBUILD_GAP_BANDS: readonly string[] = GAP_BANDS.filter((band) => band.lo >= FIVE_MINUTES_MS).map((band) => band.name);\n\n/** One request as the TTL what-if needs it. */\nexport interface TtlRequestRow {\n sessionId: string;\n role: string;\n profile: string;\n model: string;\n ts: string;\n cacheReadTokens: number;\n cacheWrite1hTokens: number;\n /** Milliseconds since the session's previous request; null for its first. */\n gapMs: number | null;\n}\n\nconst count = z.number().int().nonnegative();\nconst effectFields = {\n sessions: count,\n requests: count,\n write1hTokens: count,\n /** 1h writes repriced at the 5m write rate. */\n repriceSavingUsd: z.number(),\n rebuilds: count,\n rebuildTokens: count,\n /** Each rebuild writes at the 5m rate what the 1h cache still served as a read. */\n rebuildCostUsd: z.number(),\n netSavingUsd: z.number(),\n netPerSessionUsd: z.number(),\n};\nconst bucketSchema = z.object({ key: z.string(), ...effectFields, fiveMinuteLoses: z.boolean() });\n\nexport const cacheTtlWhatIfSchema = z.object({\n window: z.object({ since: z.string().nullable(), until: z.string().nullable() }).optional(),\n priceTableVersion: z.number().int(),\n rebuildGapBands: z.array(z.string()),\n totals: z.object(effectFields),\n unpricedRequests: count,\n byRole: z.array(bucketSchema),\n byProfile: z.array(bucketSchema),\n /** Roles whose rebuilds after long gaps outweigh the cheaper writes. */\n lossRoles: z.array(z.string()),\n});\n\nexport type CacheTtlWhatIf = z.infer<typeof cacheTtlWhatIfSchema>;\nexport type CacheTtlBucket = z.infer<typeof bucketSchema>;\n\ninterface RequestEffect {\n sessionId: string;\n write1hTokens: number;\n repriceSavingUsd: number;\n rebuildTokens: number;\n rebuildCostUsd: number;\n}\n\n/** Q3: what each role and profile would have paid with `CLAUDE_CODE_PROMPT_CACHE_TTL=5m` instead of 1h. */\nexport function cacheTtlWhatIf(rows: readonly TtlRequestRow[], prices: readonly PriceRow[] = PRICE_TABLE): CacheTtlWhatIf {\n const effects = new Map<TtlRequestRow, RequestEffect>();\n for (const row of rows) {\n const price = findPrice(row.model, row.ts, prices);\n if (price) effects.set(row, requestEffect(row, price));\n }\n const priced = [...effects.keys()];\n const byRole = buckets(priced, effects, (row) => row.role);\n return {\n priceTableVersion: PRICE_TABLE_VERSION,\n rebuildGapBands: [...REBUILD_GAP_BANDS],\n totals: sumEffects([...effects.values()]),\n unpricedRequests: rows.length - priced.length,\n byRole,\n byProfile: buckets(priced, effects, (row) => row.profile),\n lossRoles: byRole.filter((bucket) => bucket.fiveMinuteLoses).map((bucket) => bucket.key),\n };\n}\n\nfunction requestEffect(row: TtlRequestRow, price: PriceRow): RequestEffect {\n const band = row.gapMs === null ? null : gapBand(row.gapMs);\n const rebuildTokens = band !== null && REBUILD_GAP_BANDS.includes(band) ? row.cacheReadTokens : 0;\n return {\n sessionId: row.sessionId,\n write1hTokens: row.cacheWrite1hTokens,\n repriceSavingUsd: (row.cacheWrite1hTokens * (price.cacheWrite1h - price.cacheWrite5m)) / MTOK,\n rebuildTokens,\n rebuildCostUsd: (rebuildTokens * (price.cacheWrite5m - price.cacheRead)) / MTOK,\n };\n}\n\nfunction sumEffects(effects: readonly RequestEffect[]): CacheTtlWhatIf[\"totals\"] {\n const sum = (pick: (effect: RequestEffect) => number) => effects.reduce((total, effect) => total + pick(effect), 0);\n const sessions = new Set(effects.map((effect) => effect.sessionId)).size;\n const netSavingUsd = sum((effect) => effect.repriceSavingUsd - effect.rebuildCostUsd);\n return {\n sessions,\n requests: effects.length,\n write1hTokens: sum((effect) => effect.write1hTokens),\n repriceSavingUsd: sum((effect) => effect.repriceSavingUsd),\n rebuilds: effects.filter((effect) => effect.rebuildTokens > 0).length,\n rebuildTokens: sum((effect) => effect.rebuildTokens),\n rebuildCostUsd: sum((effect) => effect.rebuildCostUsd),\n netSavingUsd,\n netPerSessionUsd: sessions > 0 ? netSavingUsd / sessions : 0,\n };\n}\n\n/** Largest saving first, so the roles 5m would cost money sit at the bottom. */\nfunction buckets(rows: readonly TtlRequestRow[], effects: Map<TtlRequestRow, RequestEffect>, keyOf: (row: TtlRequestRow) => string): CacheTtlBucket[] {\n const groups = new Map<string, RequestEffect[]>();\n for (const row of rows) {\n const key = keyOf(row);\n const members = groups.get(key);\n if (members) members.push(effects.get(row)!);\n else groups.set(key, [effects.get(row)!]);\n }\n return [...groups]\n .map(([key, members]) => {\n const totals = sumEffects(members);\n return { key, ...totals, fiveMinuteLoses: totals.netSavingUsd < 0 };\n })\n .sort((a, b) => b.netSavingUsd - a.netSavingUsd || a.key.localeCompare(b.key));\n}\n\nconst IN_WINDOW = \"(@since IS NULL OR ts >= @since) AND (@until IS NULL OR ts < @until)\";\n\n// The miner leaves `gap_ms` null, so the gap falls back to the session's previous request, even one before the window.\nconst TTL_ROWS = `\n WITH member AS (SELECT DISTINCT session_id FROM request_dedup WHERE ${IN_WINDOW}),\n timed AS (\n SELECT session_id, model, ts, cache_read_tokens, cache_creation_1h, gap_ms,\n LAG(ts) OVER (PARTITION BY session_id, is_sidechain ORDER BY ts, request_id) AS previous_ts\n FROM request_dedup WHERE session_id IN member\n )\n SELECT session_id AS sessionId, model, ts, cache_read_tokens AS cacheReadTokens, cache_creation_1h AS cacheWrite1hTokens,\n COALESCE(gap_ms, CAST(ROUND((julianday(ts) - julianday(previous_ts)) * 86400000) AS INTEGER)) AS gapMs\n FROM timed WHERE ${IN_WINDOW}`;\n\n/** Reads the graph and never writes it; roles are the cost report's. */\nexport function cacheTtlReport(db: Db, options: CostReportOptions = {}, prices: readonly PriceRow[] = PRICE_TABLE): CacheTtlWhatIf {\n const window = resolveWindow(options);\n return { window, ...cacheTtlWhatIf(readTtlRows(db, window).filter(scopeFilter(db, options.scope)), prices) };\n}\n\nexport function readTtlRows(db: Db, window: ReportWindow): TtlRequestRow[] {\n const rows = db.prepare(TTL_ROWS).all(window) as Omit<TtlRequestRow, \"role\" | \"profile\">[];\n const contexts = readSessionContexts(db, [...new Set(rows.map((row) => row.sessionId))]);\n const tags = tagSessions(contexts);\n return rows.map((row) => ({\n ...row,\n role: tags.get(row.sessionId)!.role,\n profile: contexts.get(row.sessionId)!.facts.origin?.profile ?? NO_PROFILE,\n }));\n}\n\n/** One table per dimension; a role or profile 5m would cost money is marked `loss`. */\nexport function renderCacheTtlText(whatIf: CacheTtlWhatIf): string {\n const { totals, window } = whatIf;\n const span = window ? `, ${window.since ?? \"beginning\"} to ${window.until ?? \"now\"}` : \"\";\n const header = [\n `Cache TTL what-if, 5m against 1h${span}`,\n `Net ${usd(totals.netSavingUsd)} over ${totals.sessions} sessions: 1h writes repriced save ${usd(totals.repriceSavingUsd)}, ` +\n `${totals.rebuilds} rebuilds after gaps in ${whatIf.rebuildGapBands.join(\", \")} cost ${usd(totals.rebuildCostUsd)}`,\n `Roles where 5m loses: ${whatIf.lossRoles.join(\", \") || \"none\"}`,\n ].join(\"\\n\");\n const footer = `Price table v${whatIf.priceTableVersion}; ${whatIf.unpricedRequests} unpriced requests left out.`;\n return [header, ttlTable(\"By role\", whatIf.byRole), ttlTable(\"By profile\", whatIf.byProfile), [LIST_PRICE_CAVEAT, footer].join(\"\\n\")].join(\"\\n\\n\") + \"\\n\";\n}\n\nfunction ttlTable(title: string, rows: readonly CacheTtlBucket[]): string {\n const head = [\"key\", \"sessions\", \"requests\", \"reprice saving\", \"rebuilds\", \"rebuild cost\", \"net\", \"net per session\", \"5m\"];\n const cells = rows.map((b) => [b.key, b.sessions, b.requests, usd(b.repriceSavingUsd), b.rebuilds, usd(b.rebuildCostUsd), usd(b.netSavingUsd), usd(b.netPerSessionUsd), b.fiveMinuteLoses ? \"loss\" : \"saves\"]);\n return table(title, head, cells);\n}\n","import { z } from \"zod\";\n\n/** One reviewer verdict message, as agent-chat's events table records it. */\nexport interface VerdictRecord {\n eventId: number;\n at: string;\n /** The seat the verdict was sent to. */\n seat: string;\n reviewer: string;\n verdict: string;\n repo: string;\n pr: number;\n head: string;\n}\n\n/** A PR as GitHub REST reports it at the time of the run. */\nexport interface PullState {\n repo: string;\n pr: number;\n state: \"open\" | \"closed\";\n mergedAt: string | null;\n headSha: string;\n}\n\nexport type ParsedVerdict = Pick<VerdictRecord, \"verdict\" | \"repo\" | \"pr\" | \"head\">;\n\nconst VERDICT_LINE = /^Verdict:\\s*([A-Z_]+)/;\nconst PR_LINE = /^PR:\\s*(?:https:\\/\\/github\\.com\\/)?([\\w.-]+\\/[\\w.-]+)(?:#|\\/pull\\/)(\\d+)/m;\nconst HEAD_LINE = /^Head:\\s*`?([0-9a-f]{7,40})\\b/m;\n\n/** Reads a `Verdict:` message's first three lines; null when any of them is missing. */\nexport function parseVerdict(body: string): ParsedVerdict | null {\n const verdict = VERDICT_LINE.exec(body)?.[1];\n const pr = PR_LINE.exec(body);\n const head = HEAD_LINE.exec(body)?.[1];\n if (!verdict || !pr || !head) return null;\n return { verdict, repo: pr[1]!, pr: Number(pr[2]), head };\n}\n\nexport type MergeStatus = \"merged\" | \"open\" | \"stale-head\" | \"closed\" | \"unknown\";\n\n/** A PR holding at least one MERGE verdict, resolved against its GitHub state at `asOf`. */\nexport interface MergeOutcome {\n repo: string;\n pr: number;\n status: MergeStatus;\n /** The first MERGE verdict at the PR's final head; null when no verdict names that head. */\n verdict: VerdictRecord | null;\n /** Verdict to merge for merged PRs; verdict to `asOf` (a censored age) for open ones. */\n minutes: number | null;\n}\n\nconst MINUTE_MS = 60_000;\n\nexport function mergeOutcomes(verdicts: readonly VerdictRecord[], pulls: readonly PullState[], asOf: string): MergeOutcome[] {\n const byPr = new Map<string, VerdictRecord[]>();\n for (const v of verdicts) if (v.verdict === \"MERGE\") byPr.set(prKey(v), [...(byPr.get(prKey(v)) ?? []), v]);\n const pullByKey = new Map(pulls.map((p) => [prKey(p), p]));\n return [...byPr.values()].map((held) => outcome(held, pullByKey.get(prKey(held[0]!)), asOf));\n}\n\nexport function prKey(row: { repo: string; pr: number }): string {\n return `${row.repo}#${row.pr}`;\n}\n\nfunction outcome(held: VerdictRecord[], pull: PullState | undefined, asOf: string): MergeOutcome {\n const { repo, pr } = held[0]!;\n if (!pull) return { repo, pr, status: \"unknown\", verdict: null, minutes: null };\n const atHead = held.filter((v) => sameSha(v.head, pull.headSha)).sort((a, b) => a.at.localeCompare(b.at))[0];\n const mergedBy = pull.mergedAt !== null && pull.mergedAt <= asOf;\n if (!atHead) return { repo, pr, status: pull.mergedAt !== null || pull.state === \"open\" ? \"stale-head\" : \"closed\", verdict: null, minutes: null };\n if (mergedBy) return { repo, pr, status: \"merged\", verdict: atHead, minutes: Math.max(0, minutesBetween(atHead.at, pull.mergedAt!)) };\n if (pull.state === \"open\" || pull.mergedAt !== null) return { repo, pr, status: \"open\", verdict: atHead, minutes: minutesBetween(atHead.at, asOf) };\n return { repo, pr, status: \"closed\", verdict: atHead, minutes: null };\n}\n\nfunction sameSha(a: string, b: string): boolean {\n return a.startsWith(b) || b.startsWith(a);\n}\n\nfunction minutesBetween(from: string, to: string): number {\n return (Date.parse(to) - Date.parse(from)) / MINUTE_MS;\n}\n\nconst minutes = z.number().nullable();\n\nexport const latencyStatsSchema = z.object({\n merged: z.number().int().nonnegative(),\n medianMin: minutes,\n meanMin: minutes,\n p90Min: minutes,\n maxMin: minutes,\n /** Open PRs holding MERGE at their current head; their ages are lower bounds on the wait. */\n censored: z.number().int().nonnegative(),\n oldestCensoredMin: minutes,\n censoredPrMinutes: z.number().nonnegative(),\n /** Median over merged waits and censored ages together: a lower bound on the true median. */\n medianWithCensoredMin: minutes,\n});\n\nexport type LatencyStats = z.infer<typeof latencyStatsSchema>;\n\nexport function latencyStats(outcomes: readonly MergeOutcome[]): LatencyStats {\n const merged = sorted(outcomes.filter((o) => o.status === \"merged\").map((o) => o.minutes!));\n const censored = sorted(outcomes.filter((o) => o.status === \"open\").map((o) => o.minutes!));\n return {\n merged: merged.length,\n medianMin: median(merged),\n meanMin: merged.length === 0 ? null : round(merged.reduce((a, b) => a + b, 0) / merged.length),\n p90Min: nearestRank(merged, 0.9),\n maxMin: merged.at(-1) === undefined ? null : round(merged.at(-1)!),\n censored: censored.length,\n oldestCensoredMin: censored.at(-1) === undefined ? null : round(censored.at(-1)!),\n censoredPrMinutes: round(censored.reduce((a, b) => a + b, 0)),\n medianWithCensoredMin: median(sorted([...merged, ...censored])),\n };\n}\n\nfunction sorted(values: number[]): number[] {\n return values.sort((a, b) => a - b);\n}\n\nfunction median(values: readonly number[]): number | null {\n if (values.length === 0) return null;\n const mid = Math.floor(values.length / 2);\n return round(values.length % 2 === 1 ? values[mid]! : (values[mid - 1]! + values[mid]!) / 2);\n}\n\nfunction nearestRank(values: readonly number[], p: number): number | null {\n return values.length === 0 ? null : round(values[Math.ceil(p * values.length) - 1]!);\n}\n\nexport function round(value: number): number {\n return Math.round(value * 10) / 10;\n}\n","/** One action the auto-mode classifier refused, read from a seat's transcript. */\nexport interface DenialRecord {\n seat: string;\n at: string;\n /** The classifier's bracketed reason, such as \"Merge Without Review\". */\n reason: string;\n /** What the refused call was doing, from its tool input; the reason label alone is loose. */\n action: string;\n tool: string;\n}\n\nconst DENIAL = /^Permission for this action (?:was|has been) denied by the Claude Code auto mode classifier\\. Reason: \\[([^\\]]+)\\]/;\n\nconst BASH_ACTIONS: readonly (readonly [string, RegExp])[] = [\n [\"merge\", /\\bgh pr merge\\b|\\/pulls\\/\\d+\\/merge\\b/],\n [\"retire\", /\\bagent[ _-]retire\\b|\\bagent\\s+retire\\b/],\n [\"worktree-remove\", /\\bgit\\b.*\\bworktree (?:remove|prune)\\b/],\n [\"branch-delete\", /\\bgit branch -[dD]\\b|\\bpush\\b.*--delete\\b|\\/git\\/refs\\/heads\\/\\S*.*-X DELETE|-X DELETE\\b.*\\/git\\/refs\\//],\n [\"push\", /\\bgit\\b.*\\bpush\\b/],\n [\"github-write\", /\\bgh (?:pr|issue) (?:create|edit|comment|close)\\b|\\bgh api\\b.*(?:-X|--method)\\s*(?:POST|PATCH|PUT|DELETE)\\b/],\n [\"service-restart\", /\\bservice restart\\b|\\blaunchctl\\b/],\n [\"process-kill\", /\\b(?:pkill|kill)\\b/],\n [\"file-write\", /\\s>>?\\s*(?!\\/dev\\/null|&)\\S|\\bopen\\([^)]*[\"'][wa][\"']\\)|\\bsed -i\\b/],\n];\n\nconst FILE_TOOLS = new Set([\"Edit\", \"Write\", \"MultiEdit\", \"NotebookEdit\"]);\n\n/** Classifies a refused call by what it did; MCP tools keep their own short name. */\nexport function classifyDeniedAction(tool: string, input: unknown): string {\n if (tool === \"Bash\") return bashAction(String((input as { command?: unknown } | null)?.command ?? \"\"));\n if (FILE_TOOLS.has(tool)) return \"file-edit\";\n if (tool.startsWith(\"mcp__\")) return `mcp:${tool.split(\"__\").at(-1)}`;\n return `tool:${tool}`;\n}\n\nfunction bashAction(command: string): string {\n return BASH_ACTIONS.find(([, pattern]) => pattern.test(command))?.[0] ?? \"bash-other\";\n}\n\ninterface TranscriptEntry {\n timestamp?: string;\n message?: { content?: unknown };\n}\n\ninterface ContentBlock {\n type?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: unknown;\n}\n\n/** Scans transcript JSONL for classifier refusals and joins each to the tool call it refused. */\nexport function parseDenials(lines: Iterable<string>, seat: string): DenialRecord[] {\n const calls = new Map<string, { tool: string; input: unknown }>();\n const denials: DenialRecord[] = [];\n for (const line of lines) {\n if (!line.includes('\"tool_use\"') && !line.includes(\"auto mode classifier\")) continue;\n const entry = parseLine(line);\n for (const block of blocksOf(entry)) {\n if (block.type === \"tool_use\" && block.id) calls.set(block.id, { tool: block.name ?? \"unknown\", input: block.input });\n const reason = block.type === \"tool_result\" ? DENIAL.exec(resultText(block.content))?.[1] : undefined;\n if (reason === undefined) continue;\n const call = calls.get(block.tool_use_id ?? \"\") ?? { tool: \"unknown\", input: null };\n denials.push({ seat, at: entry?.timestamp ?? \"\", reason, action: classifyDeniedAction(call.tool, call.input), tool: call.tool });\n }\n }\n return denials;\n}\n\nfunction parseLine(line: string): TranscriptEntry | null {\n try {\n return JSON.parse(line) as TranscriptEntry;\n } catch {\n return null;\n }\n}\n\nfunction blocksOf(entry: TranscriptEntry | null): ContentBlock[] {\n const content = entry?.message?.content;\n return Array.isArray(content) ? (content as ContentBlock[]) : [];\n}\n\nfunction resultText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n const first = (content as { type?: string; text?: string }[]).find((part) => part.type === \"text\");\n return first?.text ?? \"\";\n}\n","/** A seat journal line that states its implementer slot count, and why it did not fill a free slot. */\nexport interface SlotTick {\n seat: string;\n at: string;\n used: number;\n cap: number;\n reason: string;\n /** The journal line number, so a row can be checked against its source. */\n line: number;\n}\n\nexport interface SeatJournal {\n ticks: SlotTick[];\n /** The journal's last timestamped line; the final tick holds until then. */\n lastAt: string | null;\n}\n\nexport const UNSTATED_REASON = \"unstated\";\n\n/** A tick's count holds at most this long, so a dark seat is not read as an hour of idle slots. */\nexport const TICK_HOLD_MAX_MIN = 60;\n\nconst STAMP = /^(\\d{1,2}):(\\d{2})(?::(\\d{2}))?\\s/;\nconst IMPL = /\\bimpl(?:ementers?)?\\s+(\\d+)\\s*\\/\\s*(\\d+)/i;\nconst REASON = /\\b(?:no dispatch|dispatch 0)\\s*:\\s*([^.;(]+)/i;\n\n/**\n * Reads `HH:MM[:SS] ...` journal lines for the date the journal covers.\n * `utcOffsetMin` is the journal clock's offset east of UTC, such as -360 for UTC-6.\n */\nexport function parseSeatJournal(text: string, seat: string, date: string, utcOffsetMin: number): SeatJournal {\n const ticks: SlotTick[] = [];\n let lastAt: string | null = null;\n text.split(\"\\n\").forEach((raw, index) => {\n const stamp = STAMP.exec(raw);\n if (!stamp) return;\n const at = journalTime(date, stamp, utcOffsetMin);\n lastAt = at;\n const impl = IMPL.exec(raw);\n if (!impl) return;\n const used = Number(impl[1]);\n const cap = Number(impl[2]);\n const reason = used < cap ? (REASON.exec(raw)?.[1]?.trim().toLowerCase() ?? UNSTATED_REASON) : \"\";\n ticks.push({ seat, at, used, cap, reason, line: index + 1 });\n });\n return { ticks, lastAt };\n}\n\nfunction journalTime(date: string, stamp: RegExpExecArray, utcOffsetMin: number): string {\n const [year, month, day] = date.split(\"-\").map(Number);\n const local = Date.UTC(year!, month! - 1, day!, Number(stamp[1]), Number(stamp[2]), Number(stamp[3] ?? 0));\n return new Date(local - utcOffsetMin * 60_000).toISOString();\n}\n\nexport interface IdleSlotRow {\n seat: string;\n reason: string;\n slotMinutes: number;\n ticks: number;\n /** Journal line numbers of the ticks counted here. */\n lines: number[];\n}\n\n/** Free implementer slots times the minutes each tick's count held, clipped to the window. */\nexport function idleSlotMinutes(journals: readonly SeatJournal[], window: { since?: string; until?: string }): IdleSlotRow[] {\n const rows = new Map<string, IdleSlotRow>();\n for (const journal of journals) {\n journal.ticks.forEach((tick, i) => {\n const free = Math.max(0, tick.cap - tick.used);\n const held = heldMinutes(tick.at, journal.ticks[i + 1]?.at ?? journal.lastAt ?? tick.at, window);\n if (free === 0 || held <= 0) return;\n const key = `${tick.seat}\\u0000${tick.reason}`;\n const row = rows.get(key) ?? { seat: tick.seat, reason: tick.reason, slotMinutes: 0, ticks: 0, lines: [] };\n rows.set(key, { ...row, slotMinutes: row.slotMinutes + free * held, ticks: row.ticks + 1, lines: [...row.lines, tick.line] });\n });\n }\n return [...rows.values()].map((r) => ({ ...r, slotMinutes: Math.round(r.slotMinutes) })).sort((a, b) => b.slotMinutes - a.slotMinutes);\n}\n\nfunction heldMinutes(from: string, to: string, window: { since?: string; until?: string }): number {\n const start = Math.max(Date.parse(from), window.since ? Date.parse(window.since) : -Infinity);\n const capped = Math.min(Date.parse(to), Date.parse(from) + TICK_HOLD_MAX_MIN * 60_000);\n const end = Math.min(capped, window.until ? Date.parse(window.until) : Infinity);\n return Math.max(0, (end - start) / 60_000);\n}\n","import { z } from \"zod\";\nimport { latencyStats, latencyStatsSchema, mergeOutcomes, round, type LatencyStats, type MergeOutcome, type PullState, type VerdictRecord } from \"./blocked-flow-merge.js\";\nimport type { DenialRecord } from \"./blocked-flow-denials.js\";\nimport { TICK_HOLD_MAX_MIN, idleSlotMinutes, type SeatJournal } from \"./blocked-flow-idle.js\";\nimport { LIST_PRICE_CAVEAT, table } from \"./render-text.js\";\n\n/** Where each section's numbers come from: the command that re-reads them and the field it reads. */\nexport const BLOCKED_FLOW_SOURCES = {\n verdicts: {\n command: `sqlite3 -readonly <events.db> \"SELECT id, ts, target, body FROM events WHERE kind='message' AND body LIKE 'Verdict:%'\"`,\n field: \"events.ts, events.target, events.body lines Verdict:, PR:, Head:\",\n },\n pulls: { command: \"gh api repos/<owner>/<repo>/pulls/<n>\", field: \".state, .merged_at, .head.sha\" },\n denials: {\n command: \"grep 'auto mode classifier. Reason: \\\\[' <seat transcript>.jsonl\",\n field: \"tool_result.content Reason: [<class>], joined to tool_use.input by tool_use_id\",\n },\n journals: { command: \"grep -nE 'impl [0-9]+/[0-9]+' <seat journal>.md\", field: \"impl <used>/<cap>, No dispatch: <reason>\" },\n} as const;\n\nexport type BlockedFlowSource = keyof typeof BLOCKED_FLOW_SOURCES;\n\nexport interface BlockedFlowInput {\n verdicts: readonly VerdictRecord[];\n pulls: readonly PullState[];\n denials: readonly DenialRecord[];\n journals: readonly SeatJournal[];\n /** Waits are measured to here; a PR merged later counts as open. */\n asOf: string;\n window?: { since?: string; until?: string };\n /** Splits verdict-to-merge by verdict time, such as the moment a seat was granted merge authority. */\n splitAt?: string;\n /** Keeps only verdicts sent to, and denials and journals of, these seats. */\n seats?: readonly string[];\n}\n\nconst source = z.enum([\"verdicts\", \"pulls\", \"denials\", \"journals\"]);\nconst count = z.number().int().nonnegative();\n\nconst latencyRowSchema = z.object({\n repo: z.string(),\n prs: count,\n staleHead: count,\n closed: count,\n unknown: count,\n all: latencyStatsSchema,\n before: latencyStatsSchema.optional(),\n after: latencyStatsSchema.optional(),\n});\n\nconst openRowSchema = z.object({\n repo: z.string(),\n pr: count,\n head: z.string(),\n seat: z.string(),\n verdictAt: z.string(),\n ageMin: z.number(),\n eventId: count,\n});\n\nexport const blockedFlowSchema = z.object({\n asOf: z.string(),\n window: z.object({ since: z.string().optional(), until: z.string().optional() }),\n splitAt: z.string().optional(),\n sources: z.record(source, z.object({ command: z.string(), field: z.string() })),\n verdictToMerge: z.object({ cites: z.array(source), rows: z.array(latencyRowSchema) }),\n openHoldingMerge: z.object({ cites: z.array(source), prMinutes: z.number(), rows: z.array(openRowSchema) }),\n denials: z.object({\n cites: z.array(source),\n total: count,\n rows: z.array(z.object({ reason: z.string(), action: z.string(), seat: z.string(), count })),\n }),\n idleSlots: z.object({\n cites: z.array(source),\n holdMaxMin: z.number(),\n total: z.number(),\n rows: z.array(z.object({ seat: z.string(), reason: z.string(), slotMinutes: z.number(), ticks: count, lines: z.array(count) })),\n }),\n});\n\nexport type BlockedFlowReport = z.infer<typeof blockedFlowSchema>;\nexport type LatencyRow = z.infer<typeof latencyRowSchema>;\n\nexport const ALL_REPOS = \"all\";\n\n/** Per repo: verdict-to-merge waits, PRs still holding MERGE, classifier denials and idle implementer slots. */\nexport function blockedFlowReport(input: BlockedFlowInput): BlockedFlowReport {\n const window = input.window ?? {};\n const inScope = scopeTest(input.seats, window);\n const outcomes = mergeOutcomes(input.verdicts.filter((v) => inScope(v.seat, v.at)), input.pulls, input.asOf);\n const open = openRows(outcomes);\n const journals = input.journals.map((j) => ({ ...j, ticks: j.ticks.filter((t) => inScope(t.seat)) }));\n const idle = idleSlotMinutes(journals, window);\n return {\n asOf: input.asOf,\n window,\n ...(input.splitAt ? { splitAt: input.splitAt } : {}),\n sources: BLOCKED_FLOW_SOURCES,\n verdictToMerge: { cites: [\"verdicts\", \"pulls\"], rows: latencyRows(outcomes, input.splitAt) },\n openHoldingMerge: { cites: [\"verdicts\", \"pulls\"], prMinutes: round(open.reduce((sum, r) => sum + r.ageMin, 0)), rows: open },\n denials: denialSection(input.denials.filter((d) => inScope(d.seat, d.at))),\n idleSlots: { cites: [\"journals\"], holdMaxMin: TICK_HOLD_MAX_MIN, total: idle.reduce((sum, r) => sum + r.slotMinutes, 0), rows: idle },\n };\n}\n\nfunction scopeTest(seats: readonly string[] | undefined, window: { since?: string; until?: string }) {\n const named = seats ? new Set(seats) : null;\n return (seat: string, at?: string): boolean =>\n (!named || named.has(seat)) && (at === undefined || ((!window.since || at >= window.since) && (!window.until || at < window.until)));\n}\n\nfunction latencyRows(outcomes: readonly MergeOutcome[], splitAt: string | undefined): LatencyRow[] {\n const repos = [...new Set(outcomes.map((o) => o.repo))];\n const rows = repos.map((repo) => latencyRow(repo, outcomes.filter((o) => o.repo === repo), splitAt));\n return [...rows.sort((a, b) => b.prs - a.prs || a.repo.localeCompare(b.repo)), latencyRow(ALL_REPOS, outcomes, splitAt)];\n}\n\nfunction latencyRow(repo: string, outcomes: readonly MergeOutcome[], splitAt: string | undefined): LatencyRow {\n const status = (s: string) => outcomes.filter((o) => o.status === s).length;\n const row: LatencyRow = { repo, prs: outcomes.length, staleHead: status(\"stale-head\"), closed: status(\"closed\"), unknown: status(\"unknown\"), all: latencyStats(outcomes) };\n if (!splitAt) return row;\n const timed = outcomes.filter((o) => o.verdict !== null);\n return { ...row, before: latencyStats(timed.filter((o) => o.verdict!.at < splitAt)), after: latencyStats(timed.filter((o) => o.verdict!.at >= splitAt)) };\n}\n\nfunction openRows(outcomes: readonly MergeOutcome[]): BlockedFlowReport[\"openHoldingMerge\"][\"rows\"] {\n return outcomes\n .filter((o) => o.status === \"open\")\n .map((o) => ({ repo: o.repo, pr: o.pr, head: o.verdict!.head, seat: o.verdict!.seat, verdictAt: o.verdict!.at, ageMin: round(o.minutes!), eventId: o.verdict!.eventId }))\n .sort((a, b) => b.ageMin - a.ageMin);\n}\n\nfunction denialSection(denials: readonly DenialRecord[]): BlockedFlowReport[\"denials\"] {\n const counts = new Map<string, { reason: string; action: string; seat: string; count: number }>();\n for (const d of denials) {\n const key = [d.reason, d.action, d.seat].join(\"\\u0000\");\n const row = counts.get(key) ?? { reason: d.reason, action: d.action, seat: d.seat, count: 0 };\n counts.set(key, { ...row, count: row.count + 1 });\n }\n const rows = [...counts.values()].sort((a, b) => b.count - a.count || a.reason.localeCompare(b.reason) || a.action.localeCompare(b.action));\n return { cites: [\"denials\"], total: denials.length, rows };\n}\n\n/** Each table's title names the JSON field its numbers come from; the sources close the report. */\nexport function renderBlockedFlowText(report: BlockedFlowReport): string {\n const scope = `Blocked flow as of ${report.asOf}${report.window.since ? `, since ${report.window.since}` : \"\"}${report.window.until ? `, until ${report.window.until}` : \"\"}`;\n const latency = [latencyTable(\"Verdict to merge, minutes from the first MERGE at the final head [verdictToMerge.rows[].all]\", report.verdictToMerge.rows, \"all\")];\n if (report.splitAt) latency.push(...([\"before\", \"after\"] as const).map((part) => latencyTable(`Verdict to merge, verdicts ${part} ${report.splitAt} [verdictToMerge.rows[].${part}]`, report.verdictToMerge.rows, part)));\n return [scope, ...latency, openTable(report), denialTable(report), idleTable(report), sourceLines(report), LIST_PRICE_CAVEAT].join(\"\\n\\n\") + \"\\n\";\n}\n\nfunction latencyTable(title: string, rows: readonly LatencyRow[], part: \"all\" | \"before\" | \"after\"): string {\n const cells = rows.map((r) => [r.repo, r.prs, ...statCells(r[part]!), r.staleHead]);\n return table(title, [\"repo\", \"prs\", \"merged\", \"median\", \"mean\", \"p90\", \"max\", \"open\", \"oldest open\", \"median incl. open\", \"stale head\"], cells);\n}\n\nfunction statCells(s: LatencyStats): (string | number)[] {\n const n = (v: number | null) => (v === null ? \"-\" : v);\n return [s.merged, n(s.medianMin), n(s.meanMin), n(s.p90Min), n(s.maxMin), s.censored, n(s.oldestCensoredMin), n(s.medianWithCensoredMin)];\n}\n\nfunction openTable(report: BlockedFlowReport): string {\n const rows = report.openHoldingMerge.rows.map((r) => [r.repo, `#${r.pr}`, r.head.slice(0, 7), r.seat, r.verdictAt, r.ageMin, `events#${r.eventId}`]);\n const title = `Open PRs holding MERGE at their current head, ${report.openHoldingMerge.prMinutes} PR-minutes [openHoldingMerge.rows[].ageMin]`;\n return table(title, [\"repo\", \"pr\", \"head\", \"seat\", \"verdict at\", \"age min\", \"verdict\"], rows);\n}\n\nfunction denialTable(report: BlockedFlowReport): string {\n const rows = report.denials.rows.map((r) => [r.reason, r.action, r.seat, r.count]);\n return table(`Classifier denials, ${report.denials.total} in all [denials.rows[].count]`, [\"reason\", \"action\", \"seat\", \"count\"], rows);\n}\n\nfunction idleTable(report: BlockedFlowReport): string {\n const rows = report.idleSlots.rows.map((r) => [r.seat, r.reason, r.slotMinutes, r.ticks, r.lines.join(\",\")]);\n const title = `Idle implementer slot-minutes by stated reason, ${report.idleSlots.total} in all, each tick held at most ${report.idleSlots.holdMaxMin} min [idleSlots.rows[].slotMinutes]`;\n return table(title, [\"seat\", \"reason\", \"slot-min\", \"ticks\", \"journal lines\"], rows);\n}\n\nfunction sourceLines(report: BlockedFlowReport): string {\n return [\"Sources\", ...Object.entries(report.sources).map(([name, s]) => `${name}: ${s.command} (${s.field})`)].join(\"\\n\");\n}\n"],"mappings":"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","names":["z","agentSessions","costOf","z","count","z","groupBy","count","z","byCostThenKey","buckets","gapBand","buckets","fraction","z","MTOK","count","z","bucketSchema","IN_WINDOW","header","footer","z","MINUTE_MS","z","z","count"]}
1
+ {"version":3,"sources":["../src/prices.ts","../src/price-request.ts","../src/classify-session.ts","../src/bands.ts","../src/cost-report.ts","../src/cost-report-queries.ts","../src/episodes.ts","../src/handoff-threshold.ts","../src/initiative.ts","../src/request-owner.ts","../src/roles.ts","../src/scope.ts","../src/turn-action.ts","../src/wake-episodes.ts","../src/render-text.ts","../src/cache-ttl.ts","../src/blocked-flow-merge.ts","../src/blocked-flow-denials.ts","../src/blocked-flow-idle.ts","../src/blocked-flow.ts","../src/liveness-broker.ts","../src/liveness-routes.ts","../src/liveness-dark.ts","../src/liveness-exits.ts","../src/liveness-prompts.ts","../src/liveness.ts","../src/timeline-types.ts","../src/timeline-breakdowns.ts","../src/timeline-buckets.ts","../src/timeline-tokens.ts","../src/timeline-turns.ts","../src/timeline.ts","../src/count-at-or-before.ts","../src/review-fill.ts"],"sourcesContent":["/** USD per million tokens. Fitted against 392 `cost-state` rows in the 2026-09-20 audit. */\nexport interface PriceRow {\n /** Matched at a model-id boundary: the id itself, or followed by a -YYYYMMDD or [..] suffix. */\n modelPrefix: string;\n /** ISO date. The latest row at or before a request's timestamp wins. */\n effectiveFrom: string;\n input: number;\n cacheRead: number;\n cacheWrite5m: number;\n cacheWrite1h: number;\n output: number;\n}\n\n/** Bump on any edit to PRICE_TABLE. The cost report prints it in its footer. */\nexport const PRICE_TABLE_VERSION = 2;\n\nconst OPUS = { input: 5.0, cacheRead: 0.5, cacheWrite5m: 6.25, cacheWrite1h: 10.0, output: 25.0 };\nconst OPUS_5_5 = { input: 4.0, cacheRead: 0.2, cacheWrite5m: 5.0, cacheWrite1h: 8.0, output: 20.0 };\nconst SONNET = { input: 2.0, cacheRead: 0.2, cacheWrite5m: 2.5, cacheWrite1h: 4.0, output: 10.0 };\n// Fable's cache read is 0.025 of input, not the 0.1 every other model uses. Reading it as\n// 0.1 overstated the 2026-09-20 audit by about $1,700; `fable-cache-read.test` pins the ratio.\nconst FABLE = { input: 10.0, cacheRead: 0.25, cacheWrite5m: 12.5, cacheWrite1h: 20.0, output: 50.0 };\nconst SONNET_5_5 = { input: 2.0, cacheRead: 0.2, cacheWrite5m: 2.5, cacheWrite1h: 4.0, output: 10.0 };\nconst HAIKU = { input: 1.0, cacheRead: 0.1, cacheWrite5m: 1.25, cacheWrite1h: 2.0, output: 5.0 };\nconst FREE = { input: 0, cacheRead: 0, cacheWrite5m: 0, cacheWrite1h: 0, output: 0 };\n\nconst GENESIS = \"2026-01-01\";\n\nexport const PRICE_TABLE: readonly PriceRow[] = [\n // 5.5 rows: claude-api skill shared/models.md and prompt-caching.md, bundled copy cached 2026-09-25.\n { modelPrefix: \"claude-opus-5-5\", effectiveFrom: GENESIS, ...OPUS_5_5 },\n { modelPrefix: \"claude-opus-5\", effectiveFrom: GENESIS, ...OPUS },\n { modelPrefix: \"claude-opus-4-8\", effectiveFrom: GENESIS, ...OPUS },\n { modelPrefix: \"claude-sonnet-5-5\", effectiveFrom: GENESIS, ...SONNET_5_5 },\n { modelPrefix: \"claude-sonnet-5\", effectiveFrom: GENESIS, ...SONNET },\n { modelPrefix: \"claude-fable-5-1\", effectiveFrom: GENESIS, ...FABLE },\n { modelPrefix: \"claude-fable-5\", effectiveFrom: GENESIS, ...FABLE },\n { modelPrefix: \"claude-haiku-4-5\", effectiveFrom: GENESIS, ...HAIKU },\n { modelPrefix: \"<synthetic>\", effectiveFrom: GENESIS, ...FREE },\n];\n\n/**\n * The longest prefix that matches the model at an id boundary, then the latest row effective at `ts`.\n * Returns null for a model no row covers: an unknown model is unpriced, never defaulted,\n * because a default silently prices a new model at an old model's rate.\n */\nexport function findPrice(model: string, ts: string, prices: readonly PriceRow[] = PRICE_TABLE): PriceRow | null {\n let best: PriceRow | null = null;\n for (const row of prices) {\n if (!matchesAtBoundary(model, row.modelPrefix)) continue;\n if (row.effectiveFrom > ts) continue;\n if (best && !isBetterMatch(row, best)) continue;\n best = row;\n }\n return best;\n}\n\nfunction isBetterMatch(row: PriceRow, best: PriceRow): boolean {\n if (row.modelPrefix.length !== best.modelPrefix.length) return row.modelPrefix.length > best.modelPrefix.length;\n return row.effectiveFrom > best.effectiveFrom;\n}\n\n// A bare startsWith lets claude-opus-5 price claude-opus-5-5 at the older model's rates.\nfunction matchesAtBoundary(model: string, prefix: string): boolean {\n if (!model.startsWith(prefix)) return false;\n const rest = model.slice(prefix.length);\n return rest === \"\" || rest.startsWith(\"[\") || /^-\\d{8}(\\[.*\\])?$/.test(rest);\n}\n","import type { PriceRow } from \"./prices.js\";\nimport { PRICE_TABLE, findPrice } from \"./prices.js\";\n\n/** Raw token counts for one API request, as the transcript reports them. */\nexport interface RequestTokens {\n inputTokens?: number;\n cacheReadTokens?: number;\n /** Total cache creation. Used only when the 5m/1h split is absent. */\n cacheCreationTokens?: number;\n cacheCreation5mTokens?: number;\n cacheCreation1hTokens?: number;\n outputTokens?: number;\n}\n\nexport interface PricedRequest {\n inputUsd: number;\n cacheReadUsd: number;\n cacheWrite5mUsd: number;\n cacheWrite1hUsd: number;\n outputUsd: number;\n costUsd: number;\n /** False when no price row covers the model. Every component is then zero. */\n priced: boolean;\n}\n\nconst UNPRICED: PricedRequest = {\n inputUsd: 0,\n cacheReadUsd: 0,\n cacheWrite5mUsd: 0,\n cacheWrite1hUsd: 0,\n outputUsd: 0,\n costUsd: 0,\n priced: false,\n};\n\nexport function priceRequest(\n tokens: RequestTokens,\n model: string,\n ts: string,\n prices: readonly PriceRow[] = PRICE_TABLE,\n): PricedRequest {\n const row = findPrice(model, ts, prices);\n if (!row) return { ...UNPRICED };\n\n const { write5m, write1h } = splitCacheCreation(tokens);\n const inputUsd = perMTok(tokens.inputTokens, row.input);\n const cacheReadUsd = perMTok(tokens.cacheReadTokens, row.cacheRead);\n const cacheWrite5mUsd = perMTok(write5m, row.cacheWrite5m);\n const cacheWrite1hUsd = perMTok(write1h, row.cacheWrite1h);\n const outputUsd = perMTok(tokens.outputTokens, row.output);\n const costUsd = inputUsd + cacheReadUsd + cacheWrite5mUsd + cacheWrite1hUsd + outputUsd;\n return { inputUsd, cacheReadUsd, cacheWrite5mUsd, cacheWrite1hUsd, outputUsd, costUsd, priced: true };\n}\n\n/**\n * Older transcripts carry a cache_creation total with no ttl breakdown. Charging the\n * 5m rate there under-reads rather than over-reads, and 5m is the harness default.\n */\nfunction splitCacheCreation(tokens: RequestTokens): { write5m: number; write1h: number } {\n const write5m = tokens.cacheCreation5mTokens ?? 0;\n const write1h = tokens.cacheCreation1hTokens ?? 0;\n if (write5m > 0 || write1h > 0) return { write5m, write1h };\n return { write5m: tokens.cacheCreationTokens ?? 0, write1h: 0 };\n}\n\nfunction perMTok(tokens: number | undefined, ratePerMTok: number): number {\n return ((tokens ?? 0) * ratePerMTok) / 1_000_000;\n}\n","export type SessionClass = \"agent_spawned\" | \"human_interactive\" | \"headless_sdk\" | \"other_headless\";\n\n/** Human sessions only. A coordinator drives other agents; an adhoc session does not. */\nexport type HumanRole = \"coordinator\" | \"adhoc\";\n\n/** The agent-chat spawn record for a session, as the origin resolver returns it. */\nexport interface SessionOrigin {\n depth: number;\n parentName?: string | null;\n /** \"adopted\" and \"inherited\" mark a pane the human took over, not a spawned worker. */\n originKind?: string | null;\n profile?: string | null;\n}\n\nexport interface SessionFacts {\n /** The harness entrypoint. Agent-chat workers and `-p` miners both report \"sdk-cli\". */\n startType?: string | null;\n origin?: SessionOrigin | null;\n firstUserText?: string | null;\n humanTurnCount?: number;\n inboundKinds?: readonly string[];\n signalKinds?: readonly string[];\n}\n\nexport interface SessionClassification {\n sessionClass: SessionClass;\n reason: string;\n humanRole: HumanRole | null;\n}\n\nconst COORDINATOR_SIGNALS = new Set([\"agent_spawn\", \"chat_send\"]);\n\n/**\n * Rule order matters. The origin row wins over `startType` because agent-chat workers\n * run `claude -p` and so report \"sdk-cli\" exactly like a headless miner does.\n */\nexport function classifySession(facts: SessionFacts): SessionClassification {\n const [sessionClass, reason] = classOf(facts);\n const humanRole = sessionClass === \"human_interactive\" ? humanRoleOf(facts) : null;\n return { sessionClass, reason, humanRole };\n}\n\nfunction classOf(facts: SessionFacts): [SessionClass, string] {\n const origin = facts.origin;\n if (origin) {\n if (isAdoptedPane(origin)) return [\"human_interactive\", \"origin depth 0, human or adopted parent\"];\n return [\"agent_spawned\", \"origin depth >= 1\"];\n }\n if (facts.startType === \"sdk-cli\") return [\"headless_sdk\", \"start_type sdk-cli with no origin row\"];\n if (isProgrammaticPrompt(facts)) return [\"other_headless\", \"content-block prompt with <= 2 human turns\"];\n return [\"human_interactive\", \"no origin row, no headless marker\"];\n}\n\nfunction isAdoptedPane(origin: SessionOrigin): boolean {\n if (origin.depth !== 0) return false;\n if (origin.parentName === \"human\") return true;\n if (origin.originKind === \"adopted\" || origin.originKind === \"inherited\") return true;\n return !origin.profile;\n}\n\n/** Cron and RemoteTrigger daemons inject a structured content block, never typed prose. */\nfunction isProgrammaticPrompt(facts: SessionFacts): boolean {\n const text = (facts.firstUserText ?? \"\").trimStart();\n return text.startsWith(\"[{\") && (facts.humanTurnCount ?? 0) <= 2;\n}\n\nfunction humanRoleOf(facts: SessionFacts): HumanRole {\n if (facts.inboundKinds?.includes(\"channel_message\")) return \"coordinator\";\n if (facts.signalKinds?.some((kind) => COORDINATOR_SIGNALS.has(kind))) return \"coordinator\";\n return \"adhoc\";\n}\n","/** Half-open [lo, hi) in the band's own unit. */\nexport interface Band {\n lo: number;\n hi: number;\n name: string;\n}\n\n/** Context size in tokens. From `cf_analyze.py` BANDS. */\nexport const CONTEXT_BANDS: readonly Band[] = [\n { lo: 0, hi: 50_000, name: \"<50k\" },\n { lo: 50_000, hi: 100_000, name: \"50-100k\" },\n { lo: 100_000, hi: 200_000, name: \"100-200k\" },\n { lo: 200_000, hi: Number.POSITIVE_INFINITY, name: \"200k+\" },\n];\n\n/** Idle gap in milliseconds. From `cf_analyze.py` IDLE. */\nexport const GAP_BANDS: readonly Band[] = [\n { lo: 0, hi: 5 * 60_000, name: \"<5m\" },\n { lo: 5 * 60_000, hi: 60 * 60_000, name: \"5-60m\" },\n { lo: 60 * 60_000, hi: Number.POSITIVE_INFINITY, name: \">60m\" },\n];\n\n/** Null for a value no band covers, so a caller reports the gap instead of inventing one. */\nexport function bandOf(value: number, bands: readonly Band[]): string | null {\n for (const band of bands) {\n if (value >= band.lo && value < band.hi) return band.name;\n }\n return null;\n}\n\nexport function contextBand(tokens: number): string | null {\n return bandOf(tokens, CONTEXT_BANDS);\n}\n\nexport function gapBand(millis: number): string | null {\n return bandOf(millis, GAP_BANDS);\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { z } from \"zod\";\nimport { classifySession, type SessionClass } from \"./classify-session.js\";\nimport {\n readAgentNames,\n readCompactions,\n readCostRows,\n readCoverage,\n readAgentSessions,\n readPriceTableVersion,\n readRequestEvents,\n readSessionContexts,\n readWakeEvents,\n type CompactionRow,\n type CostRow,\n type ReportWindow,\n type SessionContext,\n} from \"./cost-report-queries.js\";\nimport { assignmentCount, heuristicFor } from \"./episodes.js\";\nimport { handoffThreshold, handoffThresholdSchema, isBootAction, parseTeleportEvents, type HandoffOptions, type HandoffThreshold } from \"./handoff-threshold.js\";\nimport { sessionInitiative } from \"./initiative.js\";\nimport { readRequestToolCalls } from \"./request-owner.js\";\nimport { sessionRole } from \"./roles.js\";\nimport { scopeFilter, type ReportScope } from \"./scope.js\";\nimport {\n ACTION_CLASSES,\n DEFAULT_ACTION_RULES,\n DEFAULT_MECHANICAL_CLASSES,\n classifyRequest,\n type ActionClass,\n type ActionRule,\n} from \"./turn-action.js\";\nimport {\n DEFAULT_EPISODE_ROLES,\n DEFAULT_NO_ACTION_CLASSES,\n buildWakeEpisodes,\n episodeNames,\n summarizeWakeEpisodes,\n wakeEpisodesSchema,\n type WakeEpisodes,\n} from \"./wake-episodes.js\";\n\nconst count = z.number().int().nonnegative();\nconst bucketSchema = z.object({ key: z.string(), requests: count, sessions: count, costUsd: z.number() });\nconst wakePartSchema = bucketSchema.extend({ midLoopRequests: count, midLoopCostUsd: z.number() });\nconst cellSchema = z.object({ wakeCause: z.string(), gapBand: z.string(), requests: count, costUsd: z.number() });\nconst fraction = z.number().min(0).max(1);\nconst roleShareSchema = z.object({ role: z.string(), costUsd: z.number(), share: fraction });\n\nexport const TOKEN_CLASSES = [\"input\", \"cache_read\", \"cache_write_5m\", \"cache_write_1h\", \"output\"] as const;\nexport type TokenClass = (typeof TOKEN_CLASSES)[number];\n\nexport const costReportSchema = z.object({\n window: z.object({ since: z.string().nullable(), until: z.string().nullable() }),\n priceTableVersion: z.number().int().nullable(),\n totals: z.object({ requests: count, sessions: count, costUsd: z.number(), unpricedRequests: count }),\n byTokenClass: z.array(z.object({ tokenClass: z.enum(TOKEN_CLASSES), tokens: count, costUsd: z.number() })),\n byAccount: z.array(bucketSchema),\n byModel: z.array(bucketSchema),\n byClass: z.array(bucketSchema),\n byRole: z.array(bucketSchema),\n /** Per role, cost by the action class of each request, from the tool calls it issued. */\n byAction: z.array(z.object({ role: z.string(), buckets: z.array(bucketSchema) })),\n /** Cost of the mechanical action classes over the window total; each role's share is over that role's cost. */\n mechanicalShare: z.object({ classes: z.array(z.enum(ACTION_CLASSES)), costUsd: z.number(), share: fraction, byRole: z.array(roleShareSchema) }),\n /** Sessions by how many episodes their class's heuristic cut them into; `none` when not yet segmented. */\n byEpisodeCount: z.array(bucketSchema),\n byInitiative: z.array(bucketSchema),\n byContextBand: z.array(bucketSchema),\n byWakeCause: z.array(wakePartSchema.extend({ parts: z.array(wakePartSchema) })),\n /** Per wake episode of the episode roles: an arrival and the requests up to the next one, mid-loop deliveries included. */\n wakeEpisodes: wakeEpisodesSchema,\n /** Per role and model, the handoff threshold K that minimises boot plus cache-read cost per request. */\n handoffThreshold: handoffThresholdSchema,\n wakeCauseByGapBand: z.array(cellSchema),\n coldRebuild: z.object({ requests: count, costUsd: z.number(), byGapBandAndCause: z.array(cellSchema) }),\n compactions: z.object({ total: count, manual: count, auto: count, midLoop: count, droppedTokens: count }),\n topSessions: z.array(\n z.object({\n sessionId: z.string(),\n sessionClass: z.string(),\n role: z.string(),\n initiative: z.string(),\n account: z.string(),\n requests: count,\n costUsd: z.number(),\n }),\n ),\n unpricedModels: z.array(z.object({ model: z.string(), requests: count, tokens: count })),\n coverage: z.object({ transcriptsIndexed: count, transcriptsDiscovered: count.nullable(), facetBacklog: count }),\n});\n\nexport type CostReport = z.infer<typeof costReportSchema>;\nexport type CostBucket = z.infer<typeof bucketSchema>;\nexport type WakeCauseBucket = CostReport[\"byWakeCause\"][number];\nexport type WakeGapCell = z.infer<typeof cellSchema>;\nexport type RoleActions = CostReport[\"byAction\"][number];\nexport type MechanicalShare = CostReport[\"mechanicalShare\"];\n\nexport interface CostReportOptions {\n /** ISO timestamp or date, inclusive. Overrides `days`. */\n since?: string;\n /** ISO timestamp or date, exclusive. */\n until?: string;\n /** Window length ending at `until`, or at `now` when `until` is absent. */\n days?: number;\n now?: Date;\n /** Sessions listed in `topSessions`. */\n top?: number;\n /** Transcripts the caller discovered on disk; the graph cannot know this. */\n transcriptsDiscovered?: number;\n /** The extraction version an audit facet must reach to count as current. */\n facetVersion?: number;\n /** Action rules in precedence order; seat-specific rules belong in the caller's config. */\n actionRules?: readonly ActionRule[];\n /** Action classes counted as mechanical in `mechanicalShare`. */\n mechanicalClasses?: readonly ActionClass[];\n /** Report roles whose wakes `wakeEpisodes` cuts into episodes. */\n episodeRoles?: readonly string[];\n /** A wake is no-action when every one of its requests falls in these action classes. */\n noActionClasses?: readonly ActionClass[];\n /** The broker log's lines, read by the caller; its teleport starts give each handoff's exit fill. */\n brokerLogLines?: () => Iterable<string>;\n handoff?: HandoffOptions;\n /** Narrows every request-keyed field to some sessions; absent means all. */\n scope?: ReportScope;\n}\n\n/** AskUserQuestion answers are the human answering, so they count under `human` (decisions Q4). */\nconst HUMAN_CAUSES: readonly string[] = [\"human_typed\", \"ask_user_answer\"];\nconst NONE = \"none\";\nconst DEFAULT_TOP = 10;\nconst EPISODE_COUNT_CAP = 5;\nconst DAY_MS = 86_400_000;\n\ninterface SessionTags {\n sessionClass: SessionClass;\n role: string;\n episodeCount: string;\n initiative: string;\n account: string;\n}\n\ntype TaggedRow = CostRow & SessionTags & { action: ActionClass; bootAction: boolean };\n\n/** Reads the graph and never writes it, so a read-only connection is enough. */\nexport function costReport(db: Db, options: CostReportOptions = {}): CostReport {\n const window = resolveWindow(options);\n const rows = readTaggedRows(db, window, options.actionRules ?? DEFAULT_ACTION_RULES).filter(scopeFilter(db, options.scope));\n return {\n window,\n priceTableVersion: readPriceTableVersion(db),\n totals: { ...sumOf(rows), sessions: new Set(rows.map((row) => row.sessionId)).size, unpricedRequests: rows.filter((row) => !row.priced).length },\n byTokenClass: tokenClasses(rows),\n ...dimensionBuckets(rows),\n byAction: roleActions(rows),\n mechanicalShare: mechanicalShare(rows, options.mechanicalClasses ?? DEFAULT_MECHANICAL_CLASSES),\n byWakeCause: wakeCauses(rows),\n wakeEpisodes: wakeEpisodes(db, window, rows, options),\n handoffThreshold: handoff(db, window, rows, options),\n wakeCauseByGapBand: gapCells(rows),\n coldRebuild: coldRebuild(rows),\n compactions: compactionCounts(readCompactions(db, window)),\n topSessions: topSessions(rows, options.top ?? DEFAULT_TOP),\n unpricedModels: unpricedModels(rows),\n coverage: { ...readCoverage(db, options.facetVersion ?? null), transcriptsDiscovered: options.transcriptsDiscovered ?? null },\n };\n}\n\nfunction readTaggedRows(db: Db, window: ReportWindow, rules: readonly ActionRule[]): TaggedRow[] {\n const costRows = readCostRows(db, window);\n const tags = tagSessions(readSessionContexts(db, [...new Set(costRows.map((row) => row.sessionId))]));\n const calls = readRequestToolCalls(db, window);\n return costRows.map((row) => {\n const requestCalls = calls.get(row.requestId) ?? [];\n return { ...row, ...tags.get(row.sessionId)!, action: classifyRequest(requestCalls, rules), bootAction: isBootAction(requestCalls) };\n });\n}\n\nexport function resolveWindow(options: CostReportOptions): ReportWindow {\n const until = options.until ?? null;\n if (options.since !== undefined) return { since: options.since, until };\n if (options.days === undefined) return { since: null, until };\n const end = until ? Date.parse(until) : (options.now ?? new Date()).getTime();\n return { since: new Date(end - options.days * DAY_MS).toISOString(), until };\n}\n\nexport function tagSessions(contexts: Map<string, SessionContext>): Map<string, SessionTags> {\n const tags = new Map<string, SessionTags>();\n for (const [sessionId, context] of contexts) {\n const classification = classifySession(context.facts);\n const episodes = context.episodes.filter((episode) => episode.heuristic === heuristicFor(classification.sessionClass));\n const worker = { profile: context.facts.origin?.profile, lifetimeMs: context.lifetimeMs, assignments: assignmentCount(episodes) };\n tags.set(sessionId, {\n sessionClass: classification.sessionClass,\n role: sessionRole(classification, worker),\n episodeCount: episodeCountKey(episodes.length),\n initiative: sessionInitiative(context.tasks, context.cwd),\n account: context.account ?? \"unknown\",\n });\n }\n return tags;\n}\n\n/** The worker report's assignment buckets: 1, 2, 3, 4, 5+. */\nfunction episodeCountKey(episodes: number): string {\n if (episodes === 0) return NONE;\n return episodes >= EPISODE_COUNT_CAP ? `${EPISODE_COUNT_CAP}+` : String(episodes);\n}\n\nfunction sumOf(rows: readonly CostRow[]): { requests: number; costUsd: number } {\n return { requests: rows.length, costUsd: rows.reduce((sum, row) => sum + row.costUsd, 0) };\n}\n\nfunction tokenClasses(rows: readonly CostRow[]): CostReport[\"byTokenClass\"] {\n const pick: Record<TokenClass, (row: CostRow) => [number, number]> = {\n input: (row) => [row.inputTokens, row.inputCostUsd],\n cache_read: (row) => [row.cacheReadTokens, row.cacheReadCostUsd],\n cache_write_5m: (row) => [row.cacheWrite5mTokens, row.cacheWrite5mCostUsd],\n cache_write_1h: (row) => [row.cacheWrite1hTokens, row.cacheWrite1hCostUsd],\n output: (row) => [row.outputTokens, row.outputCostUsd],\n };\n return TOKEN_CLASSES.map((tokenClass) => {\n const pairs = rows.map(pick[tokenClass]);\n return { tokenClass, tokens: pairs.reduce((sum, [tokens]) => sum + tokens, 0), costUsd: pairs.reduce((sum, [, cost]) => sum + cost, 0) };\n });\n}\n\nfunction dimensionBuckets(rows: readonly TaggedRow[]) {\n return {\n byAccount: bucketsBy(rows, (row) => row.account),\n byModel: bucketsBy(rows, (row) => row.model),\n byClass: bucketsBy(rows, (row) => row.sessionClass),\n byRole: bucketsBy(rows, (row) => row.role),\n byEpisodeCount: bucketsBy(rows, (row) => row.episodeCount),\n byInitiative: bucketsBy(rows, (row) => row.initiative),\n byContextBand: bucketsBy(rows, (row) => row.contextBand),\n };\n}\n\n/** Roles most expensive first, the same order as `byRole`. */\nfunction roleActions(rows: readonly TaggedRow[]): RoleActions[] {\n return [...groupRows(rows, (row) => row.role)]\n .map(([role, members]) => ({ key: role, costUsd: sumOf(members).costUsd, buckets: bucketsBy(members, (row) => row.action) }))\n .sort(byCostThenKey)\n .map(({ key, buckets }) => ({ role: key, buckets }));\n}\n\nfunction mechanicalShare(rows: readonly TaggedRow[], classes: readonly ActionClass[]): MechanicalShare {\n const isMechanical = (row: TaggedRow) => classes.includes(row.action);\n const shareOf = (members: readonly TaggedRow[]) => {\n const costUsd = sumOf(members.filter(isMechanical)).costUsd;\n return { costUsd, share: ratio(costUsd, sumOf(members).costUsd) };\n };\n const byRole = [...groupRows(rows, (row) => row.role)]\n .map(([role, members]) => ({ role, ...shareOf(members) }))\n .sort((a, b) => b.costUsd - a.costUsd || a.role.localeCompare(b.role));\n return { classes: [...classes], ...shareOf(rows), byRole };\n}\n\nfunction ratio(part: number, whole: number): number {\n return whole > 0 ? Math.min(part / whole, 1) : 0;\n}\n\n/** Most expensive first; ties by key so the report is stable. */\nfunction bucketsBy<T extends CostRow>(rows: readonly T[], keyOf: (row: T) => string): CostBucket[] {\n const groups = groupRows(rows, keyOf);\n return [...groups]\n .map(([key, members]) => ({ key, ...sumOf(members), sessions: new Set(members.map((row) => row.sessionId)).size }))\n .sort(byCostThenKey);\n}\n\nfunction groupRows<T>(rows: readonly T[], keyOf: (row: T) => string): Map<string, T[]> {\n const groups = new Map<string, T[]>();\n for (const row of rows) {\n const key = keyOf(row);\n const members = groups.get(key);\n if (members) members.push(row);\n else groups.set(key, [row]);\n }\n return groups;\n}\n\nfunction byCostThenKey(a: { key: string; costUsd: number }, b: { key: string; costUsd: number }): number {\n return b.costUsd - a.costUsd || a.key.localeCompare(b.key);\n}\n\nfunction wakeCauses(rows: readonly CostRow[]): WakeCauseBucket[] {\n const causeOf = (row: CostRow) => row.wakeCause ?? NONE;\n const groupOf = (row: CostRow) => (HUMAN_CAUSES.includes(causeOf(row)) ? \"human\" : causeOf(row));\n return [...groupRows(rows, groupOf)]\n .map(([key, members]) => ({\n ...wakePart(key, members),\n parts: key === \"human\" ? [...groupRows(members, causeOf)].map(([cause, part]) => wakePart(cause, part)).sort(byCostThenKey) : [],\n }))\n .sort(byCostThenKey);\n}\n\nfunction wakeEpisodes(db: Db, window: ReportWindow, rows: readonly TaggedRow[], options: CostReportOptions): WakeEpisodes {\n const roles = options.episodeRoles ?? DEFAULT_EPISODE_ROLES;\n const noActionClasses = options.noActionClasses ?? DEFAULT_NO_ACTION_CLASSES;\n const members = rows.filter((row) => roles.includes(row.role));\n const sessionIds = [...new Set(members.map((row) => row.sessionId))];\n const eventOf = readRequestEvents(db, window, sessionIds);\n const requests = members.map((row) => ({ costUsd: row.costUsd, action: row.action, eventKey: eventOf.get(row.requestId) ?? null }));\n const episodes = buildWakeEpisodes(readWakeEvents(db, window, sessionIds), requests, episodeNames(readAgentNames(db)), noActionClasses);\n return summarizeWakeEpisodes(episodes, requests, roles, noActionClasses);\n}\n\nfunction handoff(db: Db, window: ReportWindow, rows: readonly TaggedRow[], options: CostReportOptions): HandoffThreshold {\n const inWindow = (ts: string) => (window.since === null || ts >= window.since) && (window.until === null || ts < window.until);\n const teleports = parseTeleportEvents(options.brokerLogLines?.() ?? []).filter((event) => inWindow(event.ts));\n const requests = rows\n .filter((row) => !row.isSidechain)\n .map((row) => ({\n sessionId: row.sessionId,\n role: row.role,\n model: row.model,\n ts: row.ts,\n fill: row.contextTokens,\n tokens: { inputTokens: row.inputTokens, cacheReadTokens: row.cacheReadTokens, cacheCreation5mTokens: row.cacheWrite5mTokens, cacheCreation1hTokens: row.cacheWrite1hTokens, outputTokens: row.outputTokens },\n bootAction: row.bootAction,\n }));\n return handoffThreshold(requests, teleports, readAgentSessions(db), options.handoff);\n}\n\nfunction wakePart(key: string, rows: readonly CostRow[]) {\n const midLoop = rows.filter((row) => row.wakeDelivery === \"mid_loop\");\n const sessions = new Set(rows.map((row) => row.sessionId)).size;\n return { key, ...sumOf(rows), sessions, midLoopRequests: midLoop.length, midLoopCostUsd: sumOf(midLoop).costUsd };\n}\n\nfunction gapCells(rows: readonly CostRow[]): WakeGapCell[] {\n const keyOf = (row: CostRow) => JSON.stringify([row.wakeCause ?? NONE, row.gapBand ?? NONE]);\n return [...groupRows(rows, keyOf)]\n .map(([key, members]) => {\n const [wakeCause, gapBand] = JSON.parse(key) as [string, string];\n return { wakeCause, gapBand, ...sumOf(members) };\n })\n .sort((a, b) => b.costUsd - a.costUsd || a.wakeCause.localeCompare(b.wakeCause) || a.gapBand.localeCompare(b.gapBand));\n}\n\nfunction coldRebuild(rows: readonly CostRow[]): CostReport[\"coldRebuild\"] {\n const cold = rows.filter((row) => row.isCold);\n return { ...sumOf(cold), byGapBandAndCause: gapCells(cold) };\n}\n\nfunction compactionCounts(rows: readonly CompactionRow[]): CostReport[\"compactions\"] {\n return {\n total: rows.length,\n manual: rows.filter((row) => row.trigger === \"manual\").length,\n auto: rows.filter((row) => row.trigger === \"auto\").length,\n midLoop: rows.filter((row) => row.midLoop).length,\n droppedTokens: rows.reduce((sum, row) => sum + (row.droppedTokens ?? 0), 0),\n };\n}\n\nfunction topSessions(rows: readonly TaggedRow[], top: number): CostReport[\"topSessions\"] {\n return [...groupRows(rows, (row) => row.sessionId)]\n .map(([sessionId, members]) => {\n const { sessionClass, role, initiative, account } = members[0]!;\n return { sessionId, sessionClass, role, initiative, account, ...sumOf(members) };\n })\n .sort((a, b) => b.costUsd - a.costUsd || a.sessionId.localeCompare(b.sessionId))\n .slice(0, top);\n}\n\nfunction unpricedModels(rows: readonly CostRow[]): CostReport[\"unpricedModels\"] {\n const unpriced = rows.filter((row) => !row.priced);\n return [...groupRows(unpriced, (row) => row.model)]\n .map(([model, members]) => ({ model, requests: members.length, tokens: members.reduce((sum, row) => sum + tokensOf(row), 0) }))\n .sort((a, b) => b.tokens - a.tokens || a.model.localeCompare(b.model));\n}\n\nfunction tokensOf(row: CostRow): number {\n return row.inputTokens + row.cacheReadTokens + row.cacheWrite5mTokens + row.cacheWrite1hTokens + row.outputTokens;\n}\n","import { AUDIT_FACET, EPISODE_TABLE, FACET_TABLE, KIT } from \"@titan-design/session-graph\";\nimport type { Db } from \"@titan-design/store-sqlite\";\nimport type { SessionFacts } from \"./classify-session.js\";\nimport type { TaskInitiative } from \"./initiative.js\";\n\n/** ISO bounds on request `ts`: `since` inclusive, `until` exclusive, null for open. */\nexport interface ReportWindow {\n since: string | null;\n until: string | null;\n}\n\n/** One deduplicated, priced request as the `request_cost` view returns it. */\nexport interface CostRow {\n sessionId: string;\n requestId: string;\n ts: string;\n model: string;\n /** Tokens in context at the request. */\n contextTokens: number;\n isSidechain: boolean;\n inputTokens: number;\n cacheReadTokens: number;\n cacheWrite5mTokens: number;\n cacheWrite1hTokens: number;\n outputTokens: number;\n inputCostUsd: number;\n cacheReadCostUsd: number;\n cacheWrite5mCostUsd: number;\n cacheWrite1hCostUsd: number;\n outputCostUsd: number;\n costUsd: number;\n priced: boolean;\n isCold: boolean;\n contextBand: string;\n gapBand: string | null;\n wakeCause: string | null;\n wakeDelivery: string | null;\n}\n\n/** What the report needs about one session beyond its requests. */\nexport interface SessionContext {\n facts: SessionFacts;\n cwd: string | null;\n account: string | null;\n tasks: TaskInitiative[];\n /** First to last main-thread request over the whole session, not just the window. */\n lifetimeMs: number;\n /** Stored episode rows of every heuristic, in episode order. */\n episodes: StoredEpisode[];\n}\n\nexport interface StoredEpisode {\n heuristic: string;\n openedBy: string;\n}\n\nexport interface CompactionRow {\n trigger: string | null;\n midLoop: boolean;\n droppedTokens: number | null;\n}\n\nconst IN_WINDOW = \"(@since IS NULL OR ts >= @since) AND (@until IS NULL OR ts < @until)\";\nconst IN_SESSIONS = \"session_id IN (SELECT value FROM json_each(@ids))\";\n\n// The 5m write column mirrors the view: a split-less write is billed at the 5m rate.\nconst COST_ROWS = `\n SELECT session_id AS sessionId, request_id AS requestId, ts, model, COALESCE(context_tokens, 0) AS contextTokens, is_sidechain AS isSidechain,\n input_tokens AS inputTokens, cache_read_tokens AS cacheReadTokens,\n CASE WHEN cache_creation_5m + cache_creation_1h = 0 THEN cache_creation_tokens ELSE cache_creation_5m END AS cacheWrite5mTokens,\n cache_creation_1h AS cacheWrite1hTokens, output_tokens AS outputTokens,\n input_cost_usd AS inputCostUsd, cache_read_cost_usd AS cacheReadCostUsd,\n cache_write_5m_cost_usd AS cacheWrite5mCostUsd, cache_write_1h_cost_usd AS cacheWrite1hCostUsd,\n output_cost_usd AS outputCostUsd, cost_usd AS costUsd, priced, is_cold AS isCold,\n context_band AS contextBand, gap_band AS gapBand, wake_cause AS wakeCause, wake_delivery AS wakeDelivery\n FROM request_cost WHERE ${IN_WINDOW}\n`;\n\nexport function readCostRows(db: Db, window: ReportWindow): CostRow[] {\n type Row = Omit<CostRow, \"priced\" | \"isCold\" | \"isSidechain\"> & { priced: number; isCold: number; isSidechain: number | null };\n const rows = db.prepare(COST_ROWS).all(window) as Row[];\n return rows.map((row) => ({ ...row, priced: row.priced === 1, isCold: row.isCold === 1, isSidechain: row.isSidechain === 1 }));\n}\n\nexport function readCompactions(db: Db, window: ReportWindow): CompactionRow[] {\n const sql = `SELECT trigger, mid_loop AS midLoop, dropped_tokens AS droppedTokens FROM compaction WHERE ${IN_WINDOW}`;\n const rows = db.prepare(sql).all(window) as (Omit<CompactionRow, \"midLoop\"> & { midLoop: number | null })[];\n return rows.map((row) => ({ ...row, midLoop: row.midLoop === 1 }));\n}\n\n/** The graph's own price version, which is what `request_cost` priced with; null before any price row exists. */\nexport function readPriceTableVersion(db: Db): number | null {\n return (db.prepare(\"SELECT MAX(table_version) AS version FROM price\").get() as { version: number | null }).version;\n}\n\n/** Indexed transcripts, and those whose audit facet is missing or older than `facetVersion`. */\nexport function readCoverage(db: Db, facetVersion: number | null): { transcriptsIndexed: number; facetBacklog: number } {\n const indexed = db.prepare(`SELECT COUNT(*) AS n FROM \"${KIT.watermark}\"`).get() as { n: number };\n const backlog = db\n .prepare(\n `SELECT COUNT(*) AS n FROM \"${KIT.watermark}\" t LEFT JOIN \"${FACET_TABLE}\" f\n ON f.transcript_id = t.source_id AND f.facet = @facet AND (@version IS NULL OR f.version >= @version)\n WHERE f.transcript_id IS NULL`,\n )\n .get({ facet: AUDIT_FACET, version: facetVersion }) as { n: number };\n return { transcriptsIndexed: indexed.n, facetBacklog: backlog.n };\n}\n\n/** An arrival that opens a wake episode: a turn-start record or a mid-loop `queued_command` delivery. */\nexport interface WakeEventRow {\n key: string;\n sessionId: string;\n cause: string;\n delivery: string;\n fromName: string | null;\n /** The same `msg_id` reached more than one session. */\n broadcast: boolean;\n}\n\n/** One agent-chat identity: the name a session carries and how it came to carry it. */\nexport interface AgentNameRow {\n sessionId: string;\n agentName: string;\n originKind: string | null;\n profile: string | null;\n}\n\nconst EPISODE_DELIVERIES = \"('turn_start', 'mid_loop')\";\n\n// A record with several blocks is one event; its last block decides, as the request rollup does.\nconst WAKE_EVENTS = `\n WITH event AS (\n SELECT transcript_id, byte_offset, MAX(block_index) AS block_index FROM inbound\n WHERE ${IN_SESSIONS} AND ${IN_WINDOW} AND delivery IN ${EPISODE_DELIVERIES}\n GROUP BY transcript_id, byte_offset\n ), fanout AS (\n SELECT msg_id, COUNT(DISTINCT session_id) AS receivers FROM inbound\n WHERE msg_id IN (SELECT i.msg_id FROM event JOIN inbound i USING (transcript_id, byte_offset, block_index))\n GROUP BY msg_id\n )\n SELECT i.transcript_id || ':' || i.byte_offset AS key, i.session_id AS sessionId, i.cause, i.delivery,\n i.from_name AS fromName, COALESCE(f.receivers, 1) > 1 AS broadcast\n FROM event JOIN inbound i USING (transcript_id, byte_offset, block_index)\n LEFT JOIN fanout f ON f.msg_id = i.msg_id\n ORDER BY i.transcript_id, i.byte_offset`;\n\nconst REQUEST_EVENTS = `\n SELECT d.request_id AS requestId, d.transcript_id || ':' || (\n SELECT MAX(i.byte_offset) FROM inbound i\n WHERE i.transcript_id = d.transcript_id AND i.session_id = d.session_id AND i.byte_offset < d.byte_offset\n AND i.delivery IN ${EPISODE_DELIVERIES}) AS eventKey\n FROM request_dedup d WHERE d.${IN_SESSIONS} AND (@since IS NULL OR d.ts >= @since) AND (@until IS NULL OR d.ts < @until)`;\n\nexport function readWakeEvents(db: Db, window: ReportWindow, sessionIds: readonly string[]): WakeEventRow[] {\n const rows = db.prepare(WAKE_EVENTS).all({ ...window, ids: JSON.stringify(sessionIds) }) as (Omit<WakeEventRow, \"broadcast\"> & { broadcast: number })[];\n return rows.map((row) => ({ ...row, broadcast: row.broadcast === 1 }));\n}\n\n/** The event each request in the window follows, keyed by `request_id`; null before a transcript's first event. */\nexport function readRequestEvents(db: Db, window: ReportWindow, sessionIds: readonly string[]): Map<string, string | null> {\n const rows = db.prepare(REQUEST_EVENTS).all({ ...window, ids: JSON.stringify(sessionIds) }) as { requestId: string; eventKey: string | null }[];\n return new Map(rows.map((row) => [row.requestId, row.eventKey]));\n}\n\nexport function readAgentNames(db: Db): AgentNameRow[] {\n const sql = `SELECT session_id AS sessionId, agent_name AS agentName, origin_kind AS originKind, profile FROM session_origin WHERE agent_name IS NOT NULL`;\n return db.prepare(sql).all() as AgentNameRow[];\n}\n\n/** Each agent-chat agent id to the sessions it ran as; the broker log names agents by id. */\nexport function readAgentSessions(db: Db): Map<string, string[]> {\n const sql = `SELECT agent_id AS agentId, session_id AS sessionId FROM session_origin WHERE agent_id IS NOT NULL`;\n const sessions = new Map<string, string[]>();\n for (const row of db.prepare(sql).all() as { agentId: string; sessionId: string }[]) sessions.set(row.agentId, [...(sessions.get(row.agentId) ?? []), row.sessionId]);\n return sessions;\n}\n\nexport function readSessionContexts(db: Db, sessionIds: readonly string[]): Map<string, SessionContext> {\n const ids = JSON.stringify(sessionIds);\n const contexts = new Map<string, SessionContext>(sessionIds.map((id) => [id, emptyContext()]));\n addSessionRows(db, ids, contexts);\n addOrigins(db, ids, contexts);\n addInbounds(db, ids, contexts);\n addSignals(db, ids, contexts);\n addTaskInitiatives(db, ids, contexts);\n addLifetimes(db, ids, contexts);\n addEpisodes(db, ids, contexts);\n return contexts;\n}\n\nfunction emptyContext(): SessionContext {\n return { facts: { inboundKinds: [], signalKinds: [], humanTurnCount: 0 }, cwd: null, account: null, tasks: [], lifetimeMs: 0, episodes: [] };\n}\n\nfunction addSessionRows(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, start_type AS startType, cwd, seed_prompt AS seedPrompt, account FROM session WHERE ${IN_SESSIONS}`;\n type Row = { sessionId: string; startType: string | null; cwd: string | null; seedPrompt: string | null; account: string | null };\n for (const row of db.prepare(sql).all({ ids }) as Row[]) {\n const context = contexts.get(row.sessionId)!;\n context.cwd = row.cwd;\n context.account = row.account;\n context.facts.startType = row.startType;\n context.facts.firstUserText = row.seedPrompt;\n }\n}\n\nfunction addOrigins(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, depth, parent_name AS parentName, origin_kind AS originKind, profile FROM session_origin WHERE ${IN_SESSIONS}`;\n type Row = { sessionId: string; depth: number | null; parentName: string | null; originKind: string | null; profile: string | null };\n for (const { sessionId, depth, ...origin } of db.prepare(sql).all({ ids }) as Row[]) {\n contexts.get(sessionId)!.facts.origin = { ...origin, depth: depth ?? 0 };\n }\n}\n\nfunction addInbounds(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, cause, SUM(delivery = 'turn_start') AS turnStarts FROM inbound WHERE ${IN_SESSIONS} GROUP BY session_id, cause`;\n for (const row of db.prepare(sql).all({ ids }) as { sessionId: string; cause: string; turnStarts: number }[]) {\n const facts = contexts.get(row.sessionId)!.facts;\n facts.inboundKinds = [...(facts.inboundKinds ?? []), row.cause];\n if (row.cause === \"human_typed\") facts.humanTurnCount = row.turnStarts;\n }\n}\n\nfunction addSignals(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT DISTINCT session_id AS sessionId, signal FROM session_signal WHERE ${IN_SESSIONS}`;\n for (const row of db.prepare(sql).all({ ids }) as { sessionId: string; signal: string }[]) {\n const facts = contexts.get(row.sessionId)!.facts;\n facts.signalKinds = [...(facts.signalKinds ?? []), row.signal];\n }\n}\n\nfunction addTaskInitiatives(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `\n SELECT substr(e.source_ref, 9) AS sessionId, t.initiative, COUNT(*) AS edges\n FROM \"${KIT.edge}\" e JOIN task t ON t.task_ref = e.target_ref\n WHERE e.relation = 'ran' AND e.t_expired IS NULL AND t.initiative IS NOT NULL\n AND e.source_ref IN (SELECT 'session:' || value FROM json_each(@ids))\n GROUP BY e.source_ref, t.initiative`;\n for (const row of db.prepare(sql).all({ ids }) as ({ sessionId: string } & TaskInitiative)[]) {\n contexts.get(row.sessionId)!.tasks.push({ initiative: row.initiative, edges: row.edges });\n }\n}\n\nfunction addLifetimes(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, MIN(ts) AS first, MAX(ts) AS last FROM request_dedup WHERE ${IN_SESSIONS} AND is_sidechain = 0 GROUP BY session_id`;\n for (const row of db.prepare(sql).all({ ids }) as { sessionId: string; first: string; last: string }[]) {\n contexts.get(row.sessionId)!.lifetimeMs = Date.parse(row.last) - Date.parse(row.first);\n }\n}\n\nfunction addEpisodes(db: Db, ids: string, contexts: Map<string, SessionContext>): void {\n const sql = `SELECT session_id AS sessionId, heuristic, opened_by AS openedBy FROM \"${EPISODE_TABLE}\" WHERE ${IN_SESSIONS} ORDER BY session_id, heuristic, episode_index`;\n for (const { sessionId, ...episode } of db.prepare(sql).all({ ids }) as ({ sessionId: string } & StoredEpisode)[]) {\n contexts.get(sessionId)!.episodes.push(episode);\n }\n}\n","import { replaceEpisodes, type EpisodeRow, type SessionGraph } from \"@titan-design/session-graph\";\nimport type { Db } from \"@titan-design/store-sqlite\";\nimport { classifySession, type SessionClass } from \"./classify-session.js\";\nimport { readSessionContexts } from \"./cost-report-queries.js\";\n\n/** Two rule sets on purpose (design section 18): workers segment by assignment, coordinators by work phase. */\nexport type Heuristic = \"worker-v1\" | \"coordinator-v1\";\nexport const HEURISTIC_VERSIONS: Readonly<Record<Heuristic, number>> = { \"worker-v1\": 1, \"coordinator-v1\": 1 };\n\nexport interface EpisodeRequest {\n offset: number;\n ts: string;\n transcriptId: number;\n contextTokens: number;\n wakeCause: string | null;\n}\nexport interface EpisodeInbound {\n offset: number;\n ts: string;\n transcriptId: number;\n cause: string;\n}\nexport interface EpisodeSignal {\n offset: number;\n ts: string;\n transcriptId: number;\n signal: string;\n}\nexport interface EpisodeInput {\n requests: readonly EpisodeRequest[];\n inbounds: readonly EpisodeInbound[];\n signals: readonly EpisodeSignal[];\n /** An agent-chat spawn has a brief; anything else opens at `session_start`. */\n spawned: boolean;\n}\n\nconst MINUTE_MS = 60_000;\nexport const IDLE_GAP_MS = 30 * MINUTE_MS;\nexport const CHANNEL_CLUSTER_MS = 10 * MINUTE_MS;\nexport const COORDINATOR_MIN_EPISODE_REQUESTS = 8;\nexport const COORDINATOR_MERGE_DEDUPE_REQUESTS = 15;\nexport const COORDINATOR_WAVE_QUIET_REQUESTS = 15;\nexport const CONTEXT_RESET_TOKENS = 20_000;\nconst DELIVERABLE_SIGNALS = new Set([\"status_report\", \"pr_create\", \"commit\", \"doc_written\", \"task_wrap\"]);\nconst ASSIGNMENT_OPENERS = new Set([\"brief\", \"channel_followup\"]);\n\n/** Pure: the same rows always cut the same way. Rows come back in episode order. */\nexport function buildEpisodes(input: EpisodeInput, heuristic: Heuristic): EpisodeRow[] {\n return heuristic === \"worker-v1\" ? workerEpisodes(input) : coordinatorEpisodes(input);\n}\n\n/** Workers are segmented; human sessions get the coordinator rule; headless runs get none. */\nexport function heuristicFor(sessionClass: SessionClass): Heuristic | null {\n if (sessionClass === \"agent_spawned\") return \"worker-v1\";\n if (sessionClass === \"human_interactive\") return \"coordinator-v1\";\n return null;\n}\n\n/** The worker report's `n_assignments`: episodes an assignment opened, which is what the standing-peer overlay counts. */\nexport function assignmentCount(rows: readonly Pick<EpisodeRow, \"openedBy\">[]): number {\n return rows.filter((row) => ASSIGNMENT_OPENERS.has(row.openedBy)).length;\n}\n\n// ---------------------------------------------------------------- worker-v1\n\ntype Event =\n | { kind: \"request\"; offset: number; ts: string; ms: number; transcriptId: number }\n | { kind: \"inbound\"; offset: number; ts: string; ms: number; transcriptId: number; cause: string }\n | { kind: \"signal\"; offset: number; ts: string; ms: number; transcriptId: number; signal: string };\n\ninterface Draft {\n row: EpisodeRow;\n hasRequest: boolean;\n}\n\ninterface WorkerState {\n drafts: Draft[];\n lastRequestMs: number | null;\n lastChannelMs: number | null;\n}\n\n/** worker-forensics-report.md section 5 and wf_analyze.py:241-251, with the status-report trigger from design section 9. */\nfunction workerEpisodes(input: EpisodeInput): EpisodeRow[] {\n const state: WorkerState = { drafts: [], lastRequestMs: null, lastChannelMs: null };\n for (const event of timeline(input)) {\n const current = state.drafts.at(-1);\n const reason = current ? workerBoundary(event, current, state) : input.spawned ? \"brief\" : \"session_start\";\n if (reason && (!current || current.hasRequest)) state.drafts.push(openDraft(event, reason, state.drafts.length));\n absorb(state.drafts.at(-1)!, event);\n if (event.kind === \"request\") state.lastRequestMs = event.ms;\n if (isChannel(event)) state.lastChannelMs = event.ms;\n }\n return state.drafts.map((draft) => draft.row);\n}\n\nfunction workerBoundary(event: Event, current: Draft, state: WorkerState): string | null {\n if (event.kind === \"request\" && state.lastRequestMs !== null && event.ms - state.lastRequestMs >= IDLE_GAP_MS) return \"idle_gap\";\n if (!isChannel(event)) return null;\n const startsCluster = state.lastChannelMs === null || event.ms - state.lastChannelMs > CHANNEL_CLUSTER_MS;\n return startsCluster && current.row.firstStatusOffset != null ? \"channel_followup\" : null;\n}\n\nfunction isChannel(event: Event): boolean {\n return event.kind === \"inbound\" && event.cause === \"channel_message\";\n}\n\nfunction openDraft(event: Event, openedBy: string, episodeIndex: number): Draft {\n const assignment = ASSIGNMENT_OPENERS.has(openedBy) && event.kind === \"inbound\" ? event.offset : null;\n const row: EpisodeRow = {\n episodeIndex,\n heuristicVersion: HEURISTIC_VERSIONS[\"worker-v1\"],\n startedAt: event.ts,\n endedAt: event.ts,\n startOffset: event.offset,\n endOffset: event.offset,\n openedBy,\n startTranscriptId: event.transcriptId,\n endTranscriptId: event.transcriptId,\n assignmentOffset: assignment,\n firstDeliverableOffset: null,\n firstDeliverableSignal: null,\n firstStatusOffset: null,\n };\n return { row, hasRequest: false };\n}\n\n/** The first commit is recorded as a deliverable but not as a report: commit fires early for implementers (221 of 411). */\nfunction absorb(draft: Draft, event: Event): void {\n draft.row.endedAt = event.ts;\n draft.row.endOffset = event.offset;\n draft.row.endTranscriptId = event.transcriptId;\n if (event.kind === \"request\") draft.hasRequest = true;\n if (event.kind !== \"signal\") return;\n if (draft.row.firstDeliverableOffset == null && DELIVERABLE_SIGNALS.has(event.signal)) {\n draft.row.firstDeliverableOffset = event.offset;\n draft.row.firstDeliverableSignal = event.signal;\n }\n if (draft.row.firstStatusOffset == null && event.signal === \"status_report\") draft.row.firstStatusOffset = event.offset;\n}\n\n/**\n * Offsets only order events inside one transcript, so time orders first, then the transcript a\n * session resumed into, then the offset breaks ties within it.\n */\nfunction timeline(input: EpisodeInput): Event[] {\n const events: Event[] = [\n ...input.requests.map((r) => ({ kind: \"request\" as const, offset: r.offset, ts: r.ts, ms: Date.parse(r.ts), transcriptId: r.transcriptId })),\n ...input.inbounds.map((i) => ({ kind: \"inbound\" as const, offset: i.offset, ts: i.ts, ms: Date.parse(i.ts), transcriptId: i.transcriptId, cause: i.cause })),\n ...input.signals.map((s) => ({ kind: \"signal\" as const, offset: s.offset, ts: s.ts, ms: Date.parse(s.ts), transcriptId: s.transcriptId, signal: s.signal })),\n ];\n return events.sort((a, b) => a.ms - b.ms || a.transcriptId - b.transcriptId || a.offset - b.offset);\n}\n\n// ---------------------------------------------------------------- coordinator-v1\n\ninterface Turn {\n request: EpisodeRequest;\n ms: number;\n signals: Set<string>;\n}\n\ninterface Boundary {\n at: number;\n reason: string;\n}\n\n/** coordinator-forensics-report.md section 1, ported from co_analyze.py `segment` with `merge_lag` 0. */\nfunction coordinatorEpisodes(input: EpisodeInput): EpisodeRow[] {\n const turns = toTurns(input);\n if (turns.length === 0) return [];\n const opens = [{ at: 0, reason: \"session_start\" }, ...dropShort(coordinatorBoundaries(turns), turns.length)];\n return opens.map((open, index) => {\n const first = turns[open.at]!.request;\n const last = turns[(opens[index + 1]?.at ?? turns.length) - 1]!.request;\n return {\n episodeIndex: index,\n heuristicVersion: HEURISTIC_VERSIONS[\"coordinator-v1\"],\n startedAt: first.ts,\n endedAt: last.ts,\n startOffset: first.offset,\n endOffset: last.offset,\n startTranscriptId: first.transcriptId,\n endTranscriptId: last.transcriptId,\n openedBy: open.reason,\n };\n });\n}\n\nfunction coordinatorBoundaries(turns: readonly Turn[]): Boundary[] {\n const bounds: Boundary[] = [];\n let spawnedSince = false;\n let lastMerge = -Infinity;\n for (let i = 1; i < turns.length; i++) {\n const reason = coordinatorTrigger(turns, i, lastMerge) ?? (spawnedSince && waveComplete(turns, i) ? \"spawn_wave_complete\" : null);\n if (turns[i - 1]!.signals.has(\"pr_merge\")) lastMerge = i;\n if (reason) {\n bounds.push({ at: i, reason });\n spawnedSince = false;\n }\n if (turns[i]!.signals.has(\"agent_spawn\")) spawnedSince = true;\n }\n return bounds;\n}\n\n/** Checked in the source's order; the first that fires names the boundary. */\nfunction coordinatorTrigger(turns: readonly Turn[], i: number, lastMerge: number): string | null {\n const [a, b] = [turns[i - 1]!, turns[i]!];\n if (b.ms - a.ms >= IDLE_GAP_MS) return \"idle_gap\";\n if (a.signals.has(\"pr_merge\") && i - lastMerge > COORDINATOR_MERGE_DEDUPE_REQUESTS) return \"pr_merge\";\n if (a.signals.has(\"task_wrap\") || a.signals.has(\"task_done\")) return \"task_wrap\";\n const drop = a.request.contextTokens - b.request.contextTokens;\n if (a.request.contextTokens > 0 && drop > CONTEXT_RESET_TOKENS) return \"context_reset\";\n return null;\n}\n\n/** The last agent-chat traffic before a quiet run; the source also counted any agent-chat tool call, which only reaches the graph as `chat_send` or `agent_spawn`. */\nfunction waveComplete(turns: readonly Turn[], i: number): boolean {\n return hasChatTraffic(turns[i - 1]!) && !turns.slice(i, i + COORDINATOR_WAVE_QUIET_REQUESTS).some(hasChatTraffic);\n}\n\nfunction hasChatTraffic(turn: Turn): boolean {\n return turn.request.wakeCause === \"channel_message\" || turn.signals.has(\"chat_send\") || turn.signals.has(\"agent_spawn\");\n}\n\n/** No episode shorter than the minimum, at either end of the session. */\nfunction dropShort(bounds: readonly Boundary[], total: number): Boundary[] {\n const kept: Boundary[] = [];\n let last = 0;\n for (const bound of bounds) {\n if (bound.at - last < COORDINATOR_MIN_EPISODE_REQUESTS || total - bound.at < COORDINATOR_MIN_EPISODE_REQUESTS) continue;\n kept.push(bound);\n last = bound.at;\n }\n return kept;\n}\n\n/** A signal belongs to the latest request at or before it; one before any request goes to the first. */\nfunction toTurns(input: EpisodeInput): Turn[] {\n const turns = input.requests\n .map((request) => ({ request, ms: Date.parse(request.ts), signals: new Set<string>() }))\n .sort((a, b) => a.ms - b.ms || a.request.transcriptId - b.request.transcriptId || a.request.offset - b.request.offset);\n for (const signal of input.signals) ownerOf(turns, signal)?.signals.add(signal.signal);\n return turns;\n}\n\nfunction ownerOf(turns: readonly Turn[], signal: EpisodeSignal): Turn | undefined {\n const ms = Date.parse(signal.ts);\n for (let i = turns.length - 1; i >= 0; i--) {\n const turn = turns[i]!;\n if (turn.ms < ms || (turn.ms === ms && turn.request.offset <= signal.offset)) return turn;\n }\n return turns[0];\n}\n\n// ---------------------------------------------------------------- graph I/O\n\nconst IN_SESSION = \"session_id = ?\";\n\n/**\n * `request_dedup` for one session without ranking every request: SQLite cannot push the session filter\n * through the view's window. Copies of a request can sit in other sessions, so the rank still covers\n * every copy of each request id the session holds.\n */\nconst SESSION_REQUEST_DEDUP = `\n SELECT * FROM (\n SELECT r.*, ROW_NUMBER() OVER (PARTITION BY r.request_id ORDER BY r.ts, r.transcript_id) AS copy_rank\n FROM request r WHERE r.request_id IN (SELECT request_id FROM request WHERE session_id = @sessionId)\n ) WHERE copy_rank = 1 AND session_id = @sessionId`;\n\n/** Main-thread requests only: a sidechain's requests belong to its subagent, not to the session's episodes. */\nexport const EPISODE_REQUESTS_SQL = `\n SELECT byte_offset AS offset, ts, transcript_id AS transcriptId, context_tokens AS contextTokens, wake_cause AS wakeCause\n FROM (${SESSION_REQUEST_DEDUP}) WHERE is_sidechain = 0`;\n\nexport function readEpisodeInput(db: Db, sessionId: string, spawned: boolean): EpisodeInput {\n const requests = db.prepare(EPISODE_REQUESTS_SQL).all({ sessionId }) as EpisodeRequest[];\n const inbounds = db\n .prepare(`SELECT byte_offset AS offset, ts, transcript_id AS transcriptId, cause FROM inbound WHERE ${IN_SESSION}`)\n .all(sessionId) as EpisodeInbound[];\n const signals = db\n .prepare(`SELECT byte_offset AS offset, ts, transcript_id AS transcriptId, signal FROM session_signal WHERE ${IN_SESSION}`)\n .all(sessionId) as EpisodeSignal[];\n return { requests, inbounds, signals, spawned };\n}\n\nexport interface WrittenEpisodes {\n sessionId: string;\n heuristic: Heuristic;\n episodes: number;\n}\n\n/** Segments each session with its class's heuristic and replaces that heuristic's rows. Headless sessions are skipped. */\nexport function writeEpisodes(graph: SessionGraph, sessionIds: readonly string[]): WrittenEpisodes[] {\n const written: WrittenEpisodes[] = [];\n for (const [sessionId, context] of readSessionContexts(graph.db, sessionIds)) {\n const { sessionClass } = classifySession(context.facts);\n const heuristic = heuristicFor(sessionClass);\n if (!heuristic) continue;\n const rows = buildEpisodes(readEpisodeInput(graph.db, sessionId, sessionClass === \"agent_spawned\"), heuristic);\n written.push({ sessionId, heuristic, episodes: replaceEpisodes(graph, sessionId, heuristic, rows) });\n }\n return written;\n}\n","import { z } from \"zod\";\nimport { priceRequest, type RequestTokens } from \"./price-request.js\";\nimport { PRICE_TABLE, findPrice, type PriceRow } from \"./prices.js\";\nimport type { ActionCall } from \"./turn-action.js\";\n\n/** A dispatch or a send; with any file write, the first such request ends a session's boot. */\nexport const BOOT_TOOL = /(agent_(spawn|resume)|chat_(send|broadcast))$/;\n\n/** The charter's `teleport_k` and `retire_k` at the time of the TP-499 plan; callers pass their own. */\nexport const DEFAULT_CONFIGURED_K: readonly number[] = [170_000, 250_000];\nexport const DEFAULT_K_SWEEP = { fromK: 20_000, toK: 1_000_000, stepK: 5_000 } as const;\nexport const DEFAULT_REVIEWER_ROLE = \"worker:reviewer\";\nexport const DEFAULT_STANDING_ROLE = \"worker:standing_peer\";\nexport const DEFAULT_REVIEWER_PRS = 10;\n/** The broker logs this when a seat starts handing over; `from` is the outgoing agent id. */\nexport const TELEPORT_EVENT = \"teleport_started\";\n\nconst MTOK = 1_000_000;\nconst count = z.number().int().nonnegative();\nconst kCostSchema = z.object({ k: count, costPerRequest: z.number().nullable(), deltaPerRequest: z.number().nullable() });\nconst sweepResultSchema = z.object({ bestK: count.nullable(), bestCostPerRequest: z.number().nullable(), atConfigured: z.array(kCostSchema) });\nconst paramsSchema = z.object({ bootCostUsd: z.number(), bootFill: z.number(), growthPerRequest: z.number(), readPricePerMTok: z.number() });\n\nconst sessionSchema = paramsSchema.extend({\n sessionId: z.string(),\n role: z.string(),\n model: z.string(),\n requests: count,\n bootRequests: count,\n exitFill: count,\n /** Timestamp of the session's last request; orders reviewer cohorts by recency. */\n lastTs: z.string(),\n bestK: count.nullable(),\n});\nconst cohortSchema = paramsSchema.extend({\n role: z.string(),\n model: z.string(),\n sessions: count,\n ...sweepResultSchema.shape,\n /** The same sweep when only half the boot is overhead the next session pays again. */\n halfBoot: sweepResultSchema,\n});\nconst teleportSchema = z.object({\n ts: z.string(),\n name: z.string().nullable(),\n sessionId: z.string(),\n role: z.string(),\n model: z.string(),\n exitFill: count,\n bestK: count.nullable(),\n /** Exit fill minus each configured K; positive means the seat left late. */\n overConfigured: z.array(z.object({ k: count, over: z.number() })),\n});\n/** `requestsFrom` when the report has no reviewer session at all, so requests per PR is 0. */\nexport const POOLED_REVIEWERS = \"pooled\";\nconst reviewerCostSchema = z.object({\n role: z.string(),\n model: z.string(),\n sessions: count,\n /** Mean requests after boot of a per-PR reviewer: the work each PR adds. */\n requestsPerPr: z.number(),\n /** The reviewer model whose sessions give `requestsPerPr`: the row's own, else the newest reviewer cohort; `pooled` with none. */\n requestsFrom: z.string(),\n /** Sessions in the `requestsFrom` cohort; 1 means the per-PR figure rests on one session. */\n requestsFromSessions: count,\n costUsd: z.number(),\n});\nconst reviewerSchema = z.object({ prs: count, fresh: z.array(reviewerCostSchema), standing: z.array(reviewerCostSchema) });\n\nexport const handoffThresholdSchema = z.object({\n configuredK: z.array(count),\n sweep: z.object({ fromK: count, toK: count, stepK: count }),\n cohorts: z.array(cohortSchema),\n sessions: z.array(sessionSchema),\n /** Sessions with no dispatch, send or write, or none priced: they have no boot to measure. */\n unbootedSessions: count,\n teleports: z.array(teleportSchema),\n unmatchedTeleports: count,\n /** Boot and cache reads for `prs` reviews: a fresh reviewer per PR against one standing reviewer. */\n reviewers: reviewerSchema,\n});\n\nexport type HandoffThreshold = z.infer<typeof handoffThresholdSchema>;\nexport type HandoffCohort = z.infer<typeof cohortSchema>;\nexport type HandoffSession = z.infer<typeof sessionSchema>;\nexport type HandoffTeleport = z.infer<typeof teleportSchema>;\nexport type ReviewerComparison = z.infer<typeof reviewerSchema>;\nexport type CycleParams = z.infer<typeof paramsSchema>;\nexport type KSweep = HandoffThreshold[\"sweep\"];\n\n/** One main-thread request as the handoff model needs it. */\nexport interface HandoffRequestRow {\n sessionId: string;\n role: string;\n model: string;\n ts: string;\n /** Tokens in context: input, cache reads and cache writes. */\n fill: number;\n tokens: RequestTokens;\n bootAction: boolean;\n}\n\nexport interface TeleportEvent {\n ts: string;\n name: string | null;\n fromAgentId: string;\n}\n\nexport interface HandoffOptions {\n configuredK?: readonly number[];\n sweep?: KSweep;\n reviewerRole?: string;\n /** The role whose boot, fill and growth price a reviewer that stays up across PRs. */\n standingRole?: string;\n reviewerPrs?: number;\n /** Prices every request and the read rate; the package table, not the graph's stored one. */\n prices?: readonly PriceRow[];\n}\n\nexport function isBootAction(calls: readonly ActionCall[]): boolean {\n return calls.some((call) => BOOT_TOOL.test(call.tool) || (call.writePaths?.length ?? 0) > 0);\n}\n\n/** Broker log lines to teleport starts; any other line, or one that is not JSON, is skipped. */\nexport function parseTeleportEvents(lines: Iterable<string>): TeleportEvent[] {\n const events: TeleportEvent[] = [];\n for (const line of lines) {\n const entry = parseJson(line);\n if (entry?.event !== TELEPORT_EVENT || typeof entry.from !== \"string\" || typeof entry.ts !== \"string\") continue;\n events.push({ ts: entry.ts, name: typeof entry.name === \"string\" ? entry.name : null, fromAgentId: entry.from });\n }\n return events;\n}\n\nfunction parseJson(line: string): Record<string, unknown> | null {\n try {\n const value: unknown = JSON.parse(line);\n return typeof value === \"object\" && value !== null ? (value as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\n/** One cycle boots to f0 and grows g per request up to K: boot/n + read price x mean fill, with n = (K - f0) / g. */\nexport function costPerRequest(params: CycleParams, k: number): number | null {\n const requests = (k - params.bootFill) / params.growthPerRequest;\n if (!(params.growthPerRequest > 0) || requests < 1) return null;\n return params.bootCostUsd / requests + (params.readPricePerMTok / MTOK) * ((params.bootFill + k) / 2);\n}\n\n/** The cheapest K on the sweep grid, then each configured K against it. */\nexport function sweepK(params: CycleParams, sweep: KSweep, configuredK: readonly number[]): z.infer<typeof sweepResultSchema> {\n let best: { k: number; cost: number } | null = null;\n for (let k = sweep.fromK; k <= sweep.toK; k += sweep.stepK) {\n const cost = costPerRequest(params, k);\n if (cost !== null && (best === null || cost < best.cost)) best = { k, cost };\n }\n const atConfigured = configuredK.map((k) => {\n const cost = costPerRequest(params, k);\n return { k, costPerRequest: cost, deltaPerRequest: cost === null || best === null ? null : cost - best.cost };\n });\n return { bestK: best?.k ?? null, bestCostPerRequest: best?.cost ?? null, atConfigured };\n}\n\n/** Per role and model: boot cost and fill, fill growth and read price from the requests, then the K sweep. */\nexport function handoffThreshold(rows: readonly HandoffRequestRow[], teleports: readonly TeleportEvent[], agentSessions: ReadonlyMap<string, readonly string[]>, options: HandoffOptions = {}): HandoffThreshold {\n const configuredK = [...(options.configuredK ?? DEFAULT_CONFIGURED_K)];\n const sweep = { ...(options.sweep ?? DEFAULT_K_SWEEP) };\n const bySession = groupBy(rows, (row) => row.sessionId);\n const fits = [...bySession.values()].map((requests) => fitSession(requests, options.prices ?? PRICE_TABLE, sweep));\n const sessions = fits.filter((fit): fit is HandoffSession => fit !== null).sort((a, b) => a.sessionId.localeCompare(b.sessionId));\n const cohorts = cohortsOf(sessions, sweep, configuredK);\n const matched = teleports.map((event) => teleportExit(event, agentSessions, bySession, cohorts, configuredK)).filter((t): t is HandoffTeleport => t !== null);\n return {\n configuredK,\n sweep,\n cohorts,\n sessions,\n unbootedSessions: fits.length - sessions.length,\n teleports: matched.sort((a, b) => a.ts.localeCompare(b.ts)),\n unmatchedTeleports: teleports.length - matched.length,\n reviewers: reviewerComparison(sessions, options.reviewerRole ?? DEFAULT_REVIEWER_ROLE, options.standingRole ?? DEFAULT_STANDING_ROLE, options.reviewerPrs ?? DEFAULT_REVIEWER_PRS),\n };\n}\n\nfunction fitSession(unsorted: readonly HandoffRequestRow[], prices: readonly PriceRow[], sweep: KSweep): HandoffSession | null {\n const requests = [...unsorted].sort((a, b) => a.ts.localeCompare(b.ts));\n const first = requests[0]!;\n const bootIndex = requests.findIndex((row) => row.bootAction);\n const price = findPrice(first.model, first.ts, prices);\n if (bootIndex < 0 || price === null) return null;\n const params: CycleParams = {\n bootCostUsd: requests.slice(0, bootIndex + 1).reduce((sum, row) => sum + priceRequest(row.tokens, row.model, row.ts, prices).costUsd, 0),\n bootFill: requests[bootIndex]!.fill,\n growthPerRequest: meanGrowth(requests.slice(bootIndex).map((row) => row.fill)),\n readPricePerMTok: price.cacheRead,\n };\n const { sessionId, role, model } = first;\n const last = requests[requests.length - 1]!;\n return { sessionId, role, model, requests: requests.length, bootRequests: bootIndex + 1, exitFill: last.fill, lastTs: last.ts, ...params, bestK: sweepK(params, sweep, []).bestK };\n}\n\n/** Rises only, so a compaction's drop does not cancel the growth before it; zero with no request after boot. */\nfunction meanGrowth(fills: readonly number[]): number {\n if (fills.length < 2) return 0;\n let rise = 0;\n for (let i = 1; i < fills.length; i += 1) rise += Math.max(0, fills[i]! - fills[i - 1]!);\n return rise / (fills.length - 1);\n}\n\n/** Session means per role and model; a model's read price differs, so it splits the role. */\nfunction cohortsOf(sessions: readonly HandoffSession[], sweep: KSweep, configuredK: readonly number[]): HandoffCohort[] {\n return [...groupBy(sessions, (s) => JSON.stringify([s.role, s.model]))]\n .map(([, members]) => {\n const params = meanParams(members);\n return {\n role: members[0]!.role,\n model: members[0]!.model,\n sessions: members.length,\n ...params,\n ...sweepK(params, sweep, configuredK),\n halfBoot: sweepK({ ...params, bootCostUsd: params.bootCostUsd / 2 }, sweep, configuredK),\n };\n })\n .sort((a, b) => a.role.localeCompare(b.role) || a.model.localeCompare(b.model));\n}\n\nfunction meanParams(sessions: readonly HandoffSession[]): CycleParams {\n const mean = (pick: (s: HandoffSession) => number) => sessions.reduce((sum, s) => sum + pick(s), 0) / sessions.length;\n return {\n bootCostUsd: mean((s) => s.bootCostUsd),\n bootFill: mean((s) => s.bootFill),\n growthPerRequest: meanGrowthOf(sessions),\n readPricePerMTok: mean((s) => s.readPricePerMTok),\n };\n}\n\n/** Sessions with no request after boot have g = 0; counting them would dilute the growth of those that grew. */\nfunction meanGrowthOf(sessions: readonly HandoffSession[]): number {\n const grown = sessions.filter((s) => s.growthPerRequest > 0);\n return grown.length === 0 ? 0 : grown.reduce((sum, s) => sum + s.growthPerRequest, 0) / grown.length;\n}\n\n/** The fill of the outgoing session's last request at or before the teleport. */\nfunction teleportExit(\n event: TeleportEvent,\n agentSessions: ReadonlyMap<string, readonly string[]>,\n bySession: ReadonlyMap<string, readonly HandoffRequestRow[]>,\n cohorts: readonly HandoffCohort[],\n configuredK: readonly number[],\n): HandoffTeleport | null {\n const candidates = (agentSessions.get(event.fromAgentId) ?? []).flatMap((id) => bySession.get(id) ?? []);\n const exit = candidates.filter((row) => row.ts <= event.ts).sort((a, b) => b.ts.localeCompare(a.ts))[0];\n if (!exit) return null;\n const cohort = cohorts.find((c) => c.role === exit.role && c.model === exit.model);\n return {\n ts: event.ts,\n name: event.name,\n sessionId: exit.sessionId,\n role: exit.role,\n model: exit.model,\n exitFill: exit.fill,\n bestK: cohort?.bestK ?? null,\n overConfigured: configuredK.map((k) => ({ k, over: exit.fill - k })),\n };\n}\n\n/** Reads over m requests from f0 growing g each: m f0 + g m(m + 1) / 2 tokens at the read price. */\nfunction readCost(params: CycleParams, requests: number): number {\n return ((requests * params.bootFill + (params.growthPerRequest * requests * (requests + 1)) / 2) * params.readPricePerMTok) / MTOK;\n}\n\n/** Fresh: every PR pays a boot and its own reads. Standing: one boot, then every PR's requests read the context the earlier ones left. */\nfunction reviewerComparison(sessions: readonly HandoffSession[], reviewerRole: string, standingRole: string, prs: number): ReviewerComparison {\n const cohorts = (role: string) => [...groupBy(sessions.filter((s) => s.role === role), (s) => s.model)].sort(([a], [b]) => a.localeCompare(b));\n const reviewers = cohorts(reviewerRole);\n const perPr = new Map(reviewers.map(([model, members]) => [model, meanRequestsAfterBoot(members)]));\n const newest = newestCohort(reviewers);\n const priced = (role: string, costOf: (params: CycleParams, requests: number) => number) =>\n cohorts(role).map(([model, members]) => {\n const from = perPr.has(model) ? model : newest;\n const requestsPerPr = from === null ? 0 : perPr.get(from)!;\n const requestsFromSessions = from === null ? 0 : (reviewers.find(([name]) => name === from)?.[1].length ?? 0);\n return { role, model, sessions: members.length, requestsPerPr, requestsFrom: from ?? POOLED_REVIEWERS, requestsFromSessions, costUsd: costOf(meanParams(members), requestsPerPr) };\n });\n return {\n prs,\n fresh: priced(reviewerRole, (params, requests) => prs * (params.bootCostUsd + readCost(params, requests))),\n standing: priced(standingRole, (params, requests) => params.bootCostUsd + readCost(params, prs * requests)),\n };\n}\n\n/** The reviewer model whose latest session is newest by instant, not by string; a tie goes to the later model name. */\nfunction newestCohort(reviewers: readonly (readonly [string, readonly HandoffSession[]])[]): string | null {\n const epoch = (ts: string) => (Number.isNaN(Date.parse(ts)) ? Number.NEGATIVE_INFINITY : Date.parse(ts));\n const latest = reviewers.map(([model, members]) => ({ model, at: Math.max(...members.map((s) => epoch(s.lastTs))) }));\n latest.sort((a, b) => (a.at === b.at ? b.model.localeCompare(a.model) : b.at - a.at));\n return latest[0]?.model ?? null;\n}\n\nfunction meanRequestsAfterBoot(sessions: readonly HandoffSession[]): number {\n return sessions.length === 0 ? 0 : sessions.reduce((sum, s) => sum + s.requests - s.bootRequests, 0) / sessions.length;\n}\n\nfunction groupBy<T>(rows: readonly T[], keyOf: (row: T) => string): Map<string, T[]> {\n const groups = new Map<string, T[]>();\n for (const row of rows) {\n const key = keyOf(row);\n const members = groups.get(key);\n if (members) members.push(row);\n else groups.set(key, [row]);\n }\n return groups;\n}\n","/** Initiatives a session's task edges name, with how many edges name each. */\nexport interface TaskInitiative {\n initiative: string;\n edges: number;\n}\n\n/**\n * A task edge names the initiative outright, so it wins over the cwd guess. Among several,\n * the most-named initiative wins and a tie goes to the alphabetically first, for a stable report.\n */\nexport function sessionInitiative(tasks: readonly TaskInitiative[], cwd: string | null | undefined): string {\n const best = [...tasks].sort((a, b) => b.edges - a.edges || a.initiative.localeCompare(b.initiative))[0];\n return best ? best.initiative : initiativeFromCwd(cwd);\n}\n\n/** The cwd rule from `cf_analyze.py` `initiative()`. A worktree under a repo counts as that repo. */\nexport function initiativeFromCwd(cwd: string | null | undefined): string {\n if (!cwd) return \"unknown\";\n const repo = /\\/projects\\/([^/]+)/.exec(cwd);\n if (repo) return `repo:${repo[1]}`;\n const activeWork = /active-work\\/([^/]+)/.exec(cwd);\n if (activeWork) return `active-work:${activeWork[1]}`;\n if (/ac-fork-\\w+/.test(cwd)) return \"ac-fork(tmp)\";\n const trimmed = cwd.replace(/\\/+$/, \"\");\n return `other:${trimmed.slice(trimmed.lastIndexOf(\"/\") + 1)}`;\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport type { ReportWindow } from \"./cost-report-queries.js\";\nimport type { ActionCall } from \"./turn-action.js\";\n\n/** The signals session-read extracts per tool use that the action classifier reads. */\nconst CALL_SIGNALS = { command_heads: \"heads\", file_read: \"readPaths\", file_write: \"writePaths\" } as const;\ntype CallSignal = keyof typeof CALL_SIGNALS;\n\n/**\n * A tool_use line follows the first line of the request that issued it, so the owner is the latest\n * request at or before it; context_contribution maps the other way, to the request it feeds.\n * Joining owners to request_dedup drops every fan-out copy along with its tool calls.\n */\nconst OWNED_CALLS = `\n WITH scope AS (\n SELECT DISTINCT transcript_id FROM request_dedup\n WHERE (@since IS NULL OR ts >= @since) AND (@until IS NULL OR ts < @until)\n ), stream AS (\n SELECT transcript_id, byte_offset, -1 AS lane, 0 AS block_index, request_id, NULL AS tool_use_id, NULL AS name\n FROM request WHERE transcript_id IN (SELECT transcript_id FROM scope)\n UNION ALL\n SELECT transcript_id, byte_offset, 0, block_index, NULL, tool_use_id, name\n FROM tool_call WHERE transcript_id IN (SELECT transcript_id FROM scope)\n ), ordered AS (\n SELECT *, COUNT(request_id) OVER (PARTITION BY transcript_id ORDER BY byte_offset, lane, block_index ROWS UNBOUNDED PRECEDING) AS requests_seen\n FROM stream\n ), owned AS (\n SELECT c.transcript_id, c.byte_offset, c.block_index, c.tool_use_id, c.name, r.request_id\n FROM ordered c JOIN ordered r ON r.transcript_id = c.transcript_id AND r.lane = -1 AND r.requests_seen = c.requests_seen\n WHERE c.lane = 0\n )\n SELECT o.request_id AS requestId, o.transcript_id || ':' || o.byte_offset || ':' || o.block_index AS callKey, o.name AS tool, s.signal, s.detail\n FROM owned o\n JOIN request_dedup d ON d.transcript_id = o.transcript_id AND d.request_id = o.request_id\n LEFT JOIN session_signal s ON s.transcript_id = o.transcript_id AND s.tool_use_id = o.tool_use_id\n AND s.signal IN ('command_heads', 'file_read', 'file_write')\n WHERE (@since IS NULL OR d.ts >= @since) AND (@until IS NULL OR d.ts < @until)\n ORDER BY o.transcript_id, o.byte_offset, o.block_index\n`;\n\ninterface OwnedRow {\n requestId: string;\n callKey: string;\n tool: string;\n signal: CallSignal | null;\n detail: string | null;\n}\n\n/** The tool calls each request in the window issued, keyed by `request_id`; a request with none is absent. */\nexport function readRequestToolCalls(db: Db, window: ReportWindow): Map<string, ActionCall[]> {\n const byRequest = new Map<string, Map<string, ActionCall>>();\n for (const row of db.prepare(OWNED_CALLS).all(window) as OwnedRow[]) {\n const calls = byRequest.get(row.requestId) ?? new Map<string, ActionCall>();\n byRequest.set(row.requestId, calls);\n const call = calls.get(row.callKey) ?? { tool: row.tool };\n calls.set(row.callKey, row.signal ? withSignal(call, row.signal, row.detail ?? \"\") : call);\n }\n return new Map([...byRequest].map(([requestId, calls]) => [requestId, [...calls.values()]]));\n}\n\n/** `command_heads` is one `;`-joined string per Bash call; file signals carry one path each. */\nfunction withSignal(call: ActionCall, signal: CallSignal, detail: string): ActionCall {\n const field = CALL_SIGNALS[signal];\n const values = signal === \"command_heads\" ? detail.split(\";\").filter(Boolean) : [detail];\n return { ...call, [field]: [...(call[field] ?? []), ...values] };\n}\n","import type { SessionClassification } from \"./classify-session.js\";\n\n/** worker-v1's role vocabulary, from worker-forensics-report.md section 2. */\nexport type WorkerRole = \"implementer\" | \"reviewer\" | \"researcher\" | \"planner\" | \"coordinator\" | \"standing_peer\" | \"unknown\";\n\n/** Spawn profile to role, as the worker report's table (wf_analyze.py:79-91) maps it. */\nexport const PROFILE_ROLES: Readonly<Record<string, WorkerRole>> = {\n implementer: \"implementer\",\n \"implementer-lite\": \"implementer\",\n \"relay-implementer\": \"implementer\",\n \"beat-builder\": \"implementer\",\n \"fable-optimizer\": \"implementer\",\n \"bd-implementer\": \"implementer\",\n \"bd-implementer-lite\": \"implementer\",\n reviewer: \"reviewer\",\n \"relay-reviewer\": \"reviewer\",\n \"bd-reviewer\": \"reviewer\",\n researcher: \"researcher\",\n explorer: \"researcher\",\n \"fable-architect\": \"planner\",\n planner: \"planner\",\n \"bd-planner\": \"planner\",\n decider: \"planner\",\n \"fable-coordinator\": \"coordinator\",\n \"opus-coordinator\": \"coordinator\",\n peer: \"standing_peer\",\n};\n\nexport const STANDING_PEER_MIN_HOURS = 12;\nexport const STANDING_PEER_MIN_ASSIGNMENTS = 2;\nconst HOUR_MS = 3_600_000;\n\nexport interface WorkerFacts {\n profile?: string | null;\n /** First request to last request, over the whole session rather than a report window. */\n lifetimeMs: number;\n /** worker-v1 episodes opened by an assignment (the brief or a channel follow-up), not by an idle gap. */\n assignments: number;\n}\n\nexport function roleFromProfile(profile: string | null | undefined): WorkerRole {\n return PROFILE_ROLES[(profile ?? \"\").toLowerCase()] ?? \"unknown\";\n}\n\n/** A worker that outlives its first assignment is a standing peer whatever it was spawned as (wf_analyze.py:94-103). */\nexport function workerRole(facts: WorkerFacts): WorkerRole {\n const outlived = facts.lifetimeMs >= STANDING_PEER_MIN_HOURS * HOUR_MS && facts.assignments >= STANDING_PEER_MIN_ASSIGNMENTS;\n return outlived ? \"standing_peer\" : roleFromProfile(facts.profile);\n}\n\n/** The report's role key: `coordinator` or `adhoc` for humans, `worker:<role>` for spawned agents, else the class. */\nexport function sessionRole(classification: SessionClassification, worker: WorkerFacts): string {\n if (classification.humanRole) return classification.humanRole;\n if (classification.sessionClass === \"agent_spawned\") return `worker:${workerRole(worker)}`;\n return classification.sessionClass;\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { readAgentNames } from \"./cost-report-queries.js\";\n\n/**\n * Narrows a report to some sessions. Every field left out matches all, and fields combine with AND.\n * Compactions and coverage stay window-wide: the graph does not key them to a request.\n */\nexport interface ReportScope {\n sessionIds?: readonly string[];\n /** Keeps sessions whose agent-chat agent name starts with it. */\n agentPrefix?: string;\n /** Report roles, as `byRole` names them. */\n roles?: readonly string[];\n}\n\n/** A predicate over a request's session and role; with no scope every request passes. */\nexport function scopeFilter(db: Db, scope: ReportScope = {}): (row: { sessionId: string; role: string }) => boolean {\n const ids = scope.sessionIds ? new Set(scope.sessionIds) : null;\n const named = scope.agentPrefix === undefined ? null : agentSessions(db, scope.agentPrefix);\n const roles = scope.roles ? new Set(scope.roles) : null;\n return (row) => (!ids || ids.has(row.sessionId)) && (!named || named.has(row.sessionId)) && (!roles || roles.has(row.role));\n}\n\nfunction agentSessions(db: Db, prefix: string): Set<string> {\n return new Set(readAgentNames(db).filter((row) => row.agentName.startsWith(prefix)).map((row) => row.sessionId));\n}\n","export const ACTION_CLASSES = [\n \"journal-write\",\n \"pr-ci-check\",\n \"merge\",\n \"dispatch\",\n \"retire\",\n \"task-state\",\n \"budget-status\",\n \"scorer\",\n \"message\",\n \"read-investigate\",\n \"text-only\",\n \"other\",\n] as const;\n\nexport type ActionClass = (typeof ACTION_CLASSES)[number];\n\n/** One tool call of a request, with the signals session-read extracted for it. */\nexport interface ActionCall {\n tool: string;\n /** Command heads of a Bash call, such as `gh pr checks`. */\n heads?: readonly string[];\n readPaths?: readonly string[];\n writePaths?: readonly string[];\n}\n\n/** A rule matches a call when every field it sets matches; list order is the precedence. */\nexport interface ActionRule {\n cls: ActionClass;\n tool?: RegExp;\n head?: RegExp;\n readPath?: RegExp;\n writePath?: RegExp;\n}\n\n/** A basename naming a log, journal or event file, so `catalog.md`, `CHANGELOG.md` and `fixture.jsonl` stay out. */\nconst JOURNAL_BASENAME = String.raw`(?:(?:[^/]*[-_.])?(?:log|journal|events?)(?:[-_.][^/]*)?\\.(?:md|jsonl)|[^/]*journal[^/]*)$`;\nconst INTERPRETER = String.raw`(?:(?:python3?|node|tsx|bash|sh) )?`;\n\nexport const DEFAULT_ACTION_RULES: readonly ActionRule[] = [\n { cls: \"journal-write\", writePath: new RegExp(String.raw`(?:^|/)${JOURNAL_BASENAME}`, \"i\") },\n { cls: \"journal-write\", head: new RegExp(`^>(?:[^/]*/)?${JOURNAL_BASENAME}`, \"i\") },\n { cls: \"pr-ci-check\", head: /^gh pr (checks|view)\\b/ },\n { cls: \"pr-ci-check\", head: /^gh run\\b/ },\n { cls: \"pr-ci-check\", head: /^git merge-tree\\b/ },\n { cls: \"pr-ci-check\", head: /^gh api GET commits\\/check-runs$/ },\n { cls: \"pr-ci-check\", head: /^gh api GET commits\\/status$/ },\n { cls: \"merge\", head: /^gh pr merge\\b/ },\n { cls: \"merge\", head: /^gh api PUT pulls\\/merge$/ },\n { cls: \"dispatch\", tool: /agent_(spawn|resume)$/ },\n { cls: \"retire\", head: /^(agent-chat )?agent retire\\b/ },\n { cls: \"task-state\", head: /^active-work task\\b/ },\n { cls: \"budget-status\", tool: /(session_budget|chat_status)$/ },\n { cls: \"budget-status\", head: /^(agent-chat )?agent list\\b/ },\n { cls: \"budget-status\", head: /^(agent-chat )?agent (ls|budget|worktrees)\\b/ },\n { cls: \"budget-status\", head: /^git worktree list\\b/ },\n { cls: \"budget-status\", tool: /(agent_list|chat_list|ListAgents)$/ },\n { cls: \"scorer\", tool: /(^|__)scor/i },\n { cls: \"scorer\", head: new RegExp(`^${INTERPRETER}[\\\\w.-]*scor`, \"i\") },\n { cls: \"message\", tool: /chat_send$/ },\n { cls: \"message\", tool: /(chat_ask|chat_inbox|chat_claim|chat_release)$/ },\n { cls: \"read-investigate\", tool: /^(Read|Grep|Glob)$/ },\n { cls: \"read-investigate\", head: /^(cat|ls|grep|rg|head|tail|find|wc|git (log|diff|show|status))\\b/ },\n];\n\n/** Dispatch is judgment about what to hand out, so it stays out of the mechanical list. */\nexport const DEFAULT_MECHANICAL_CLASSES: readonly ActionClass[] = [\n \"journal-write\",\n \"pr-ci-check\",\n \"task-state\",\n \"budget-status\",\n \"retire\",\n \"merge\",\n \"scorer\",\n];\n\nfunction callMatches(call: ActionCall, rule: ActionRule): boolean {\n if (rule.tool && !rule.tool.test(call.tool)) return false;\n if (rule.head && !(call.heads ?? []).some((h) => rule.head?.test(h))) return false;\n if (rule.readPath && !(call.readPaths ?? []).some((p) => rule.readPath?.test(p))) return false;\n if (rule.writePath && !(call.writePaths ?? []).some((p) => rule.writePath?.test(p))) return false;\n return true;\n}\n\nexport function classifyRequest(\n calls: readonly ActionCall[],\n rules: readonly ActionRule[] = DEFAULT_ACTION_RULES,\n): ActionClass {\n if (calls.length === 0) return \"text-only\";\n const hit = rules.find((rule) => calls.some((call) => callMatches(call, rule)));\n return hit?.cls ?? \"other\";\n}\n","import { z } from \"zod\";\nimport type { AgentNameRow, WakeEventRow } from \"./cost-report-queries.js\";\nimport { roleFromProfile } from \"./roles.js\";\nimport { ACTION_CLASSES, type ActionClass } from \"./turn-action.js\";\n\nexport const WAKE_FROM_KINDS = [\"seat\", \"agent\", \"broadcast\", \"broker\", \"none\"] as const;\nexport type WakeFromKind = (typeof WAKE_FROM_KINDS)[number];\n\n/** Report roles whose wakes are cut into episodes: a human coordinator and a spawned coordinator seat. */\nexport const DEFAULT_EPISODE_ROLES: readonly string[] = [\"coordinator\", \"worker:coordinator\"];\n\n/** A wake whose requests only read, answer in text, or call tools no rule names changed nothing outside the session. */\nexport const DEFAULT_NO_ACTION_CLASSES: readonly ActionClass[] = [\"read-investigate\", \"text-only\", \"other\"];\n\n/** agent-chat's own name on the notices it writes, such as the agent lifecycle notice. */\nexport const BROKER_SENDER = \"agent-chat\";\nexport const AGENT_LIFECYCLE = \"agent_lifecycle\";\nconst UNNAMED = \"unnamed\";\n\nconst count = z.number().int().nonnegative();\nconst costFields = { episodes: count, requests: count, costUsd: z.number(), noActionEpisodes: count, noActionCostUsd: z.number() };\nconst fromSchema = z.object({ key: z.enum(WAKE_FROM_KINDS), ...costFields });\nconst causeSchema = z.object({\n key: z.string(),\n ...costFields,\n midLoopEpisodes: count,\n requestsPerEpisode: z.number(),\n costPerEpisode: z.number(),\n byFrom: z.array(fromSchema),\n});\nconst pairSchema = z.object({ from: z.string(), fromKind: z.enum(WAKE_FROM_KINDS), to: z.string(), ...costFields });\n\nexport const wakeEpisodesSchema = z.object({\n roles: z.array(z.string()),\n noActionClasses: z.array(z.enum(ACTION_CLASSES)),\n ...costFields,\n /** Requests in the window that follow no event in it: the work an earlier arrival started. */\n unattributed: z.object({ requests: count, costUsd: z.number() }),\n byCause: z.array(causeSchema),\n /** Sender by receiver; a seat is named, every other sender is its kind. */\n pairs: z.array(pairSchema),\n});\n\nexport type WakeEpisodes = z.infer<typeof wakeEpisodesSchema>;\nexport type WakeCauseEpisodes = z.infer<typeof causeSchema>;\nexport type WakePair = z.infer<typeof pairSchema>;\n\n/** One request as the episode view needs it. */\nexport interface EpisodeRequestRow {\n costUsd: number;\n action: ActionClass;\n eventKey: string | null;\n}\n\nexport interface WakeEpisode {\n key: string;\n cause: string;\n midLoop: boolean;\n fromKind: WakeFromKind;\n from: string;\n to: string;\n requests: number;\n costUsd: number;\n noAction: boolean;\n}\n\nexport interface EpisodeNames {\n seats: ReadonlySet<string>;\n /** Each receiving session's agent-chat name. */\n receivers: ReadonlyMap<string, string>;\n}\n\n/** A seat is a name some top-level session carries, or one a coordinator profile was spawned under. */\nexport function episodeNames(rows: readonly AgentNameRow[]): EpisodeNames {\n const isSeat = (row: AgentNameRow) => row.originKind !== \"spawned\" || roleFromProfile(row.profile) === \"coordinator\";\n return {\n seats: new Set(rows.filter(isSeat).map((row) => row.agentName)),\n receivers: new Map(rows.map((row) => [row.sessionId, row.agentName])),\n };\n}\n\n/** The lifecycle notice is session-read's `channel_system`; every other cause keeps its name. */\nexport function episodeCause(cause: string): string {\n return cause === \"channel_system\" ? AGENT_LIFECYCLE : cause;\n}\n\nexport function fromKindOf(event: WakeEventRow, seats: ReadonlySet<string>): WakeFromKind {\n if (!event.cause.startsWith(\"channel_\") || event.fromName === null) return \"none\";\n if (event.fromName === BROKER_SENDER) return \"broker\";\n if (event.broadcast) return \"broadcast\";\n return seats.has(event.fromName) ? \"seat\" : \"agent\";\n}\n\n/** Each event with the requests that followed it, flagged no-action when every request's class is listed. */\nexport function buildWakeEpisodes(\n events: readonly WakeEventRow[],\n requests: readonly EpisodeRequestRow[],\n names: EpisodeNames,\n noActionClasses: readonly ActionClass[],\n): WakeEpisode[] {\n const byEvent = groupBy(requests, (request) => request.eventKey ?? \"\");\n return events.map((event) => {\n const members = byEvent.get(event.key) ?? [];\n const fromKind = fromKindOf(event, names.seats);\n return {\n key: event.key,\n cause: episodeCause(event.cause),\n midLoop: event.delivery === \"mid_loop\",\n fromKind,\n from: pairSender(fromKind, event.fromName, names.seats),\n to: names.receivers.get(event.sessionId) ?? UNNAMED,\n requests: members.length,\n costUsd: members.reduce((sum, row) => sum + row.costUsd, 0),\n noAction: members.every((row) => noActionClasses.includes(row.action)),\n };\n });\n}\n\n/** Spawned agents have one-off names, so they collapse to `agent`; a seat broadcasting keeps its name. */\nfunction pairSender(kind: WakeFromKind, name: string | null, seats: ReadonlySet<string>): string {\n if (kind === \"seat\" || (kind === \"broadcast\" && name !== null && seats.has(name))) return name!;\n return kind === \"broadcast\" ? \"agent\" : kind;\n}\n\nexport function summarizeWakeEpisodes(\n episodes: readonly WakeEpisode[],\n requests: readonly EpisodeRequestRow[],\n roles: readonly string[],\n noActionClasses: readonly ActionClass[],\n): WakeEpisodes {\n const keys = new Set(episodes.map((episode) => episode.key));\n const unattributed = requests.filter((row) => row.eventKey === null || !keys.has(row.eventKey));\n return {\n roles: [...roles],\n noActionClasses: [...noActionClasses],\n ...costOf(episodes),\n unattributed: { requests: unattributed.length, costUsd: unattributed.reduce((sum, row) => sum + row.costUsd, 0) },\n byCause: causeBuckets(episodes),\n pairs: pairBuckets(episodes),\n };\n}\n\nfunction costOf(episodes: readonly WakeEpisode[]) {\n const noAction = episodes.filter((episode) => episode.noAction);\n const sum = (list: readonly WakeEpisode[], pick: (episode: WakeEpisode) => number) => list.reduce((total, episode) => total + pick(episode), 0);\n return {\n episodes: episodes.length,\n requests: sum(episodes, (episode) => episode.requests),\n costUsd: sum(episodes, (episode) => episode.costUsd),\n noActionEpisodes: noAction.length,\n noActionCostUsd: sum(noAction, (episode) => episode.costUsd),\n };\n}\n\n/** Most expensive first; ties by key so the report is stable. */\nfunction causeBuckets(episodes: readonly WakeEpisode[]): WakeCauseEpisodes[] {\n return [...groupBy(episodes, (episode) => episode.cause)]\n .map(([key, members]) => {\n const cost = costOf(members);\n return {\n key,\n ...cost,\n midLoopEpisodes: members.filter((episode) => episode.midLoop).length,\n requestsPerEpisode: cost.requests / cost.episodes,\n costPerEpisode: cost.costUsd / cost.episodes,\n byFrom: [...groupBy(members, (episode) => episode.fromKind)].map(([kind, part]) => ({ key: kind as WakeFromKind, ...costOf(part) })).sort(byCostThenKey),\n };\n })\n .sort(byCostThenKey);\n}\n\nfunction pairBuckets(episodes: readonly WakeEpisode[]): WakePair[] {\n const sent = episodes.filter((episode) => episode.fromKind !== \"none\");\n return [...groupBy(sent, (episode) => JSON.stringify([episode.from, episode.fromKind, episode.to]))]\n .map(([key, members]) => {\n const [from, fromKind, to] = JSON.parse(key) as [string, WakeFromKind, string];\n return { from, fromKind, to, ...costOf(members) };\n })\n .sort((a, b) => b.costUsd - a.costUsd || a.from.localeCompare(b.from) || a.to.localeCompare(b.to) || a.fromKind.localeCompare(b.fromKind));\n}\n\nfunction groupBy<T>(rows: readonly T[], keyOf: (row: T) => string): Map<string, T[]> {\n const groups = new Map<string, T[]>();\n for (const row of rows) {\n const key = keyOf(row);\n const members = groups.get(key);\n if (members) members.push(row);\n else groups.set(key, [row]);\n }\n return groups;\n}\n\nfunction byCostThenKey(a: { key: string; costUsd: number }, b: { key: string; costUsd: number }): number {\n return b.costUsd - a.costUsd || a.key.localeCompare(b.key);\n}\n","import type { CostBucket, CostReport, MechanicalShare, RoleActions, WakeGapCell } from \"./cost-report.js\";\nimport type { HandoffThreshold } from \"./handoff-threshold.js\";\nimport { PRICE_TABLE_VERSION } from \"./prices.js\";\nimport type { WakeEpisodes } from \"./wake-episodes.js\";\n\nexport const LIST_PRICE_CAVEAT =\n \"List prices, not a bill: the accounts behind these sessions may run on subscription plans. Rankings hold; the absolute figure is not what you paid.\";\n\ntype Cell = string | number;\n\n/** Wake causes and sender pairs the text shows; the JSON carries all of them. */\nexport const TOP_WAKE_ROWS = 10;\n\n/** The same report as plain-text tables, one section per report field, caveat and footer last. */\nexport function renderCostReportText(report: CostReport): string {\n const sections = [\n header(report),\n table(\"By token class\", [\"class\", \"tokens\", \"cost\"], report.byTokenClass.map((row) => [row.tokenClass, row.tokens, usd(row.costUsd)])),\n bucketTable(\"By account\", report.byAccount, report.totals.costUsd),\n bucketTable(\"By model\", report.byModel, report.totals.costUsd),\n bucketTable(\"By class\", report.byClass, report.totals.costUsd),\n bucketTable(\"By role\", report.byRole, report.totals.costUsd),\n actionTable(report.byAction),\n mechanicalTable(report.mechanicalShare),\n bucketTable(\"By episode count\", report.byEpisodeCount, report.totals.costUsd),\n bucketTable(\"By initiative\", report.byInitiative, report.totals.costUsd),\n bucketTable(\"By context band\", report.byContextBand, report.totals.costUsd),\n wakeCauseTable(report),\n episodeTable(report.wakeEpisodes),\n pairTable(report.wakeEpisodes),\n handoffTable(report.handoffThreshold),\n teleportTable(report.handoffThreshold),\n reviewerTable(report.handoffThreshold),\n cellTable(\"Wake cause by gap band\", report.wakeCauseByGapBand),\n cellTable(`Cold rebuilds: ${report.coldRebuild.requests} requests, ${usd(report.coldRebuild.costUsd)}`, report.coldRebuild.byGapBandAndCause),\n compactionTable(report.compactions),\n topSessionTable(report.topSessions),\n unpricedTable(report.unpricedModels),\n [LIST_PRICE_CAVEAT, footer(report)].join(\"\\n\"),\n ];\n return sections.join(\"\\n\\n\") + \"\\n\";\n}\n\n/** The report's sections a caller may render alone, keyed by the field each one shows. */\nexport const COST_REPORT_SECTIONS = {\n byRole: (report: CostReport) => bucketTable(\"By role\", report.byRole, report.totals.costUsd),\n byAction: (report: CostReport) => actionTable(report.byAction),\n mechanicalShare: (report: CostReport) => mechanicalTable(report.mechanicalShare),\n byWakeCause: (report: CostReport) => wakeCauseTable(report),\n wakeEpisodes: (report: CostReport) => episodeTable(report.wakeEpisodes),\n wakePairs: (report: CostReport) => pairTable(report.wakeEpisodes),\n handoff: (report: CostReport) => handoffTable(report.handoffThreshold),\n teleports: (report: CostReport) => teleportTable(report.handoffThreshold),\n reviewers: (report: CostReport) => reviewerTable(report.handoffThreshold),\n} as const;\n\nexport type CostReportSection = keyof typeof COST_REPORT_SECTIONS;\n\n/** Some sections of the report under its header, with the caveat and footer last as in the full text. */\nexport function renderCostReportSections(report: CostReport, sections: readonly CostReportSection[]): string {\n const body = sections.map((section) => COST_REPORT_SECTIONS[section](report));\n return [header(report), ...body, [LIST_PRICE_CAVEAT, footer(report)].join(\"\\n\")].join(\"\\n\\n\") + \"\\n\";\n}\n\nfunction header(report: CostReport): string {\n const { since, until } = report.window;\n const { requests, sessions, costUsd } = report.totals;\n return `Cost report, ${since ?? \"beginning\"} to ${until ?? \"now\"}\\nTotal ${usd(costUsd)} over ${requests} requests in ${sessions} sessions`;\n}\n\nfunction bucketTable(title: string, buckets: readonly CostBucket[], total: number): string {\n const rows = buckets.map((b) => [b.key, b.requests, b.sessions, usd(b.costUsd), share(b.costUsd, total)]);\n return table(title, [\"key\", \"requests\", \"sessions\", \"cost\", \"share\"], rows);\n}\n\n/** Each role's row carries its total; its action classes sit indented beneath, sharing that total. */\nfunction actionTable(roles: readonly RoleActions[]): string {\n const rows = roles.flatMap(({ role, buckets }) => {\n const total = buckets.reduce((sum, b) => sum + b.costUsd, 0);\n const requests = buckets.reduce((sum, b) => sum + b.requests, 0);\n return [[role, requests, usd(total), share(total, total)], ...buckets.map((b) => [` ${b.key}`, b.requests, usd(b.costUsd), share(b.costUsd, total)])];\n });\n return table(\"By action per role\", [\"role / action\", \"requests\", \"cost\", \"share\"], rows);\n}\n\nfunction mechanicalTable(m: MechanicalShare): string {\n const title = `Mechanical share: ${percent(m.share)} (${usd(m.costUsd)}) of total; classes ${m.classes.join(\", \") || \"none\"}`;\n return table(title, [\"role\", \"mechanical cost\", \"share of role\"], m.byRole.map((r) => [r.role, usd(r.costUsd), percent(r.share)]));\n}\n\n/** Q4: answers sit under `human`, with typed text and answers indented one level down. */\nfunction wakeCauseTable(report: CostReport): string {\n const rows = report.byWakeCause.flatMap((group) => [\n [group.key, group.requests, usd(group.costUsd), group.midLoopRequests, usd(group.midLoopCostUsd)],\n ...group.parts.map((part) => [` ${part.key}`, part.requests, usd(part.costUsd), part.midLoopRequests, usd(part.midLoopCostUsd)]),\n ]);\n return table(\"By wake cause\", [\"cause\", \"requests\", \"cost\", \"mid-loop\", \"mid-loop cost\"], rows);\n}\n\n/** Q4: the costliest causes per episode first, each with its senders indented beneath. */\nfunction episodeTable(w: WakeEpisodes): string {\n const title = `Wake episodes of ${w.roles.join(\", \")}: ${w.episodes} episodes, ${w.requests} requests, ${usd(w.costUsd)}; no-action means only ${w.noActionClasses.join(\", \")}`;\n const causes = [...w.byCause].sort((a, b) => b.costPerEpisode - a.costPerEpisode || a.key.localeCompare(b.key)).slice(0, TOP_WAKE_ROWS);\n const rows = causes.flatMap((c) => [\n [c.key, c.episodes, c.midLoopEpisodes, c.requests, c.requestsPerEpisode.toFixed(1), usd(c.costUsd), usd(c.costPerEpisode), noActionCell(c)],\n ...c.byFrom.map((f) => [` from ${f.key}`, f.episodes, \"\", f.requests, (f.requests / f.episodes).toFixed(1), usd(f.costUsd), usd(f.costUsd / f.episodes), noActionCell(f)]),\n ]);\n return table(title, [\"cause\", \"episodes\", \"mid-loop\", \"requests\", \"req/ep\", \"cost\", \"cost/ep\", \"no-action\"], rows);\n}\n\nfunction noActionCell(bucket: { episodes: number; noActionEpisodes: number }): string {\n return `${bucket.noActionEpisodes} (${share(bucket.noActionEpisodes, bucket.episodes)})`;\n}\n\nfunction pairTable(w: WakeEpisodes): string {\n const rows = w.pairs.slice(0, TOP_WAKE_ROWS).map((p) => [p.from, p.fromKind, p.to, p.episodes, p.requests, usd(p.costUsd), noActionCell(p)]);\n return table(\"Wake senders by receiver\", [\"from\", \"kind\", \"to\", \"episodes\", \"requests\", \"cost\", \"no-action\"], rows);\n}\n\n/** Q2: per role and model, the fitted boot, fill and growth, the best K, and each configured K's extra cost per request. */\nfunction handoffTable(h: HandoffThreshold): string {\n const title = `Handoff threshold per role, priced at package table v${PRICE_TABLE_VERSION}: best K over ${kilo(h.sweep.fromK)}-${kilo(h.sweep.toK)}, half-boot K in brackets`;\n const head = [\"role\", \"model\", \"sessions\", \"boot\", \"boot fill\", \"growth/req\", \"read $/MTok\", \"best K\", \"$/req\", ...h.configuredK.map((k) => `+$/req @${kilo(k)}`)];\n const rows = h.cohorts.map((c) => [\n c.role,\n c.model,\n c.sessions,\n usd(c.bootCostUsd),\n kilo(c.bootFill),\n Math.round(c.growthPerRequest),\n c.readPricePerMTok.toFixed(3),\n `${kiloOrDash(c.bestK)} (${kiloOrDash(c.halfBoot.bestK)})`,\n c.bestCostPerRequest === null ? \"-\" : `$${c.bestCostPerRequest.toFixed(4)}`,\n ...c.atConfigured.map((at) => (at.deltaPerRequest === null ? \"-\" : `$${at.deltaPerRequest.toFixed(4)}`)),\n ]);\n return table(title, head, rows);\n}\n\nfunction teleportTable(h: HandoffThreshold): string {\n const title = `Teleport exit fill: ${h.teleports.length} matched, ${h.unmatchedTeleports} unmatched; the latest ${TOP_WAKE_ROWS}`;\n const head = [\"ts\", \"name\", \"role\", \"exit fill\", \"best K\", ...h.configuredK.map((k) => `over ${kilo(k)}`)];\n const rows = h.teleports.slice(-TOP_WAKE_ROWS).map((t) => [t.ts, t.name ?? \"-\", t.role, kilo(t.exitFill), kiloOrDash(t.bestK), ...t.overConfigured.map((o) => kilo(o.over))]);\n return table(title, head, rows);\n}\n\nfunction reviewerTable(h: HandoffThreshold): string {\n const row = (kind: string) => (c: HandoffThreshold[\"reviewers\"][\"fresh\"][number]) => [kind, c.role, c.model, c.sessions, c.requestsPerPr.toFixed(1), c.requestsFrom, usd(c.costUsd)];\n const rows = [...h.reviewers.fresh.map(row(\"fresh per PR\")), ...h.reviewers.standing.map(row(\"standing\"))];\n return table(`Reviewers over ${h.reviewers.prs} PRs, boot and reads: fresh per PR against one standing`, [\"reviewer\", \"role\", \"model\", \"sessions\", \"req/PR\", \"req/PR from\", \"cost\"], rows);\n}\n\nfunction kilo(tokens: number): string {\n return `${Math.round(tokens / 1_000)}k`;\n}\n\nfunction kiloOrDash(tokens: number | null): string {\n return tokens === null ? \"-\" : kilo(tokens);\n}\n\nfunction cellTable(title: string, cells: readonly WakeGapCell[]): string {\n return table(title, [\"cause\", \"gap\", \"requests\", \"cost\"], cells.map((c) => [c.wakeCause, c.gapBand, c.requests, usd(c.costUsd)]));\n}\n\nfunction compactionTable(c: CostReport[\"compactions\"]): string {\n return table(\"Compactions\", [\"total\", \"manual\", \"auto\", \"mid-loop\", \"dropped tokens\"], [[c.total, c.manual, c.auto, c.midLoop, c.droppedTokens]]);\n}\n\nfunction topSessionTable(sessions: CostReport[\"topSessions\"]): string {\n const rows = sessions.map((s) => [s.sessionId, s.sessionClass, s.role, s.initiative, s.requests, usd(s.costUsd)]);\n return table(\"Top sessions\", [\"session\", \"class\", \"role\", \"initiative\", \"requests\", \"cost\"], rows);\n}\n\nfunction unpricedTable(models: CostReport[\"unpricedModels\"]): string {\n if (models.length === 0) return \"Unpriced models: none\";\n return table(\"Unpriced models (counted at zero cost)\", [\"model\", \"requests\", \"tokens\"], models.map((m) => [m.model, m.requests, m.tokens]));\n}\n\nfunction footer(report: CostReport): string {\n const { transcriptsIndexed, transcriptsDiscovered, facetBacklog } = report.coverage;\n const discovered = transcriptsDiscovered === null ? \"\" : ` of ${transcriptsDiscovered} discovered`;\n const version = report.priceTableVersion === null ? \"none\" : `v${report.priceTableVersion}`;\n const stale = report.priceTableVersion !== null && report.priceTableVersion !== PRICE_TABLE_VERSION ? ` (package has v${PRICE_TABLE_VERSION})` : \"\";\n return `Price table ${version}${stale}. Coverage: ${transcriptsIndexed} transcripts indexed${discovered}, facet backlog ${facetBacklog}.`;\n}\n\nexport function table(title: string, head: readonly string[], rows: readonly (readonly Cell[])[]): string {\n if (rows.length === 0) return `${title}: none`;\n const text = [head, ...rows].map((row) => row.map(String));\n const widths = head.map((_, i) => Math.max(...text.map((row) => row[i]!.length)));\n const rightAligned = head.map((_, i) => rows.every((row) => isNumeric(row[i]!)));\n const pad = (cell: string, i: number) => (rightAligned[i] ? cell.padStart(widths[i]!) : cell.padEnd(widths[i]!));\n const lines = text.map((row) => row.map(pad).join(\" \").trimEnd());\n return [title, ...lines].join(\"\\n\");\n}\n\nfunction isNumeric(cell: Cell): boolean {\n return typeof cell === \"number\" || /^\\$|%$/.test(cell);\n}\n\nexport function usd(value: number): string {\n return `$${value.toFixed(2)}`;\n}\n\nfunction share(value: number, total: number): string {\n return total > 0 ? percent(value / total) : \"-\";\n}\n\nfunction percent(fraction: number): string {\n return `${(fraction * 100).toFixed(1)}%`;\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { z } from \"zod\";\nimport { GAP_BANDS, gapBand } from \"./bands.js\";\nimport { readSessionContexts, type ReportWindow } from \"./cost-report-queries.js\";\nimport { resolveWindow, tagSessions, type CostReportOptions } from \"./cost-report.js\";\nimport { PRICE_TABLE, PRICE_TABLE_VERSION, findPrice, type PriceRow } from \"./prices.js\";\nimport { LIST_PRICE_CAVEAT, table, usd } from \"./render-text.js\";\nimport { scopeFilter } from \"./scope.js\";\n\nconst FIVE_MINUTES_MS = 5 * 60_000;\nconst MTOK = 1e6;\nconst NO_PROFILE = \"none\";\n\n/** Gap bands past a 5-minute TTL: the next request finds the cache gone. */\nexport const REBUILD_GAP_BANDS: readonly string[] = GAP_BANDS.filter((band) => band.lo >= FIVE_MINUTES_MS).map((band) => band.name);\n\n/** One request as the TTL what-if needs it. */\nexport interface TtlRequestRow {\n sessionId: string;\n role: string;\n profile: string;\n model: string;\n ts: string;\n cacheReadTokens: number;\n cacheWrite1hTokens: number;\n /** Milliseconds since the session's previous request; null for its first. */\n gapMs: number | null;\n}\n\nconst count = z.number().int().nonnegative();\nconst effectFields = {\n sessions: count,\n requests: count,\n write1hTokens: count,\n /** 1h writes repriced at the 5m write rate. */\n repriceSavingUsd: z.number(),\n rebuilds: count,\n rebuildTokens: count,\n /** Each rebuild writes at the 5m rate what the 1h cache still served as a read. */\n rebuildCostUsd: z.number(),\n netSavingUsd: z.number(),\n netPerSessionUsd: z.number(),\n};\nconst bucketSchema = z.object({ key: z.string(), ...effectFields, fiveMinuteLoses: z.boolean() });\n\nexport const cacheTtlWhatIfSchema = z.object({\n window: z.object({ since: z.string().nullable(), until: z.string().nullable() }).optional(),\n priceTableVersion: z.number().int(),\n rebuildGapBands: z.array(z.string()),\n totals: z.object(effectFields),\n unpricedRequests: count,\n byRole: z.array(bucketSchema),\n byProfile: z.array(bucketSchema),\n /** Roles whose rebuilds after long gaps outweigh the cheaper writes. */\n lossRoles: z.array(z.string()),\n});\n\nexport type CacheTtlWhatIf = z.infer<typeof cacheTtlWhatIfSchema>;\nexport type CacheTtlBucket = z.infer<typeof bucketSchema>;\n\ninterface RequestEffect {\n sessionId: string;\n write1hTokens: number;\n repriceSavingUsd: number;\n rebuildTokens: number;\n rebuildCostUsd: number;\n}\n\n/** Q3: what each role and profile would have paid with `CLAUDE_CODE_PROMPT_CACHE_TTL=5m` instead of 1h. */\nexport function cacheTtlWhatIf(rows: readonly TtlRequestRow[], prices: readonly PriceRow[] = PRICE_TABLE): CacheTtlWhatIf {\n const effects = new Map<TtlRequestRow, RequestEffect>();\n for (const row of rows) {\n const price = findPrice(row.model, row.ts, prices);\n if (price) effects.set(row, requestEffect(row, price));\n }\n const priced = [...effects.keys()];\n const byRole = buckets(priced, effects, (row) => row.role);\n return {\n priceTableVersion: PRICE_TABLE_VERSION,\n rebuildGapBands: [...REBUILD_GAP_BANDS],\n totals: sumEffects([...effects.values()]),\n unpricedRequests: rows.length - priced.length,\n byRole,\n byProfile: buckets(priced, effects, (row) => row.profile),\n lossRoles: byRole.filter((bucket) => bucket.fiveMinuteLoses).map((bucket) => bucket.key),\n };\n}\n\nfunction requestEffect(row: TtlRequestRow, price: PriceRow): RequestEffect {\n const band = row.gapMs === null ? null : gapBand(row.gapMs);\n const rebuildTokens = band !== null && REBUILD_GAP_BANDS.includes(band) ? row.cacheReadTokens : 0;\n return {\n sessionId: row.sessionId,\n write1hTokens: row.cacheWrite1hTokens,\n repriceSavingUsd: (row.cacheWrite1hTokens * (price.cacheWrite1h - price.cacheWrite5m)) / MTOK,\n rebuildTokens,\n rebuildCostUsd: (rebuildTokens * (price.cacheWrite5m - price.cacheRead)) / MTOK,\n };\n}\n\nfunction sumEffects(effects: readonly RequestEffect[]): CacheTtlWhatIf[\"totals\"] {\n const sum = (pick: (effect: RequestEffect) => number) => effects.reduce((total, effect) => total + pick(effect), 0);\n const sessions = new Set(effects.map((effect) => effect.sessionId)).size;\n const netSavingUsd = sum((effect) => effect.repriceSavingUsd - effect.rebuildCostUsd);\n return {\n sessions,\n requests: effects.length,\n write1hTokens: sum((effect) => effect.write1hTokens),\n repriceSavingUsd: sum((effect) => effect.repriceSavingUsd),\n rebuilds: effects.filter((effect) => effect.rebuildTokens > 0).length,\n rebuildTokens: sum((effect) => effect.rebuildTokens),\n rebuildCostUsd: sum((effect) => effect.rebuildCostUsd),\n netSavingUsd,\n netPerSessionUsd: sessions > 0 ? netSavingUsd / sessions : 0,\n };\n}\n\n/** Largest saving first, so the roles 5m would cost money sit at the bottom. */\nfunction buckets(rows: readonly TtlRequestRow[], effects: Map<TtlRequestRow, RequestEffect>, keyOf: (row: TtlRequestRow) => string): CacheTtlBucket[] {\n const groups = new Map<string, RequestEffect[]>();\n for (const row of rows) {\n const key = keyOf(row);\n const members = groups.get(key);\n if (members) members.push(effects.get(row)!);\n else groups.set(key, [effects.get(row)!]);\n }\n return [...groups]\n .map(([key, members]) => {\n const totals = sumEffects(members);\n return { key, ...totals, fiveMinuteLoses: totals.netSavingUsd < 0 };\n })\n .sort((a, b) => b.netSavingUsd - a.netSavingUsd || a.key.localeCompare(b.key));\n}\n\nconst IN_WINDOW = \"(@since IS NULL OR ts >= @since) AND (@until IS NULL OR ts < @until)\";\n\n// The miner leaves `gap_ms` null, so the gap falls back to the session's previous request, even one before the window.\nconst TTL_ROWS = `\n WITH member AS (SELECT DISTINCT session_id FROM request_dedup WHERE ${IN_WINDOW}),\n timed AS (\n SELECT session_id, model, ts, cache_read_tokens, cache_creation_1h, gap_ms,\n LAG(ts) OVER (PARTITION BY session_id, is_sidechain ORDER BY ts, request_id) AS previous_ts\n FROM request_dedup WHERE session_id IN member\n )\n SELECT session_id AS sessionId, model, ts, cache_read_tokens AS cacheReadTokens, cache_creation_1h AS cacheWrite1hTokens,\n COALESCE(gap_ms, CAST(ROUND((julianday(ts) - julianday(previous_ts)) * 86400000) AS INTEGER)) AS gapMs\n FROM timed WHERE ${IN_WINDOW}`;\n\n/** Reads the graph and never writes it; roles are the cost report's. */\nexport function cacheTtlReport(db: Db, options: CostReportOptions = {}, prices: readonly PriceRow[] = PRICE_TABLE): CacheTtlWhatIf {\n const window = resolveWindow(options);\n return { window, ...cacheTtlWhatIf(readTtlRows(db, window).filter(scopeFilter(db, options.scope)), prices) };\n}\n\nexport function readTtlRows(db: Db, window: ReportWindow): TtlRequestRow[] {\n const rows = db.prepare(TTL_ROWS).all(window) as Omit<TtlRequestRow, \"role\" | \"profile\">[];\n const contexts = readSessionContexts(db, [...new Set(rows.map((row) => row.sessionId))]);\n const tags = tagSessions(contexts);\n return rows.map((row) => ({\n ...row,\n role: tags.get(row.sessionId)!.role,\n profile: contexts.get(row.sessionId)!.facts.origin?.profile ?? NO_PROFILE,\n }));\n}\n\n/** One table per dimension; a role or profile 5m would cost money is marked `loss`. */\nexport function renderCacheTtlText(whatIf: CacheTtlWhatIf): string {\n const { totals, window } = whatIf;\n const span = window ? `, ${window.since ?? \"beginning\"} to ${window.until ?? \"now\"}` : \"\";\n const header = [\n `Cache TTL what-if, 5m against 1h${span}`,\n `Net ${usd(totals.netSavingUsd)} over ${totals.sessions} sessions: 1h writes repriced save ${usd(totals.repriceSavingUsd)}, ` +\n `${totals.rebuilds} rebuilds after gaps in ${whatIf.rebuildGapBands.join(\", \")} cost ${usd(totals.rebuildCostUsd)}`,\n `Roles where 5m loses: ${whatIf.lossRoles.join(\", \") || \"none\"}`,\n ].join(\"\\n\");\n const footer = `Price table v${whatIf.priceTableVersion}; ${whatIf.unpricedRequests} unpriced requests left out.`;\n return [header, ttlTable(\"By role\", whatIf.byRole), ttlTable(\"By profile\", whatIf.byProfile), [LIST_PRICE_CAVEAT, footer].join(\"\\n\")].join(\"\\n\\n\") + \"\\n\";\n}\n\nfunction ttlTable(title: string, rows: readonly CacheTtlBucket[]): string {\n const head = [\"key\", \"sessions\", \"requests\", \"reprice saving\", \"rebuilds\", \"rebuild cost\", \"net\", \"net per session\", \"5m\"];\n const cells = rows.map((b) => [b.key, b.sessions, b.requests, usd(b.repriceSavingUsd), b.rebuilds, usd(b.rebuildCostUsd), usd(b.netSavingUsd), usd(b.netPerSessionUsd), b.fiveMinuteLoses ? \"loss\" : \"saves\"]);\n return table(title, head, cells);\n}\n","import { z } from \"zod\";\n\n/** One reviewer verdict message, as agent-chat's events table records it. */\nexport interface VerdictRecord {\n eventId: number;\n at: string;\n /** The seat the verdict was sent to. */\n seat: string;\n reviewer: string;\n verdict: string;\n repo: string;\n pr: number;\n head: string;\n}\n\n/** A PR as GitHub REST reports it at the time of the run. */\nexport interface PullState {\n repo: string;\n pr: number;\n state: \"open\" | \"closed\";\n mergedAt: string | null;\n headSha: string;\n}\n\nexport type ParsedVerdict = Pick<VerdictRecord, \"verdict\" | \"repo\" | \"pr\" | \"head\">;\n\nconst VERDICT_LINE = /^Verdict:\\s*([A-Z_]+)/;\nconst PR_LINE = /^PR:\\s*(?:https:\\/\\/github\\.com\\/)?([\\w.-]+\\/[\\w.-]+)(?:#|\\/pull\\/)(\\d+)/m;\nconst HEAD_LINE = /^Head:\\s*`?([0-9a-f]{7,40})\\b/m;\n\n/** Reads a `Verdict:` message's first three lines; null when any of them is missing. */\nexport function parseVerdict(body: string): ParsedVerdict | null {\n const verdict = VERDICT_LINE.exec(body)?.[1];\n const pr = PR_LINE.exec(body);\n const head = HEAD_LINE.exec(body)?.[1];\n if (!verdict || !pr || !head) return null;\n return { verdict, repo: pr[1]!, pr: Number(pr[2]), head };\n}\n\nexport type MergeStatus = \"merged\" | \"open\" | \"stale-head\" | \"closed\" | \"unknown\";\n\n/** A PR holding at least one MERGE verdict, resolved against its GitHub state at `asOf`. */\nexport interface MergeOutcome {\n repo: string;\n pr: number;\n status: MergeStatus;\n /** The first MERGE verdict at the PR's final head; null when no verdict names that head. */\n verdict: VerdictRecord | null;\n /** Verdict to merge for merged PRs; verdict to `asOf` (a censored age) for open ones. */\n minutes: number | null;\n}\n\nconst MINUTE_MS = 60_000;\n\nexport function mergeOutcomes(verdicts: readonly VerdictRecord[], pulls: readonly PullState[], asOf: string): MergeOutcome[] {\n const byPr = new Map<string, VerdictRecord[]>();\n for (const v of verdicts) if (v.verdict === \"MERGE\") byPr.set(prKey(v), [...(byPr.get(prKey(v)) ?? []), v]);\n const pullByKey = new Map(pulls.map((p) => [prKey(p), p]));\n return [...byPr.values()].map((held) => outcome(held, pullByKey.get(prKey(held[0]!)), asOf));\n}\n\nexport function prKey(row: { repo: string; pr: number }): string {\n return `${row.repo}#${row.pr}`;\n}\n\nfunction outcome(held: VerdictRecord[], pull: PullState | undefined, asOf: string): MergeOutcome {\n const { repo, pr } = held[0]!;\n if (!pull) return { repo, pr, status: \"unknown\", verdict: null, minutes: null };\n const atHead = held.filter((v) => sameSha(v.head, pull.headSha)).sort((a, b) => a.at.localeCompare(b.at))[0];\n const mergedBy = pull.mergedAt !== null && pull.mergedAt <= asOf;\n if (!atHead) return { repo, pr, status: pull.mergedAt !== null || pull.state === \"open\" ? \"stale-head\" : \"closed\", verdict: null, minutes: null };\n if (mergedBy) return { repo, pr, status: \"merged\", verdict: atHead, minutes: Math.max(0, minutesBetween(atHead.at, pull.mergedAt!)) };\n if (pull.state === \"open\" || pull.mergedAt !== null) return { repo, pr, status: \"open\", verdict: atHead, minutes: minutesBetween(atHead.at, asOf) };\n return { repo, pr, status: \"closed\", verdict: atHead, minutes: null };\n}\n\nfunction sameSha(a: string, b: string): boolean {\n return a.startsWith(b) || b.startsWith(a);\n}\n\nfunction minutesBetween(from: string, to: string): number {\n return (Date.parse(to) - Date.parse(from)) / MINUTE_MS;\n}\n\nconst minutes = z.number().nullable();\n\nexport const latencyStatsSchema = z.object({\n merged: z.number().int().nonnegative(),\n medianMin: minutes,\n meanMin: minutes,\n p90Min: minutes,\n maxMin: minutes,\n /** Open PRs holding MERGE at their current head; their ages are lower bounds on the wait. */\n censored: z.number().int().nonnegative(),\n oldestCensoredMin: minutes,\n censoredPrMinutes: z.number().nonnegative(),\n /** Median over merged waits and censored ages together: a lower bound on the true median. */\n medianWithCensoredMin: minutes,\n});\n\nexport type LatencyStats = z.infer<typeof latencyStatsSchema>;\n\nexport function latencyStats(outcomes: readonly MergeOutcome[]): LatencyStats {\n const merged = sorted(outcomes.filter((o) => o.status === \"merged\").map((o) => o.minutes!));\n const censored = sorted(outcomes.filter((o) => o.status === \"open\").map((o) => o.minutes!));\n return {\n merged: merged.length,\n medianMin: median(merged),\n meanMin: merged.length === 0 ? null : round(merged.reduce((a, b) => a + b, 0) / merged.length),\n p90Min: nearestRank(merged, 0.9),\n maxMin: merged.at(-1) === undefined ? null : round(merged.at(-1)!),\n censored: censored.length,\n oldestCensoredMin: censored.at(-1) === undefined ? null : round(censored.at(-1)!),\n censoredPrMinutes: round(censored.reduce((a, b) => a + b, 0)),\n medianWithCensoredMin: median(sorted([...merged, ...censored])),\n };\n}\n\nfunction sorted(values: number[]): number[] {\n return values.sort((a, b) => a - b);\n}\n\nfunction median(values: readonly number[]): number | null {\n if (values.length === 0) return null;\n const mid = Math.floor(values.length / 2);\n return round(values.length % 2 === 1 ? values[mid]! : (values[mid - 1]! + values[mid]!) / 2);\n}\n\nfunction nearestRank(values: readonly number[], p: number): number | null {\n return values.length === 0 ? null : round(values[Math.ceil(p * values.length) - 1]!);\n}\n\nexport function round(value: number): number {\n return Math.round(value * 10) / 10;\n}\n","/** One action the auto-mode classifier refused, read from a seat's transcript. */\nexport interface DenialRecord {\n seat: string;\n at: string;\n /** The classifier's bracketed reason, such as \"Merge Without Review\". */\n reason: string;\n /** What the refused call was doing, from its tool input; the reason label alone is loose. */\n action: string;\n tool: string;\n /** The refused call's id; a forked or resumed transcript repeats it, so it is counted once. */\n toolUseId?: string;\n}\n\nconst DENIAL = /^Permission for this action (?:was|has been) denied by the Claude Code auto mode classifier\\. Reason: \\[([^\\]]+)\\]/;\n\nconst BASH_ACTIONS: readonly (readonly [string, RegExp])[] = [\n [\"merge\", /\\bgh pr merge\\b|\\/pulls\\/\\d+\\/merge\\b/],\n [\"retire\", /\\bagent[ _-]retire\\b|\\bagent\\s+retire\\b/],\n [\"worktree-remove\", /\\bgit\\b.*\\bworktree (?:remove|prune)\\b/],\n [\"branch-delete\", /\\bgit branch -[dD]\\b|\\bpush\\b.*--delete\\b|\\/git\\/refs\\/heads\\/\\S*.*-X DELETE|-X DELETE\\b.*\\/git\\/refs\\//],\n [\"push\", /\\bgit\\b.*\\bpush\\b/],\n [\"github-write\", /\\bgh (?:pr|issue) (?:create|edit|comment|close)\\b|\\bgh api\\b.*(?:-X|--method)\\s*(?:POST|PATCH|PUT|DELETE)\\b/],\n [\"service-restart\", /\\bservice restart\\b|\\blaunchctl\\b/],\n [\"process-kill\", /\\b(?:pkill|kill)\\b/],\n [\"file-write\", /\\s>>?\\s*(?!\\/dev\\/null|&)\\S|\\bopen\\([^)]*[\"'][wa][\"']\\)|\\bsed -i\\b/],\n];\n\nconst FILE_TOOLS = new Set([\"Edit\", \"Write\", \"MultiEdit\", \"NotebookEdit\"]);\n\n/** Classifies a refused call by what it did; MCP tools keep their own short name. */\nexport function classifyDeniedAction(tool: string, input: unknown): string {\n if (tool === \"Bash\") return bashAction(String((input as { command?: unknown } | null)?.command ?? \"\"));\n if (FILE_TOOLS.has(tool)) return \"file-edit\";\n if (tool.startsWith(\"mcp__\")) return `mcp:${tool.split(\"__\").at(-1)}`;\n return `tool:${tool}`;\n}\n\nfunction bashAction(command: string): string {\n return BASH_ACTIONS.find(([, pattern]) => pattern.test(command))?.[0] ?? \"bash-other\";\n}\n\ninterface TranscriptEntry {\n timestamp?: string;\n message?: { content?: unknown };\n}\n\ninterface ContentBlock {\n type?: string;\n id?: string;\n name?: string;\n input?: unknown;\n tool_use_id?: string;\n content?: unknown;\n}\n\n/** Scans transcript JSONL for classifier refusals and joins each to the tool call it refused. */\nexport function parseDenials(lines: Iterable<string>, seat: string): DenialRecord[] {\n const calls = new Map<string, { tool: string; input: unknown }>();\n const denials: DenialRecord[] = [];\n for (const line of lines) {\n if (!line.includes('\"tool_use\"') && !line.includes(\"auto mode classifier\")) continue;\n const entry = parseLine(line);\n for (const block of blocksOf(entry)) {\n if (block.type === \"tool_use\" && block.id) calls.set(block.id, { tool: block.name ?? \"unknown\", input: block.input });\n const reason = block.type === \"tool_result\" ? DENIAL.exec(resultText(block.content))?.[1] : undefined;\n if (reason === undefined) continue;\n const call = calls.get(block.tool_use_id ?? \"\") ?? { tool: \"unknown\", input: null };\n const toolUseId = block.tool_use_id ? { toolUseId: block.tool_use_id } : {};\n denials.push({ seat, at: entry?.timestamp ?? \"\", reason, action: classifyDeniedAction(call.tool, call.input), tool: call.tool, ...toolUseId });\n }\n }\n return denials;\n}\n\n/** One denial per refused call; a record without a tool_use_id cannot be matched and is kept. */\nexport function dedupeDenials(denials: readonly DenialRecord[]): DenialRecord[] {\n const seen = new Set<string>();\n return denials.filter((d) => {\n if (d.toolUseId === undefined) return true;\n const key = `${d.seat}\\u0000${d.toolUseId}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nfunction parseLine(line: string): TranscriptEntry | null {\n try {\n return JSON.parse(line) as TranscriptEntry;\n } catch {\n return null;\n }\n}\n\nfunction blocksOf(entry: TranscriptEntry | null): ContentBlock[] {\n const content = entry?.message?.content;\n return Array.isArray(content) ? (content as ContentBlock[]) : [];\n}\n\nfunction resultText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n const first = (content as { type?: string; text?: string }[]).find((part) => part.type === \"text\");\n return first?.text ?? \"\";\n}\n","/** A seat journal line that states its implementer slot count, and why it did not fill a free slot. */\nexport interface SlotTick {\n seat: string;\n at: string;\n used: number;\n cap: number;\n reason: string;\n /** The journal line number, so a row can be checked against its source. */\n line: number;\n}\n\nexport interface SeatJournal {\n ticks: SlotTick[];\n /** The journal's last timestamped line; the final tick holds until then. */\n lastAt: string | null;\n}\n\nexport const UNSTATED_REASON = \"unstated\";\n\n/** A tick's count holds at most this long, so a dark seat is not read as an hour of idle slots. */\nexport const TICK_HOLD_MAX_MIN = 60;\n\nconst STAMP = /^(\\d{1,2}):(\\d{2})(?::(\\d{2}))?\\s/;\nconst IMPL = /\\bimpl(?:ementers?)?\\s+(\\d+)\\s*\\/\\s*(\\d+)/i;\nconst REASON = /\\b(?:no dispatch|dispatch 0)\\s*:\\s*([^.;(]+)/i;\n\n/**\n * Reads `HH:MM[:SS] ...` journal lines for the date the journal covers.\n * `utcOffsetMin` is the journal clock's offset east of UTC, such as -360 for UTC-6.\n */\nexport function parseSeatJournal(text: string, seat: string, date: string, utcOffsetMin: number): SeatJournal {\n const ticks: SlotTick[] = [];\n let lastAt: string | null = null;\n text.split(\"\\n\").forEach((raw, index) => {\n const stamp = STAMP.exec(raw);\n if (!stamp) return;\n const at = journalTime(date, stamp, utcOffsetMin);\n lastAt = at;\n const impl = IMPL.exec(raw);\n if (!impl) return;\n const used = Number(impl[1]);\n const cap = Number(impl[2]);\n const reason = used < cap ? (REASON.exec(raw)?.[1]?.trim().toLowerCase() ?? UNSTATED_REASON) : \"\";\n ticks.push({ seat, at, used, cap, reason, line: index + 1 });\n });\n return { ticks, lastAt };\n}\n\nfunction journalTime(date: string, stamp: RegExpExecArray, utcOffsetMin: number): string {\n const [year, month, day] = date.split(\"-\").map(Number);\n const local = Date.UTC(year!, month! - 1, day!, Number(stamp[1]), Number(stamp[2]), Number(stamp[3] ?? 0));\n return new Date(local - utcOffsetMin * 60_000).toISOString();\n}\n\nexport interface IdleSlotRow {\n seat: string;\n reason: string;\n slotMinutes: number;\n ticks: number;\n /** Journal line numbers of the ticks counted here. */\n lines: number[];\n}\n\n/** Free implementer slots times the minutes each tick's count held, clipped to the window. */\nexport function idleSlotMinutes(journals: readonly SeatJournal[], window: { since?: string; until?: string }): IdleSlotRow[] {\n const rows = new Map<string, IdleSlotRow>();\n for (const journal of journals) {\n journal.ticks.forEach((tick, i) => {\n const free = Math.max(0, tick.cap - tick.used);\n const held = heldMinutes(tick.at, journal.ticks[i + 1]?.at ?? journal.lastAt ?? tick.at, window);\n if (free === 0 || held <= 0) return;\n const key = `${tick.seat}\\u0000${tick.reason}`;\n const row = rows.get(key) ?? { seat: tick.seat, reason: tick.reason, slotMinutes: 0, ticks: 0, lines: [] };\n rows.set(key, { ...row, slotMinutes: row.slotMinutes + free * held, ticks: row.ticks + 1, lines: [...row.lines, tick.line] });\n });\n }\n return [...rows.values()].map((r) => ({ ...r, slotMinutes: Math.round(r.slotMinutes) })).sort((a, b) => b.slotMinutes - a.slotMinutes);\n}\n\nfunction heldMinutes(from: string, to: string, window: { since?: string; until?: string }): number {\n const start = Math.max(Date.parse(from), window.since ? Date.parse(window.since) : -Infinity);\n const capped = Math.min(Date.parse(to), Date.parse(from) + TICK_HOLD_MAX_MIN * 60_000);\n const end = Math.min(capped, window.until ? Date.parse(window.until) : Infinity);\n return Math.max(0, (end - start) / 60_000);\n}\n","import { z } from \"zod\";\nimport { latencyStats, latencyStatsSchema, mergeOutcomes, round, type LatencyStats, type MergeOutcome, type PullState, type VerdictRecord } from \"./blocked-flow-merge.js\";\nimport { dedupeDenials, type DenialRecord } from \"./blocked-flow-denials.js\";\nimport { TICK_HOLD_MAX_MIN, idleSlotMinutes, type SeatJournal } from \"./blocked-flow-idle.js\";\nimport { LIST_PRICE_CAVEAT, table } from \"./render-text.js\";\n\n/** Where each section's numbers come from: the command that re-reads them and the field it reads. */\nexport const BLOCKED_FLOW_SOURCES = {\n verdicts: {\n command: `sqlite3 -readonly <events.db> \"SELECT id, ts, target, body FROM events WHERE kind='message' AND body LIKE 'Verdict:%'\"`,\n field: \"events.ts, events.target, events.body lines Verdict:, PR:, Head:\",\n },\n pulls: { command: \"gh api repos/<owner>/<repo>/pulls/<n>\", field: \".state, .merged_at, .head.sha\" },\n denials: {\n command: \"grep 'auto mode classifier. Reason: \\\\[' <seat transcript>.jsonl\",\n field: \"tool_result.content Reason: [<class>], joined to tool_use.input by tool_use_id\",\n },\n journals: { command: \"grep -nE 'impl [0-9]+/[0-9]+' <seat journal>.md\", field: \"impl <used>/<cap>, No dispatch: <reason>\" },\n} as const;\n\nexport type BlockedFlowSource = keyof typeof BLOCKED_FLOW_SOURCES;\n\nexport interface BlockedFlowInput {\n verdicts: readonly VerdictRecord[];\n pulls: readonly PullState[];\n denials: readonly DenialRecord[];\n journals: readonly SeatJournal[];\n /** Waits are measured to here; a PR merged later counts as open. */\n asOf: string;\n window?: { since?: string; until?: string };\n /** Splits verdict-to-merge by verdict time, such as the moment a seat was granted merge authority. */\n splitAt?: string;\n /** Keeps only verdicts sent to, and denials and journals of, these seats. */\n seats?: readonly string[];\n}\n\nconst source = z.enum([\"verdicts\", \"pulls\", \"denials\", \"journals\"]);\nconst count = z.number().int().nonnegative();\n\nconst latencyRowSchema = z.object({\n repo: z.string(),\n prs: count,\n staleHead: count,\n closed: count,\n unknown: count,\n all: latencyStatsSchema,\n before: latencyStatsSchema.optional(),\n after: latencyStatsSchema.optional(),\n});\n\nconst openRowSchema = z.object({\n repo: z.string(),\n pr: count,\n head: z.string(),\n seat: z.string(),\n verdictAt: z.string(),\n ageMin: z.number(),\n eventId: count,\n});\n\nexport const blockedFlowSchema = z.object({\n asOf: z.string(),\n window: z.object({ since: z.string().optional(), until: z.string().optional() }),\n splitAt: z.string().optional(),\n sources: z.record(source, z.object({ command: z.string(), field: z.string() })),\n verdictToMerge: z.object({ cites: z.array(source), rows: z.array(latencyRowSchema) }),\n openHoldingMerge: z.object({ cites: z.array(source), prMinutes: z.number(), rows: z.array(openRowSchema) }),\n denials: z.object({\n cites: z.array(source),\n total: count,\n rows: z.array(z.object({ reason: z.string(), action: z.string(), seat: z.string(), count })),\n }),\n idleSlots: z.object({\n cites: z.array(source),\n holdMaxMin: z.number(),\n total: z.number(),\n rows: z.array(z.object({ seat: z.string(), reason: z.string(), slotMinutes: z.number(), ticks: count, lines: z.array(count) })),\n }),\n});\n\nexport type BlockedFlowReport = z.infer<typeof blockedFlowSchema>;\nexport type LatencyRow = z.infer<typeof latencyRowSchema>;\n\nexport const ALL_REPOS = \"all\";\n\n/** Per repo: verdict-to-merge waits, PRs still holding MERGE, classifier denials and idle implementer slots. */\nexport function blockedFlowReport(input: BlockedFlowInput): BlockedFlowReport {\n const window = input.window ?? {};\n const inScope = scopeTest(input.seats, window);\n const outcomes = mergeOutcomes(input.verdicts.filter((v) => inScope(v.seat, v.at)), input.pulls, input.asOf);\n const open = openRows(outcomes);\n const journals = input.journals.map((j) => ({ ...j, ticks: j.ticks.filter((t) => inScope(t.seat)) }));\n const idle = idleSlotMinutes(journals, window);\n return {\n asOf: input.asOf,\n window,\n ...(input.splitAt ? { splitAt: input.splitAt } : {}),\n sources: BLOCKED_FLOW_SOURCES,\n verdictToMerge: { cites: [\"verdicts\", \"pulls\"], rows: latencyRows(outcomes, input.splitAt) },\n openHoldingMerge: { cites: [\"verdicts\", \"pulls\"], prMinutes: round(open.reduce((sum, r) => sum + r.ageMin, 0)), rows: open },\n denials: denialSection(dedupeDenials(input.denials).filter((d) => inScope(d.seat, d.at))),\n idleSlots: { cites: [\"journals\"], holdMaxMin: TICK_HOLD_MAX_MIN, total: idle.reduce((sum, r) => sum + r.slotMinutes, 0), rows: idle },\n };\n}\n\nfunction scopeTest(seats: readonly string[] | undefined, window: { since?: string; until?: string }) {\n const named = seats ? new Set(seats) : null;\n return (seat: string, at?: string): boolean =>\n (!named || named.has(seat)) && (at === undefined || ((!window.since || at >= window.since) && (!window.until || at < window.until)));\n}\n\nfunction latencyRows(outcomes: readonly MergeOutcome[], splitAt: string | undefined): LatencyRow[] {\n const repos = [...new Set(outcomes.map((o) => o.repo))];\n const rows = repos.map((repo) => latencyRow(repo, outcomes.filter((o) => o.repo === repo), splitAt));\n return [...rows.sort((a, b) => b.prs - a.prs || a.repo.localeCompare(b.repo)), latencyRow(ALL_REPOS, outcomes, splitAt)];\n}\n\nfunction latencyRow(repo: string, outcomes: readonly MergeOutcome[], splitAt: string | undefined): LatencyRow {\n const status = (s: string) => outcomes.filter((o) => o.status === s).length;\n const row: LatencyRow = { repo, prs: outcomes.length, staleHead: status(\"stale-head\"), closed: status(\"closed\"), unknown: status(\"unknown\"), all: latencyStats(outcomes) };\n if (!splitAt) return row;\n const timed = outcomes.filter((o) => o.verdict !== null);\n return { ...row, before: latencyStats(timed.filter((o) => o.verdict!.at < splitAt)), after: latencyStats(timed.filter((o) => o.verdict!.at >= splitAt)) };\n}\n\nfunction openRows(outcomes: readonly MergeOutcome[]): BlockedFlowReport[\"openHoldingMerge\"][\"rows\"] {\n return outcomes\n .filter((o) => o.status === \"open\")\n .map((o) => ({ repo: o.repo, pr: o.pr, head: o.verdict!.head, seat: o.verdict!.seat, verdictAt: o.verdict!.at, ageMin: round(o.minutes!), eventId: o.verdict!.eventId }))\n .sort((a, b) => b.ageMin - a.ageMin);\n}\n\nfunction denialSection(denials: readonly DenialRecord[]): BlockedFlowReport[\"denials\"] {\n const counts = new Map<string, { reason: string; action: string; seat: string; count: number }>();\n for (const d of denials) {\n const key = [d.reason, d.action, d.seat].join(\"\\u0000\");\n const row = counts.get(key) ?? { reason: d.reason, action: d.action, seat: d.seat, count: 0 };\n counts.set(key, { ...row, count: row.count + 1 });\n }\n const rows = [...counts.values()].sort((a, b) => b.count - a.count || a.reason.localeCompare(b.reason) || a.action.localeCompare(b.action));\n return { cites: [\"denials\"], total: denials.length, rows };\n}\n\n/** Each table's title names the JSON field its numbers come from; the sources close the report. */\nexport function renderBlockedFlowText(report: BlockedFlowReport): string {\n const scope = `Blocked flow as of ${report.asOf}${report.window.since ? `, since ${report.window.since}` : \"\"}${report.window.until ? `, until ${report.window.until}` : \"\"}`;\n const latency = [latencyTable(\"Verdict to merge, minutes from the first MERGE at the final head [verdictToMerge.rows[].all]\", report.verdictToMerge.rows, \"all\")];\n if (report.splitAt) latency.push(...([\"before\", \"after\"] as const).map((part) => latencyTable(`Verdict to merge, verdicts ${part} ${report.splitAt} [verdictToMerge.rows[].${part}]`, report.verdictToMerge.rows, part)));\n return [scope, ...latency, openTable(report), denialTable(report), idleTable(report), sourceLines(report), LIST_PRICE_CAVEAT].join(\"\\n\\n\") + \"\\n\";\n}\n\nfunction latencyTable(title: string, rows: readonly LatencyRow[], part: \"all\" | \"before\" | \"after\"): string {\n const cells = rows.map((r) => [r.repo, r.prs, ...statCells(r[part]!), r.staleHead]);\n return table(title, [\"repo\", \"prs\", \"merged\", \"median\", \"mean\", \"p90\", \"max\", \"open\", \"oldest open\", \"median incl. open\", \"stale head\"], cells);\n}\n\nfunction statCells(s: LatencyStats): (string | number)[] {\n const n = (v: number | null) => (v === null ? \"-\" : v);\n return [s.merged, n(s.medianMin), n(s.meanMin), n(s.p90Min), n(s.maxMin), s.censored, n(s.oldestCensoredMin), n(s.medianWithCensoredMin)];\n}\n\nfunction openTable(report: BlockedFlowReport): string {\n const rows = report.openHoldingMerge.rows.map((r) => [r.repo, `#${r.pr}`, r.head.slice(0, 7), r.seat, r.verdictAt, r.ageMin, `events#${r.eventId}`]);\n const title = `Open PRs holding MERGE at their current head, ${report.openHoldingMerge.prMinutes} PR-minutes [openHoldingMerge.rows[].ageMin]`;\n return table(title, [\"repo\", \"pr\", \"head\", \"seat\", \"verdict at\", \"age min\", \"verdict\"], rows);\n}\n\nfunction denialTable(report: BlockedFlowReport): string {\n const rows = report.denials.rows.map((r) => [r.reason, r.action, r.seat, r.count]);\n return table(`Classifier denials, ${report.denials.total} in all [denials.rows[].count]`, [\"reason\", \"action\", \"seat\", \"count\"], rows);\n}\n\nfunction idleTable(report: BlockedFlowReport): string {\n const rows = report.idleSlots.rows.map((r) => [r.seat, r.reason, r.slotMinutes, r.ticks, r.lines.join(\",\")]);\n const title = `Idle implementer slot-minutes by stated reason, ${report.idleSlots.total} in all, each tick held at most ${report.idleSlots.holdMaxMin} min [idleSlots.rows[].slotMinutes]`;\n return table(title, [\"seat\", \"reason\", \"slot-min\", \"ticks\", \"journal lines\"], rows);\n}\n\nfunction sourceLines(report: BlockedFlowReport): string {\n return [\"Sources\", ...Object.entries(report.sources).map(([name, s]) => `${name}: ${s.command} (${s.field})`)].join(\"\\n\");\n}\n","/** One agent-chat broker.log entry and the 1-based line it came from, so each finding can cite it. */\nexport interface BrokerEntry {\n line: number;\n ts: string;\n event: string;\n fields: Record<string, unknown>;\n}\n\n/** Broker log lines to entries; a line that is not a JSON object with `ts` and `event` is skipped but still counted. */\nexport function parseBrokerLog(lines: Iterable<string>): BrokerEntry[] {\n const entries: BrokerEntry[] = [];\n let line = 0;\n for (const text of lines) {\n line += 1;\n const fields = text.startsWith(\"{\") ? parseObject(text) : null;\n if (fields && typeof fields.ts === \"string\" && typeof fields.event === \"string\") entries.push({ line, ts: fields.ts, event: fields.event, fields });\n }\n return entries;\n}\n\nfunction parseObject(text: string): Record<string, unknown> | null {\n try {\n const value: unknown = JSON.parse(text);\n return typeof value === \"object\" && value !== null && !Array.isArray(value) ? (value as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nexport function stringField(entry: BrokerEntry, key: string): string | null {\n const value = entry.fields[key];\n return typeof value === \"string\" ? value : null;\n}\n\n/** The broker joins several recipients into one `to` as \"a, b\". */\nexport function splitNames(to: string | null): string[] {\n return (to ?? \"\").split(\",\").map((name) => name.trim()).filter((name) => name.length > 0);\n}\n\nexport function minutesBetween(from: string, to: string): number {\n return Math.round((Date.parse(to) - Date.parse(from)) / 6_000) / 10;\n}\n","import { splitNames, stringField, type BrokerEntry } from \"./liveness-broker.js\";\n\n/**\n * How a route missed a recipient: `failed` is a `delivered:false` the broker dropped, `partial` reached\n * others but not this name, and `queued` is a `delivered:false` the broker kept for later delivery.\n */\nexport type RouteMissKind = \"failed\" | \"partial\" | \"queued\";\n\n/** One recipient a routed message did not reach when it was sent. */\nexport interface RouteMiss {\n line: number;\n at: string;\n recipient: string;\n from: string;\n kind: string;\n miss: RouteMissKind;\n}\n\nexport interface RouteFailureRow {\n recipient: string;\n failed: number;\n partial: number;\n queued: number;\n first: string;\n last: string;\n lines: number[];\n}\n\n/** Answers and decisions to an offline author are written to its inbox, so `delivered:false` there is a delay. */\nconst INBOX_KINDS = new Set([\"answer\", \"decided\"]);\n\n/** Each recipient named in `to` that a route did not reach. */\nexport function routeMisses(entries: readonly BrokerEntry[]): RouteMiss[] {\n return entries.filter((e) => e.event === \"route\").flatMap((entry) => {\n const base = { line: entry.line, at: entry.ts, from: stringField(entry, \"from\") ?? \"\", kind: stringField(entry, \"kind\") ?? \"\" };\n return missedRecipients(entry).map(({ recipient, miss }) => ({ ...base, recipient, miss }));\n });\n}\n\nfunction missedRecipients(entry: BrokerEntry): { recipient: string; miss: RouteMissKind }[] {\n const to = stringField(entry, \"to\");\n const kind = stringField(entry, \"kind\") ?? \"\";\n if (to === null || to.startsWith(\"tag \") || kind === \"broadcast\") return [];\n const named = splitNames(to);\n if (entry.fields.delivered === false) {\n const miss = entry.fields.held !== undefined || INBOX_KINDS.has(kind) ? \"queued\" : \"failed\";\n return named.map((recipient) => ({ recipient, miss }));\n }\n const reached = entry.fields.recipients;\n if (entry.fields.delivered !== true || !Array.isArray(reached)) return [];\n return named.filter((name) => !reached.includes(name)).map((recipient) => ({ recipient, miss: \"partial\" as const }));\n}\n\n/** Misses grouped by recipient, most first. */\nexport function routeFailureRows(misses: readonly RouteMiss[]): RouteFailureRow[] {\n const rows = new Map<string, RouteFailureRow>();\n for (const m of misses) {\n const row = rows.get(m.recipient) ?? { recipient: m.recipient, failed: 0, partial: 0, queued: 0, first: m.at, last: m.at, lines: [] };\n rows.set(m.recipient, { ...row, [m.miss]: row[m.miss] + 1, last: m.at, lines: [...row.lines, m.line] });\n }\n const total = (r: RouteFailureRow) => r.failed + r.partial + r.queued;\n return [...rows.values()].sort((a, b) => total(b) - total(a) || a.recipient.localeCompare(b.recipient));\n}\n\nexport function countMisses(misses: readonly RouteMiss[]): Record<RouteMissKind, number> {\n return { failed: misses.filter((m) => m.miss === \"failed\").length, partial: misses.filter((m) => m.miss === \"partial\").length, queued: misses.filter((m) => m.miss === \"queued\").length };\n}\n","import { minutesBetween, stringField, type BrokerEntry } from \"./liveness-broker.js\";\nimport { countMisses, type RouteMiss } from \"./liveness-routes.js\";\n\n/** A seat off the broker for longer than this is dark; a teleport hand-off takes seconds. */\nexport const DARK_MIN = 5;\n\nconst TELEPORT_EVENTS = new Set([\"teleport_started\", \"teleport_completed\", \"teleport_failed\", \"teleport_aborted\"]);\n\n/** A name deregistered from the broker until it registered again, or until asOf if it never did, without exiting in between. */\nexport interface DarkGap {\n seat: string;\n from: string;\n to: string | null;\n minutes: number;\n /** A teleport of this name started after its last registration and before the gap closed. */\n teleport: boolean;\n /** Routes to the seat during the gap logged `delivered:false` and dropped. */\n failedRoutes: number;\n /** Routes during the gap that reached other recipients but not the seat. */\n partialRoutes: number;\n /** Routes the broker held or queued in the seat's inbox for delivery when it returned. */\n queuedRoutes: number;\n /** The deregistered and registered lines, then any teleport lines. */\n lines: number[];\n routeLines: number[];\n}\n\ninterface OpenGap {\n from: string;\n lines: number[];\n teleportLines: number[];\n}\n\ninterface SeatState {\n open: OpenGap | null;\n teleportLines: number[];\n /** A clean `agent_exited` since the last registration: a later one is a resume, not a dark seat. */\n exited: boolean;\n}\n\ntype ClosedGap = OpenGap & { seat: string; to: string | null; closeLine?: number };\n\n/** Gaps longer than DARK_MIN, skipping a clean exit and later resume; one still open at asOf counts only if a route missed the seat in it. */\nexport function darkGaps(entries: readonly BrokerEntry[], misses: readonly RouteMiss[], asOf: string): DarkGap[] {\n return gapsByLifecycle(entries, asOf)\n .filter((gap) => minutesBetween(gap.from, gap.to ?? asOf) > DARK_MIN)\n .map((gap) => toDarkGap(gap, misses, asOf))\n .filter((gap) => gap.to !== null || gap.failedRoutes + gap.partialRoutes + gap.queuedRoutes > 0)\n .sort((a, b) => a.from.localeCompare(b.from) || a.seat.localeCompare(b.seat));\n}\n\n/** Every deregistered-to-registered gap per seat, dropping one where the agent exited cleanly without a teleport. */\nfunction gapsByLifecycle(entries: readonly BrokerEntry[], asOf: string): ClosedGap[] {\n const states = new Map<string, SeatState>();\n const gaps: ClosedGap[] = [];\n const keep = (state: SeatState, gap: ClosedGap) => {\n if (!state.exited || gap.teleportLines.length > 0) gaps.push(gap);\n };\n for (const entry of entries) {\n const seat = stringField(entry, \"name\");\n if (seat === null || entry.ts >= asOf) continue;\n const state = states.get(seat) ?? { open: null, teleportLines: [], exited: false };\n states.set(seat, state);\n step(state, entry, (gap) => keep(state, { ...gap, seat, to: entry.ts, closeLine: entry.line }));\n }\n for (const [seat, state] of states) if (state.open) keep(state, { ...state.open, seat, to: null });\n return gaps;\n}\n\nfunction step(state: SeatState, entry: BrokerEntry, close: (gap: OpenGap) => void): void {\n if (entry.event === \"agent_exited\") {\n state.exited ||= exitedCleanly(entry);\n } else if (TELEPORT_EVENTS.has(entry.event)) {\n state.teleportLines.push(entry.line);\n state.open?.teleportLines.push(entry.line);\n } else if (entry.event === \"deregistered\" && !state.open) {\n state.open = { from: entry.ts, lines: [entry.line], teleportLines: [...state.teleportLines] };\n } else if (entry.event === \"registered\") {\n if (state.open) close(state.open);\n state.open = null;\n state.teleportLines = [];\n state.exited = false;\n }\n}\n\n/** Code 0 and not inferred, as agent-chat's exitedCleanly reads it; a crash or an inferred exit leaves the seat dark. */\nfunction exitedCleanly(entry: BrokerEntry): boolean {\n return entry.fields.code === 0 && entry.fields.inferred !== true;\n}\n\nfunction toDarkGap(gap: ClosedGap, misses: readonly RouteMiss[], asOf: string): DarkGap {\n const end = gap.to ?? asOf;\n const missed = misses.filter((m) => m.recipient === gap.seat && m.at >= gap.from && m.at < end);\n const counts = countMisses(missed);\n return {\n seat: gap.seat,\n from: gap.from,\n to: gap.to,\n minutes: minutesBetween(gap.from, end),\n teleport: gap.teleportLines.length > 0,\n failedRoutes: counts.failed,\n partialRoutes: counts.partial,\n queuedRoutes: counts.queued,\n lines: [...gap.lines, ...(gap.closeLine === undefined ? [] : [gap.closeLine]), ...gap.teleportLines],\n routeLines: missed.map((m) => m.line),\n };\n}\n","import { stringField, type BrokerEntry } from \"./liveness-broker.js\";\n\n/** An `agent_spawned` row of agent-chat's events table: the agent id and the profile it ran under. */\nexport interface SpawnRecord {\n eventId: number;\n agentId: string;\n name: string;\n profile: string | null;\n}\n\n/** An agent the broker saw exit without reporting to its spawner. */\nexport interface UnreportedExit {\n at: string;\n line: number;\n agentId: string;\n name: string;\n spawner: string;\n lastAction: string;\n /** The `agent_spawned` row the profile came from, or null when none matched the agent id. */\n spawnEventId: number | null;\n}\n\nexport interface UnreportedExitRow {\n profile: string;\n count: number;\n exits: UnreportedExit[];\n}\n\nexport const UNKNOWN_PROFILE = \"unknown\";\n\n/** Broker `unreported-exit` lines grouped by the profile the agent was spawned with, most first. */\nexport function unreportedExitRows(entries: readonly BrokerEntry[], spawns: readonly SpawnRecord[]): UnreportedExitRow[] {\n const byAgent = new Map(spawns.map((s) => [s.agentId, s]));\n const rows = new Map<string, UnreportedExit[]>();\n for (const entry of entries.filter((e) => e.event === \"unreported-exit\")) {\n const agentId = stringField(entry, \"agentId\") ?? \"\";\n const spawn = byAgent.get(agentId);\n const profile = spawn?.profile ?? UNKNOWN_PROFILE;\n const exit = {\n at: entry.ts,\n line: entry.line,\n agentId,\n name: stringField(entry, \"name\") ?? spawn?.name ?? \"\",\n spawner: stringField(entry, \"spawner\") ?? \"\",\n lastAction: stringField(entry, \"lastAction\") ?? \"\",\n spawnEventId: spawn?.eventId ?? null,\n };\n rows.set(profile, [...(rows.get(profile) ?? []), exit]);\n }\n return [...rows.entries()].map(([profile, exits]) => ({ profile, count: exits.length, exits })).sort((a, b) => b.count - a.count || a.profile.localeCompare(b.profile));\n}\n","import { minutesBetween, stringField, type BrokerEntry } from \"./liveness-broker.js\";\n\n/** A prompt this old with nothing after it from the agent is a hang, not a pause for the owner. */\nexport const PROMPT_STALE_MIN = 10;\n\n/** The newest events-table row an actor wrote before asOf. */\nexport interface LastEventRecord {\n eventId: number;\n at: string;\n actor: string;\n kind: string;\n /** `meta.tool_name` of an approval request. */\n tool: string | null;\n /** A `resolution` row whose `ref` is this request's msg_id, written before asOf. */\n resolutionEventId: number | null;\n /** An `agent_exited` or `agent_retired` row for this actor after the request and before asOf. */\n endEventId: number | null;\n}\n\nexport interface StalePromptRow {\n agent: string;\n at: string;\n ageMin: number;\n tool: string | null;\n eventId: number;\n resolutionEventId: number | null;\n}\n\n/** Live agents whose last event is an approval request older than PROMPT_STALE_MIN, oldest first; resolved ones included. */\nexport function stalePromptRows(lastEvents: readonly LastEventRecord[], broker: readonly BrokerEntry[], asOf: string): StalePromptRow[] {\n const gone = goneSinceRestart(broker, asOf);\n return lastEvents\n .filter((e) => e.kind === \"approval_request\" && e.at < asOf && e.endEventId === null && !gone(e))\n .map((e) => ({ agent: e.actor, at: e.at, ageMin: minutesBetween(e.at, asOf), tool: e.tool, eventId: e.eventId, resolutionEventId: e.resolutionEventId }))\n .filter((row) => row.ageMin > PROMPT_STALE_MIN)\n .sort((a, b) => b.ageMin - a.ageMin || a.agent.localeCompare(b.agent));\n}\n\n/** An agent that prompted before the broker's last restart and never registered after it is gone, not hung. */\nfunction goneSinceRestart(broker: readonly BrokerEntry[], asOf: string): (e: LastEventRecord) => boolean {\n const before = broker.filter((e) => e.ts < asOf);\n const restart = before.filter((e) => e.event === \"broker_started\").at(-1)?.ts;\n if (restart === undefined) return () => false;\n const live = new Set(before.filter((e) => e.event === \"registered\" && e.ts >= restart).map((e) => stringField(e, \"name\")));\n return (e) => e.at < restart && !live.has(e.actor);\n}\n","import { z } from \"zod\";\nimport { stringField, type BrokerEntry } from \"./liveness-broker.js\";\nimport { DARK_MIN, darkGaps } from \"./liveness-dark.js\";\nimport { unreportedExitRows, type SpawnRecord } from \"./liveness-exits.js\";\nimport { PROMPT_STALE_MIN, stalePromptRows, type LastEventRecord } from \"./liveness-prompts.js\";\nimport { countMisses, routeFailureRows, routeMisses } from \"./liveness-routes.js\";\nimport { LIST_PRICE_CAVEAT, table } from \"./render-text.js\";\n\n/** Where each section's findings come from: the command that re-reads them and the field it reads. */\nexport const LIVENESS_SOURCES = {\n registrations: {\n command: `grep -nE '\"event\":\"(registered|deregistered|agent_exited|teleport_started|teleport_completed|teleport_failed|teleport_aborted)\"' <broker.log>`,\n field: \"ts, event, name; cited as broker.log line numbers; a gap with a clean agent_exited (code 0, not inferred) and no teleport is a resume\",\n },\n routes: { command: `grep -n '\"event\":\"route\"' <broker.log>`, field: \"to, delivered, recipients\" },\n exits: { command: `grep -n '\"event\":\"unreported-exit\"' <broker.log>`, field: \"agentId, name, spawner, lastAction\" },\n spawns: {\n command: `sqlite3 -readonly <events.db> \"SELECT id, msg_id, target, json_extract(meta,'$.profile') FROM events WHERE kind='agent_spawned'\"`,\n field: \"events.msg_id (agent id), events.meta.profile\",\n },\n prompts: {\n command: `sqlite3 -readonly <events.db> \"SELECT e.* FROM events e JOIN (SELECT actor, max(id) id FROM events WHERE ts < <asOf> AND kind != 'resolution' GROUP BY actor) l ON e.id = l.id WHERE e.kind='approval_request'\"`,\n field: \"events.ts, events.actor, events.meta.tool_name; a resolution row's events.ref; skipped after the actor's agent_exited or agent_retired, or a broker_started it never re-registered after\",\n },\n} as const;\n\nexport type LivenessSource = keyof typeof LIVENESS_SOURCES;\n\nexport interface LivenessInput {\n broker: readonly BrokerEntry[];\n spawns: readonly SpawnRecord[];\n lastEvents: readonly LastEventRecord[];\n /** Gaps still open and prompt ages are measured to here; later entries are ignored. */\n asOf: string;\n /** A finding is kept when it starts inside the window; a prompt from a live agent still unanswered at asOf is kept however old. */\n window?: { since?: string; until?: string };\n /** Keeps only findings about these names: the dark seat, route recipient, exiting agent or its spawner, prompting agent. */\n seats?: readonly string[];\n}\n\nconst source = z.enum([\"registrations\", \"routes\", \"exits\", \"spawns\", \"prompts\"]);\nconst count = z.number().int().nonnegative();\nconst lines = z.array(count);\n\nconst darkRow = z.object({\n seat: z.string(),\n from: z.string(),\n to: z.string().nullable(),\n minutes: z.number(),\n teleport: z.boolean(),\n failedRoutes: count,\n partialRoutes: count,\n queuedRoutes: count,\n lines,\n routeLines: lines,\n});\n\nconst exitRow = z.object({ at: z.string(), line: count, agentId: z.string(), name: z.string(), spawner: z.string(), lastAction: z.string(), spawnEventId: count.nullable() });\n\nconst promptRow = z.object({ agent: z.string(), at: z.string(), ageMin: z.number(), tool: z.string().nullable(), eventId: count, resolutionEventId: count.nullable() });\n\nexport const livenessSchema = z.object({\n asOf: z.string(),\n window: z.object({ since: z.string().optional(), until: z.string().optional() }),\n thresholds: z.object({ darkMin: z.number(), promptStaleMin: z.number() }),\n sources: z.record(source, z.object({ command: z.string(), field: z.string() })),\n darkSeats: z.object({ cites: z.array(source), withTeleport: count, withoutTeleport: count, rows: z.array(darkRow) }),\n routeFailures: z.object({\n cites: z.array(source),\n failed: count,\n partial: count,\n queued: count,\n rows: z.array(z.object({ recipient: z.string(), failed: count, partial: count, queued: count, first: z.string(), last: z.string(), lines })),\n }),\n unreportedExits: z.object({ cites: z.array(source), total: count, rows: z.array(z.object({ profile: z.string(), count, exits: z.array(exitRow) })) }),\n stalePrompts: z.object({ cites: z.array(source), rows: z.array(promptRow), resolvedRows: z.array(promptRow) }),\n});\n\nexport type LivenessReport = z.infer<typeof livenessSchema>;\n\n/** Seats dark past DARK_MIN, routes that missed their recipient, unreported exits and agents stuck on a prompt. */\nexport function livenessReport(input: LivenessInput): LivenessReport {\n const window = input.window ?? {};\n const keep = scopeTest(input.seats, window);\n const broker = input.broker.filter((e) => e.ts < input.asOf);\n const misses = routeMisses(broker);\n const dark = darkGaps(broker, misses, input.asOf).filter((g) => keep([g.seat], g.from));\n const routeMissesInScope = misses.filter((m) => keep([m.recipient], m.at));\n const routes = routeFailureRows(routeMissesInScope);\n const prompts = stalePromptRows(input.lastEvents, broker, input.asOf).filter((p) => !input.seats || input.seats.includes(p.agent));\n const exits = unreportedExitRows(broker.filter((e) => keep([stringField(e, \"name\") ?? \"\", stringField(e, \"spawner\") ?? \"\"], e.ts)), input.spawns);\n return {\n asOf: input.asOf,\n window,\n thresholds: { darkMin: DARK_MIN, promptStaleMin: PROMPT_STALE_MIN },\n sources: LIVENESS_SOURCES,\n darkSeats: { cites: [\"registrations\", \"routes\"], withTeleport: dark.filter((g) => g.teleport).length, withoutTeleport: dark.filter((g) => !g.teleport).length, rows: dark },\n routeFailures: { cites: [\"routes\"], ...countMisses(routeMissesInScope), rows: routes },\n unreportedExits: { cites: [\"exits\", \"spawns\"], total: sum(exits.map((r) => r.count)), rows: exits },\n stalePrompts: { cites: [\"prompts\"], rows: prompts.filter((p) => p.resolutionEventId === null), resolvedRows: prompts.filter((p) => p.resolutionEventId !== null) },\n };\n}\n\nfunction scopeTest(seats: readonly string[] | undefined, window: { since?: string; until?: string }) {\n const named = seats ? new Set(seats) : null;\n return (names: readonly string[], at: string): boolean =>\n (!named || names.some((n) => named.has(n))) && (!window.since || at >= window.since) && (!window.until || at < window.until);\n}\n\nfunction sum(values: readonly number[]): number {\n return values.reduce((total, v) => total + v, 0);\n}\n\nconst CITED_LINES = 4;\n\n/** Up to CITED_LINES line numbers, then how many more the JSON carries. */\nfunction cite(prefix: string, ids: readonly number[]): string {\n if (ids.length === 0) return \"-\";\n const shown = ids.slice(0, CITED_LINES).map((id) => `${prefix}${id}`).join(\",\");\n return ids.length > CITED_LINES ? `${shown} +${ids.length - CITED_LINES}` : shown;\n}\n\n/** Each table's title names the JSON field its rows come from; the sources and the shared caveat close the report. */\nexport function renderLivenessText(report: LivenessReport): string {\n const scope = `Liveness as of ${report.asOf}${report.window.since ? `, since ${report.window.since}` : \"\"}${report.window.until ? `, until ${report.window.until}` : \"\"}`;\n const sources = [\"Sources\", ...Object.entries(report.sources).map(([name, s]) => `${name}: ${s.command} (${s.field})`)].join(\"\\n\");\n return [scope, darkTable(report), routeTable(report), exitTable(report), promptTable(report), sources, LIST_PRICE_CAVEAT].join(\"\\n\\n\") + \"\\n\";\n}\n\nfunction darkTable(report: LivenessReport): string {\n const { rows, withTeleport, withoutTeleport } = report.darkSeats;\n const cells = rows.map((r) => [r.seat, r.from, r.to ?? \"still dark\", r.minutes, r.teleport ? \"yes\" : \"no\", r.failedRoutes, r.partialRoutes, r.queuedRoutes, cite(\"broker.log:\", [...r.lines, ...r.routeLines])]);\n const title = `Seats dark over ${report.thresholds.darkMin} min, ${withTeleport} with a teleport and ${withoutTeleport} without [darkSeats.rows[]]`;\n return table(title, [\"seat\", \"from\", \"to\", \"min\", \"teleport\", \"failed routes\", \"partial routes\", \"queued routes\", \"cites\"], cells);\n}\n\nfunction routeTable(report: LivenessReport): string {\n const { rows, failed, partial, queued } = report.routeFailures;\n const cells = rows.map((r) => [r.recipient, r.failed, r.partial, r.queued, r.first, r.last, cite(\"broker.log:\", r.lines)]);\n const title = `Routes that missed a recipient, ${failed} dropped, ${partial} partial and ${queued} held or queued for later [routeFailures.rows[]]`;\n return table(title, [\"recipient\", \"failed\", \"partial\", \"queued\", \"first\", \"last\", \"cites\"], cells);\n}\n\nfunction exitTable(report: LivenessReport): string {\n const cells = report.unreportedExits.rows.flatMap((r) => r.exits.map((e) => [r.profile, e.name, e.spawner, e.lastAction, e.at, cite(\"broker.log:\", [e.line]), e.spawnEventId === null ? \"-\" : `events#${e.spawnEventId}`]));\n const title = `Unreported exits by profile, ${report.unreportedExits.total} in all [unreportedExits.rows[].exits[]]`;\n return table(title, [\"profile\", \"agent\", \"spawner\", \"last action\", \"at\", \"exit\", \"spawn\"], cells);\n}\n\nfunction promptTable(report: LivenessReport): string {\n const cells = (rows: LivenessReport[\"stalePrompts\"][\"rows\"]) => rows.map((r) => [r.agent, r.tool ?? \"-\", r.at, r.ageMin, `events#${r.eventId}`, r.resolutionEventId === null ? \"-\" : `events#${r.resolutionEventId}`]);\n const head = [\"agent\", \"tool\", \"at\", \"age min\", \"prompt\", \"resolution\"];\n const over = `over ${report.thresholds.promptStaleMin} min old`;\n return [\n table(`Agents whose last event is an unresolved permission prompt ${over} [stalePrompts.rows[]]`, head, cells(report.stalePrompts.rows)),\n table(`Agents silent since a resolved permission prompt ${over} [stalePrompts.resolvedRows[]]`, head, cells(report.stalePrompts.resolvedRows)),\n ].join(\"\\n\\n\");\n}\n","import type { ToolFamily } from \"@titan-design/session-read\";\n\n/** Bump when a field is removed or changes meaning. Adding a field keeps the version. */\nexport const SESSION_TIMELINE_VERSION = 1;\n\n/** Idle time between two events that counts as a gap. */\nexport const TIMELINE_GAP_MIN_MS = 10 * 60_000;\n\n/** Default cap on each message text. The byte offset still points at the full record. */\nexport const TIMELINE_TEXT_CAP = 4_000;\n\n/** `prompt` is typed or sent text, `injected` is a harness block, `compaction` is a continuation summary, `none` is activity before any user message. */\nexport type TimelineTurnOrigin = \"prompt\" | \"injected\" | \"compaction\" | \"none\";\n\n/** `unknown` is a result whose source did not report an error state; `pending` has no result yet. */\nexport type TimelineToolOutcome = \"success\" | \"error\" | \"unknown\" | \"pending\";\n\nexport interface TimelineMessage {\n role: \"user\" | \"assistant\";\n /** Source order across the whole session; sort a turn's messages and tool calls by it to interleave them. */\n seq: number;\n atMs: number | null;\n text: string;\n /** True when `text` was cut at the cap. */\n truncated: boolean;\n /** Offset of the transcript line, for reading the full record. */\n byteOffset: number;\n}\n\nexport interface TimelineToolCall {\n /** The harness's own call id, unique within the session. */\n id: string;\n seq: number;\n turnIndex: number;\n name: string;\n family: ToolFamily;\n atMs: number | null;\n /** When the result arrived; null while pending. */\n endMs: number | null;\n /** Observed call-to-result span, not harness execution time. */\n durationMs: number | null;\n outcome: TimelineToolOutcome;\n errorMessage: string | null;\n /** One line naming what the call acted on: a path, a command, a pattern or a description. */\n inputSummary: string;\n filePath: string | null;\n sidechain: boolean;\n byteOffset: number;\n}\n\n/** Prompt-side counts are disjoint: `input` excludes cache reads and cache writes. */\nexport interface TimelineTokens {\n input: number;\n cacheRead: number;\n /** All cache writes, `cacheWrite5m + cacheWrite1h`. */\n cacheWrite: number;\n /** Writes at the 5m rate, including a total the source reported without a split. */\n cacheWrite5m: number;\n /** Writes at the 1h rate. */\n cacheWrite1h: number;\n output: number;\n}\n\nexport interface TimelineTurn {\n index: number;\n origin: TimelineTurnOrigin;\n /** The session-read injected-marker name when `origin` is `injected` or `compaction`. */\n injectedMarker: string | null;\n startMs: number | null;\n endMs: number | null;\n /** Idle time before this turn when it is `TIMELINE_GAP_MIN_MS` or more, else null. */\n gapBeforeMs: number | null;\n /** The message that opened the turn; null when `origin` is `none`. */\n user: TimelineMessage | null;\n assistant: TimelineMessage[];\n toolCalls: TimelineToolCall[];\n errorCount: number;\n tokens: TimelineTokens;\n costUsd: number;\n}\n\n/** One UTC clock minute that held activity. Minutes with none are omitted. */\nexport interface TimelineMinuteBucket {\n /** Start of the minute. */\n minuteMs: number;\n /** Messages, tool calls and tool results. */\n events: number;\n messages: number;\n toolCalls: number;\n errors: number;\n outputTokens: number;\n costUsd: number;\n /** Set on the first bucket after a gap. */\n gapBeforeMs: number | null;\n}\n\n/** An idle stretch. Time spent waiting on a tool call that later returned is not idle, so it is never a gap. */\nexport interface TimelineGap {\n startMs: number;\n endMs: number;\n durationMs: number;\n}\n\n/** One API request. Points are in source order and cumulative fields run over that order. */\nexport interface TimelineTokenPoint {\n atMs: number;\n turnIndex: number | null;\n model: string | null;\n /** The prompt size of this request: input plus cache read plus cache write. Null when the source omitted a count. */\n contextTokens: number | null;\n outputTokens: number;\n cumulativeOutputTokens: number;\n costUsd: number;\n cumulativeCostUsd: number;\n /** False when no price row covers the model; `costUsd` is then 0. */\n priced: boolean;\n /** True on the first request after a compaction. */\n afterCompaction: boolean;\n}\n\nexport interface CompactionMark {\n atMs: number | null;\n turnIndex: number | null;\n byteOffset: number;\n summary: string | null;\n summaryTruncated: boolean;\n}\n\nexport interface ModelRequests {\n model: string;\n requests: number;\n}\n\nexport interface TokenTimeline {\n /** `delta` has per-request points. A `snapshot` source reports running totals only: `points` is empty and nothing is priced, so every `costUsd` is 0. */\n basis: \"delta\" | \"snapshot\" | \"unreported\";\n points: TimelineTokenPoint[];\n compactions: CompactionMark[];\n /** Most requests first. */\n models: ModelRequests[];\n}\n\nexport interface ToolNameCount {\n name: string;\n family: ToolFamily;\n calls: number;\n errors: number;\n durationMs: number;\n}\n\nexport interface ToolFamilyCount {\n family: ToolFamily;\n calls: number;\n errors: number;\n /** Call start times, ascending, for `countAtOrBefore`. */\n atMs: number[];\n}\n\nexport interface TimelineToolBreakdown {\n /** Most calls first. */\n byName: ToolNameCount[];\n byFamily: ToolFamilyCount[];\n /** Every call start time, ascending. */\n atMs: number[];\n}\n\nexport interface TimelineFileTouch {\n path: string;\n access: \"read\" | \"write\";\n /** First touch of this path with this access. */\n atMs: number | null;\n calls: number;\n}\n\nexport interface TimelineFileBreakdown {\n /** One row per path and access, ordered by first touch. */\n touches: TimelineFileTouch[];\n readCount: number;\n writeCount: number;\n}\n\nexport interface TimelineError {\n callId: string;\n toolName: string;\n turnIndex: number;\n /** When the failing result arrived. */\n atMs: number | null;\n message: string;\n sidechain: boolean;\n}\n\nexport interface TimelineErrorBreakdown {\n /** Failed calls over all calls; 0 with no calls. */\n rate: number;\n items: TimelineError[];\n atMs: number[];\n}\n\n/** A subagent dispatch, from its tool call to that call's result. */\nexport interface TimelineAgentSpan {\n callId: string;\n label: string;\n startMs: number | null;\n endMs: number | null;\n outcome: TimelineToolOutcome;\n}\n\nexport interface TimelineTotals {\n turns: number;\n userMessages: number;\n assistantMessages: number;\n toolCalls: number;\n errors: number;\n compactions: number;\n /** API requests with usage. Null on a `snapshot` basis, which cannot count them. */\n requests: number | null;\n unpricedRequests: number;\n tokens: TimelineTokens;\n /** 0 on a `snapshot` basis, which has no per-request usage to price. */\n costUsd: number;\n}\n\n/**\n * Everything a session view reads, as plain JSON. Every `*Ms` field is epoch milliseconds,\n * so the model holds no time zone and a renderer picks one.\n */\nexport interface SessionTimeline {\n version: typeof SESSION_TIMELINE_VERSION;\n sessionId: string | null;\n harness: string | null;\n startMs: number | null;\n endMs: number | null;\n durationMs: number;\n totals: TimelineTotals;\n turns: TimelineTurn[];\n buckets: TimelineMinuteBucket[];\n gaps: TimelineGap[];\n tokens: TokenTimeline;\n tools: TimelineToolBreakdown;\n files: TimelineFileBreakdown;\n errors: TimelineErrorBreakdown;\n agents: TimelineAgentSpan[];\n}\n","import type { ToolFamily } from \"@titan-design/session-read\";\nimport type {\n TimelineAgentSpan,\n TimelineErrorBreakdown,\n TimelineFileBreakdown,\n TimelineFileTouch,\n TimelineToolBreakdown,\n TimelineToolCall,\n ToolFamilyCount,\n ToolNameCount,\n} from \"./timeline-types.js\";\n\nconst WRITE_TOOLS = new Set([\"Edit\", \"Write\", \"MultiEdit\", \"NotebookEdit\"]);\n\nfunction ascending(times: readonly (number | null)[]): number[] {\n return times.filter((time): time is number => time !== null).sort((a, b) => a - b);\n}\n\nexport function toolBreakdown(calls: readonly TimelineToolCall[]): TimelineToolBreakdown {\n const byName = new Map<string, ToolNameCount>();\n const byFamily = new Map<ToolFamily, ToolFamilyCount>();\n for (const call of calls) {\n const failed = call.outcome === \"error\" ? 1 : 0;\n const name = byName.get(call.name) ?? { name: call.name, family: call.family, calls: 0, errors: 0, durationMs: 0 };\n name.calls++;\n name.errors += failed;\n name.durationMs += call.durationMs ?? 0;\n byName.set(call.name, name);\n const family = byFamily.get(call.family) ?? { family: call.family, calls: 0, errors: 0, atMs: [] };\n family.calls++;\n family.errors += failed;\n if (call.atMs !== null) family.atMs.push(call.atMs);\n byFamily.set(call.family, family);\n }\n for (const family of byFamily.values()) family.atMs.sort((a, b) => a - b);\n return {\n byName: [...byName.values()].sort((a, b) => b.calls - a.calls || a.name.localeCompare(b.name)),\n byFamily: [...byFamily.values()].sort((a, b) => b.calls - a.calls || a.family.localeCompare(b.family)),\n atMs: ascending(calls.map((call) => call.atMs)),\n };\n}\n\n/** A call with a path counts as a write for the editing tools and as a read for every other tool. */\nexport function fileBreakdown(calls: readonly TimelineToolCall[]): TimelineFileBreakdown {\n const touches = new Map<string, TimelineFileTouch>();\n for (const call of calls) {\n if (!call.filePath) continue;\n const access = WRITE_TOOLS.has(call.name) ? \"write\" : \"read\";\n const key = `${access}:${call.filePath}`;\n const touch = touches.get(key) ?? { path: call.filePath, access, atMs: call.atMs, calls: 0 };\n touch.calls++;\n touches.set(key, touch);\n }\n const rows = [...touches.values()].sort((a, b) => (a.atMs ?? Infinity) - (b.atMs ?? Infinity));\n return {\n touches: rows,\n readCount: rows.filter((row) => row.access === \"read\").length,\n writeCount: rows.filter((row) => row.access === \"write\").length,\n };\n}\n\nexport function errorBreakdown(calls: readonly TimelineToolCall[]): TimelineErrorBreakdown {\n const items = calls\n .filter((call) => call.outcome === \"error\")\n .map((call) => ({\n callId: call.id,\n toolName: call.name,\n turnIndex: call.turnIndex,\n atMs: call.endMs ?? call.atMs,\n message: call.errorMessage ?? \"\",\n sidechain: call.sidechain,\n }));\n return { rate: calls.length > 0 ? items.length / calls.length : 0, items, atMs: ascending(items.map((item) => item.atMs)) };\n}\n\n/** Each subagent dispatch, labelled by the description its input carries. */\nexport function agentSpans(calls: readonly TimelineToolCall[]): TimelineAgentSpan[] {\n return calls\n .filter((call) => call.family === \"subagent\")\n .map((call) => ({ callId: call.id, label: call.inputSummary || call.name, startMs: call.atMs, endMs: call.endMs, outcome: call.outcome }));\n}\n","import type { TimelineMinuteBucket, TimelineGap, TimelineToolCall, TimelineTurn, TimelineTokenPoint } from \"./timeline-types.js\";\n\nconst MINUTE_MS = 60_000;\n\nexport interface BucketInput {\n turns: readonly TimelineTurn[];\n calls: readonly TimelineToolCall[];\n points: readonly TimelineTokenPoint[];\n}\n\n/** Every timed message, tool call, tool result and request, ascending. */\nexport function activityTimes(input: BucketInput): number[] {\n const times: (number | null)[] = input.points.map((point) => point.atMs);\n for (const turn of input.turns) {\n times.push(turn.user?.atMs ?? null, ...turn.assistant.map((message) => message.atMs));\n }\n for (const call of input.calls) times.push(call.atMs, call.endMs);\n return times.filter((time): time is number => time !== null).sort((a, b) => a - b);\n}\n\n/** A quiet stretch covered by a tool call that later returned is work in flight, not a gap. */\nexport function findGaps(sortedMs: readonly number[], gapMinMs: number, calls: readonly TimelineToolCall[]): TimelineGap[] {\n const gaps: TimelineGap[] = [];\n for (let i = 1; i < sortedMs.length; i++) {\n const startMs = sortedMs[i - 1] as number;\n const endMs = sortedMs[i] as number;\n if (endMs - startMs < gapMinMs || calls.some((call) => inFlightAcross(call, startMs, endMs))) continue;\n gaps.push({ startMs, endMs, durationMs: endMs - startMs });\n }\n return gaps;\n}\n\nfunction inFlightAcross(call: TimelineToolCall, startMs: number, endMs: number): boolean {\n return call.atMs !== null && call.endMs !== null && call.atMs <= startMs && call.endMs >= endMs;\n}\n\n/**\n * Buckets by epoch minute. Every real zone offset is a whole number of minutes, so an epoch\n * minute is a clock minute in any zone and a session that crosses midnight needs no date math.\n */\nexport function minuteBuckets(input: BucketInput, gaps: readonly TimelineGap[]): TimelineMinuteBucket[] {\n const buckets = new Map<number, TimelineMinuteBucket>();\n const at = (ms: number) => bucketAt(buckets, ms);\n for (const turn of input.turns) {\n for (const message of [turn.user, ...turn.assistant]) {\n if (message?.atMs != null) countEvent(at(message.atMs), \"messages\");\n }\n }\n for (const call of input.calls) countCall(call, at);\n for (const point of input.points) {\n const bucket = at(point.atMs);\n bucket.outputTokens += point.outputTokens;\n bucket.costUsd += point.costUsd;\n }\n for (const gap of gaps) at(gap.endMs).gapBeforeMs = gap.durationMs;\n return [...buckets.values()].sort((a, b) => a.minuteMs - b.minuteMs);\n}\n\n/** Marks each turn that opens after an idle stretch, measured from the previous turn's last event. */\nexport function markTurnGaps(turns: readonly TimelineTurn[], gapMinMs: number): void {\n let previousEndMs: number | null = null;\n for (const turn of turns) {\n const idleMs = previousEndMs !== null && turn.startMs !== null ? turn.startMs - previousEndMs : 0;\n turn.gapBeforeMs = idleMs >= gapMinMs ? idleMs : null;\n previousEndMs = turn.endMs ?? previousEndMs;\n }\n}\n\nfunction bucketAt(buckets: Map<number, TimelineMinuteBucket>, ms: number): TimelineMinuteBucket {\n const minuteMs = Math.floor(ms / MINUTE_MS) * MINUTE_MS;\n let bucket = buckets.get(minuteMs);\n if (!bucket) {\n bucket = { minuteMs, events: 0, messages: 0, toolCalls: 0, errors: 0, outputTokens: 0, costUsd: 0, gapBeforeMs: null };\n buckets.set(minuteMs, bucket);\n }\n return bucket;\n}\n\nfunction countEvent(bucket: TimelineMinuteBucket, field: \"messages\" | \"toolCalls\" | null): void {\n bucket.events++;\n if (field) bucket[field]++;\n}\n\nfunction countCall(call: TimelineToolCall, at: (ms: number) => TimelineMinuteBucket): void {\n if (call.atMs !== null) countEvent(at(call.atMs), \"toolCalls\");\n if (call.endMs !== null) countEvent(at(call.endMs), null);\n const errorMs = call.endMs ?? call.atMs;\n if (call.outcome === \"error\" && errorMs !== null) at(errorMs).errors++;\n}\n","import type { TokenCounts, UsageMeasurement } from \"@titan-design/agent-protocol\";\nimport { foldUsage } from \"@titan-design/agent-protocol\";\nimport type { CacheWriteSplit, NormalizedObservationOf } from \"@titan-design/session-read\";\nimport type { PriceRow } from \"./prices.js\";\nimport { priceRequest } from \"./price-request.js\";\nimport type { CompactionMark, ModelRequests, TimelineTokens, TimelineTokenPoint, TokenTimeline } from \"./timeline-types.js\";\nimport { capText } from \"./timeline-turns.js\";\n\ntype Snapshot = Extract<UsageMeasurement, { kind: \"snapshot\" }>;\n\n/** One deduplicated API request, before the cumulative pass. */\nexport interface TokenRequest {\n atMs: number | null;\n turnIndex: number | null;\n model: string | null;\n contextTokens: number | null;\n tokens: TimelineTokens;\n costUsd: number;\n priced: boolean;\n afterCompaction: boolean;\n}\n\nexport interface TokenFoldResult {\n timeline: TokenTimeline;\n /** Every request, timed or not; empty on a snapshot basis. */\n requests: TokenRequest[];\n /** Null when the basis cannot count requests. */\n requestCount: number | null;\n tokens: TimelineTokens;\n}\n\nexport function emptyTokens(): TimelineTokens {\n return { input: 0, cacheRead: 0, cacheWrite: 0, cacheWrite5m: 0, cacheWrite1h: 0, output: 0 };\n}\n\nexport function addTokens(into: TimelineTokens, from: TimelineTokens): void {\n into.input += from.input;\n into.cacheRead += from.cacheRead;\n into.cacheWrite += from.cacheWrite;\n into.cacheWrite5m += from.cacheWrite5m;\n into.cacheWrite1h += from.cacheWrite1h;\n into.output += from.output;\n}\n\n/** Folds usage and compaction observations into the token series. */\nexport class TokenFold {\n readonly compactions: CompactionMark[] = [];\n private readonly requests = new Map<string, TokenRequest>();\n private readonly snapshots: Snapshot[] = [];\n private compactedSinceRequest = false;\n\n constructor(\n private readonly maxTextChars: number,\n private readonly prices: readonly PriceRow[] | undefined,\n ) {}\n\n usage(observation: NormalizedObservationOf<\"usage\">, atMs: number | null, turnIndex: number | null): void {\n const { measurement } = observation;\n if (measurement.kind === \"snapshot\") {\n this.snapshots.push(measurement);\n return;\n }\n // A response written over several lines repeats its usage; the last line holds the final counts.\n const held = this.requests.get(measurement.responseId);\n const tokens = disjointTokens(measurement.tokens, \"cacheWriteSplit\" in observation ? observation.cacheWriteSplit : undefined);\n const priced = priceRequest(priceInput(tokens), measurement.model ?? \"\", isoOf(held ? held.atMs : atMs), this.prices);\n this.requests.set(measurement.responseId, {\n atMs: held ? held.atMs : atMs,\n turnIndex: held ? held.turnIndex : turnIndex,\n model: measurement.model,\n contextTokens: measurement.tokens.input,\n tokens,\n costUsd: priced.costUsd,\n priced: priced.priced,\n afterCompaction: held ? held.afterCompaction : this.takeCompactionFlag(),\n });\n }\n\n /**\n * Claude Code writes one compaction as a boundary line and then a summary line, and the\n * decoder reports both. The second joins the first: the mark keeps the boundary's time and gains the summary.\n */\n compaction(observation: NormalizedObservationOf<\"compaction\">, atMs: number | null, turnIndex: number | null): void {\n const summary = observation.nativeExtensions?.find((entry) => entry.name === \"compactionSummary\")?.value;\n const capped = typeof summary === \"string\" ? capText(summary, this.maxTextChars) : null;\n const open = this.compactedSinceRequest ? this.compactions.at(-1) : undefined;\n if (open && open.summary === null) {\n open.summary = capped?.text ?? null;\n open.summaryTruncated = capped?.truncated ?? false;\n return;\n }\n this.compactions.push({\n atMs,\n turnIndex,\n byteOffset: observation.evidence.line.byteOffset,\n summary: capped?.text ?? null,\n summaryTruncated: capped?.truncated ?? false,\n });\n this.compactedSinceRequest = true;\n }\n\n result(): TokenFoldResult {\n const requests = [...this.requests.values()];\n const basis = requests.length > 0 ? \"delta\" : this.snapshots.length > 0 ? \"snapshot\" : \"unreported\";\n const timeline: TokenTimeline = { basis, points: cumulativePoints(requests), compactions: this.compactions, models: modelCounts(requests) };\n if (basis === \"snapshot\") return { timeline, requests, requestCount: null, tokens: snapshotTokens(this.snapshots) };\n const tokens = emptyTokens();\n for (const request of requests) addTokens(tokens, request.tokens);\n return { timeline, requests, requestCount: requests.length, tokens };\n }\n\n private takeCompactionFlag(): boolean {\n const flag = this.compactedSinceRequest;\n this.compactedSinceRequest = false;\n return flag;\n }\n}\n\n/** Both decoders report `input` as the whole prompt, so cache reads and writes come out of it. */\nfunction disjointTokens(counts: TokenCounts, split?: CacheWriteSplit): TimelineTokens {\n const cacheRead = counts.cachedInput ?? 0;\n const cacheWrite = counts.cacheWriteInput ?? 0;\n const input = Math.max(0, (counts.input ?? 0) - cacheRead - cacheWrite);\n return { input, cacheRead, cacheWrite, ...cacheWriteByTtl(cacheWrite, split), output: counts.output ?? 0 };\n}\n\n/** A total with no usable split is all 5m, the harness default; costReport's request view uses the same rule. */\nfunction cacheWriteByTtl(total: number, split: CacheWriteSplit | undefined): Pick<TimelineTokens, \"cacheWrite5m\" | \"cacheWrite1h\"> {\n if (split && split.ttl5m + split.ttl1h > 0) return { cacheWrite5m: split.ttl5m, cacheWrite1h: split.ttl1h };\n return { cacheWrite5m: total, cacheWrite1h: 0 };\n}\n\nfunction priceInput(tokens: TimelineTokens) {\n return {\n inputTokens: tokens.input,\n cacheReadTokens: tokens.cacheRead,\n cacheCreation5mTokens: tokens.cacheWrite5m,\n cacheCreation1hTokens: tokens.cacheWrite1h,\n outputTokens: tokens.output,\n };\n}\n\nfunction isoOf(atMs: number | null): string {\n return atMs === null ? \"\" : new Date(atMs).toISOString();\n}\n\nfunction cumulativePoints(requests: readonly TokenRequest[]): TimelineTokenPoint[] {\n const points: TimelineTokenPoint[] = [];\n let cumulativeOutputTokens = 0;\n let cumulativeCostUsd = 0;\n for (const request of requests) {\n cumulativeOutputTokens += request.tokens.output;\n cumulativeCostUsd += request.costUsd;\n if (request.atMs === null) continue;\n const { atMs, turnIndex, model, contextTokens, costUsd, priced, afterCompaction } = request;\n points.push({ atMs, turnIndex, model, contextTokens, outputTokens: request.tokens.output, cumulativeOutputTokens, costUsd, cumulativeCostUsd, priced, afterCompaction });\n }\n return points;\n}\n\nfunction modelCounts(requests: readonly TokenRequest[]): ModelRequests[] {\n const counts = new Map<string, number>();\n for (const request of requests) {\n if (request.model) counts.set(request.model, (counts.get(request.model) ?? 0) + 1);\n }\n return [...counts]\n .map(([model, count]) => ({ model, requests: count }))\n .sort((a, b) => b.requests - a.requests || a.model.localeCompare(b.model));\n}\n\nfunction snapshotTokens(snapshots: readonly Snapshot[]): TimelineTokens {\n const tokens = emptyTokens();\n for (const measurement of foldUsage(snapshots).measurements) addTokens(tokens, disjointTokens(measurement.tokens));\n return tokens;\n}\n","import type { NormalizedObservationOf, NormalizedSessionObservation } from \"@titan-design/session-read\";\nimport { findInjectedMarker, toolFamily } from \"@titan-design/session-read\";\nimport type { TimelineMessage, TimelineToolCall, TimelineToolOutcome, TimelineTurn, TimelineTurnOrigin } from \"./timeline-types.js\";\n\nconst ERROR_TEXT_CAP = 500;\nconst SUMMARY_CAP = 160;\nconst SUMMARY_KEYS = [\"command\", \"pattern\", \"description\", \"query\", \"url\", \"prompt\"] as const;\nconst PATH_KEYS = [\"file_path\", \"notebook_path\", \"path\"] as const;\n\nexport interface CappedText {\n text: string;\n truncated: boolean;\n}\n\nexport function capText(text: string, cap: number): CappedText {\n return text.length <= cap ? { text, truncated: false } : { text: text.slice(0, cap), truncated: true };\n}\n\nexport function isSidechain(observation: NormalizedSessionObservation): boolean {\n return observation.nativeExtensions?.some((entry) => entry.name === \"isSidechain\" && entry.value === true) ?? false;\n}\n\n/** Groups messages and tool calls into turns: a user message opens one, and it runs to the next. */\nexport class TurnFold {\n readonly turns: TimelineTurn[] = [];\n readonly calls: TimelineToolCall[] = [];\n private readonly callsById = new Map<string, TimelineToolCall>();\n private readonly seenMessages = new Set<string>();\n private seq = 0;\n\n constructor(private readonly maxTextChars: number) {}\n\n currentIndex(): number | null {\n return this.turns.length > 0 ? this.turns.length - 1 : null;\n }\n\n message(observation: NormalizedObservationOf<\"message\">, atMs: number | null): void {\n // A subagent's inlined dialogue belongs to its own transcript, not to this session's turns.\n if (isSidechain(observation) || this.isRepeat(observation)) return;\n const raw = observation.content.map((part) => part.text).join(\"\\n\");\n const message: TimelineMessage = {\n role: observation.role,\n seq: this.seq++,\n atMs,\n ...capText(raw, this.maxTextChars),\n byteOffset: observation.evidence.line.byteOffset,\n };\n if (observation.role === \"user\") this.open(message, raw);\n else touch(this.current(atMs), atMs).assistant.push(message);\n }\n\n toolCall(observation: NormalizedObservationOf<\"tool_call\">, atMs: number | null): void {\n const turn = touch(this.current(atMs), atMs);\n const call: TimelineToolCall = {\n id: observation.call.nativeId,\n seq: this.seq++,\n turnIndex: turn.index,\n name: observation.name,\n family: toolFamily(observation.name).family,\n atMs,\n endMs: null,\n durationMs: null,\n outcome: \"pending\",\n errorMessage: null,\n inputSummary: inputSummary(observation.input),\n filePath: firstString(observation.input, PATH_KEYS),\n sidechain: isSidechain(observation),\n byteOffset: observation.evidence.line.byteOffset,\n };\n turn.toolCalls.push(call);\n this.calls.push(call);\n this.callsById.set(call.id, call);\n }\n\n /** A result whose call was never seen, as in a resumed slice, is dropped. */\n toolResult(observation: NormalizedObservationOf<\"tool_result\">, atMs: number | null): void {\n const call = this.callsById.get(observation.call.nativeId);\n const turn = call ? this.turns[call.turnIndex] : undefined;\n if (!call || !turn) return;\n call.endMs = atMs;\n call.durationMs = span(call.atMs, atMs);\n call.outcome = outcomeOf(observation.isError);\n touch(turn, atMs);\n if (call.outcome !== \"error\") return;\n call.errorMessage = capText(outputText(observation.output), ERROR_TEXT_CAP).text;\n turn.errorCount++;\n }\n\n private isRepeat(observation: NormalizedObservationOf<\"message\">): boolean {\n const key = observation.item?.nativeId;\n if (!key) return false;\n if (this.seenMessages.has(key)) return true;\n this.seenMessages.add(key);\n return false;\n }\n\n private open(user: TimelineMessage, raw: string): void {\n const marker = findInjectedMarker(raw);\n this.turns.push({ ...emptyTurn(this.turns.length, originOf(marker), user.atMs), injectedMarker: marker, user });\n }\n\n private current(atMs: number | null): TimelineTurn {\n const last = this.turns[this.turns.length - 1];\n if (last) return last;\n const turn = emptyTurn(0, \"none\", atMs);\n this.turns.push(turn);\n return turn;\n }\n}\n\nfunction emptyTurn(index: number, origin: TimelineTurnOrigin, atMs: number | null): TimelineTurn {\n return {\n index,\n origin,\n injectedMarker: null,\n startMs: atMs,\n endMs: atMs,\n gapBeforeMs: null,\n user: null,\n assistant: [],\n toolCalls: [],\n errorCount: 0,\n tokens: { input: 0, cacheRead: 0, cacheWrite: 0, cacheWrite5m: 0, cacheWrite1h: 0, output: 0 },\n costUsd: 0,\n };\n}\n\nfunction originOf(marker: string | null): TimelineTurnOrigin {\n if (marker === null) return \"prompt\";\n return marker === \"compaction_summary\" ? \"compaction\" : \"injected\";\n}\n\nfunction touch(turn: TimelineTurn, atMs: number | null): TimelineTurn {\n if (atMs === null) return turn;\n if (turn.startMs === null || atMs < turn.startMs) turn.startMs = atMs;\n if (turn.endMs === null || atMs > turn.endMs) turn.endMs = atMs;\n return turn;\n}\n\nfunction span(startMs: number | null, endMs: number | null): number | null {\n if (startMs === null || endMs === null || endMs < startMs) return null;\n return endMs - startMs;\n}\n\nfunction outcomeOf(isError: boolean | null): TimelineToolOutcome {\n if (isError === null) return \"unknown\";\n return isError ? \"error\" : \"success\";\n}\n\nfunction firstString(input: unknown, keys: readonly string[]): string | null {\n if (typeof input !== \"object\" || input === null) return null;\n const record = input as Record<string, unknown>;\n for (const key of keys) {\n const value = record[key];\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return null;\n}\n\nfunction inputSummary(input: unknown): string {\n const text = firstString(input, PATH_KEYS) ?? firstString(input, SUMMARY_KEYS) ?? \"\";\n const firstLine = text.split(\"\\n\", 1)[0] ?? \"\";\n return capText(firstLine, SUMMARY_CAP).text;\n}\n\nfunction outputText(output: unknown): string {\n if (typeof output === \"string\") return output;\n if (!Array.isArray(output)) return \"\";\n for (const block of output) {\n const text = firstString(block, [\"text\"]);\n if (text) return text;\n }\n return \"\";\n}\n","import type { NormalizedSessionObservation } from \"@titan-design/session-read\";\nimport type { PriceRow } from \"./prices.js\";\nimport { agentSpans, errorBreakdown, fileBreakdown, toolBreakdown } from \"./timeline-breakdowns.js\";\nimport { activityTimes, findGaps, markTurnGaps, minuteBuckets } from \"./timeline-buckets.js\";\nimport type { TokenFoldResult } from \"./timeline-tokens.js\";\nimport { TokenFold, addTokens, emptyTokens } from \"./timeline-tokens.js\";\nimport { TurnFold } from \"./timeline-turns.js\";\nimport type { SessionTimeline, TimelineTotals, TimelineTurn } from \"./timeline-types.js\";\nimport { SESSION_TIMELINE_VERSION, TIMELINE_GAP_MIN_MS, TIMELINE_TEXT_CAP } from \"./timeline-types.js\";\n\nexport interface SessionTimelineOptions {\n /** Idle time that counts as a gap. Defaults to `TIMELINE_GAP_MIN_MS`. */\n gapMinMs?: number;\n /** Cap on each message and compaction summary. Defaults to `TIMELINE_TEXT_CAP`. */\n maxTextChars?: number;\n /** Price rows for the cost series. Defaults to `PRICE_TABLE`. */\n prices?: readonly PriceRow[];\n}\n\n/** Storage-free fold for a streamed read: `add` each observation, then `result`, which returns a fresh copy each time. */\nexport class SessionTimelineAccumulator {\n private readonly turns: TurnFold;\n private readonly tokens: TokenFold;\n private readonly gapMinMs: number;\n private conversation: NormalizedSessionObservation[\"conversation\"] | null = null;\n private startMs: number | null = null;\n private endMs: number | null = null;\n\n constructor(options: SessionTimelineOptions = {}) {\n const maxTextChars = options.maxTextChars ?? TIMELINE_TEXT_CAP;\n this.gapMinMs = options.gapMinMs ?? TIMELINE_GAP_MIN_MS;\n this.turns = new TurnFold(maxTextChars);\n this.tokens = new TokenFold(maxTextChars, options.prices);\n }\n\n add(observation: NormalizedSessionObservation): void {\n this.claim(observation);\n // History copied in from a parent conversation is that conversation's activity, not this one's.\n if (observation.historyOrigin) return;\n const atMs = this.clock(observation.timestamp);\n if (observation.kind === \"message\") this.turns.message(observation, atMs);\n if (observation.kind === \"tool_call\") this.turns.toolCall(observation, atMs);\n if (observation.kind === \"tool_result\") this.turns.toolResult(observation, atMs);\n if (observation.kind === \"usage\") this.tokens.usage(observation, atMs, this.turns.currentIndex());\n if (observation.kind === \"compaction\") this.tokens.compaction(observation, atMs, this.turns.currentIndex());\n }\n\n result(): SessionTimeline {\n const { turns, calls } = this.turns;\n const tokens = this.tokens.result();\n attributeRequests(turns, tokens);\n markTurnGaps(turns, this.gapMinMs);\n const bucketInput = { turns, calls, points: tokens.timeline.points };\n const gaps = findGaps(activityTimes(bucketInput), this.gapMinMs, calls);\n const errors = errorBreakdown(calls);\n // A copy, so a later `add` cannot change a result the caller already holds.\n return structuredClone<SessionTimeline>({\n version: SESSION_TIMELINE_VERSION,\n sessionId: this.conversation?.nativeId ?? null,\n harness: this.conversation?.harness ?? null,\n startMs: this.startMs,\n endMs: this.endMs,\n durationMs: this.startMs !== null && this.endMs !== null ? this.endMs - this.startMs : 0,\n totals: totalsOf(turns, calls.length, errors.items.length, tokens),\n turns,\n buckets: minuteBuckets(bucketInput, gaps),\n gaps,\n tokens: tokens.timeline,\n tools: toolBreakdown(calls),\n files: fileBreakdown(calls),\n errors,\n agents: agentSpans(calls),\n });\n }\n\n private claim(observation: NormalizedSessionObservation): void {\n const { harness, namespace, nativeId } = observation.conversation;\n this.conversation ??= observation.conversation;\n const held = this.conversation;\n if (held.harness !== harness || held.namespace !== namespace || held.nativeId !== nativeId) {\n throw new TypeError(\"cannot build one timeline from observations of different conversations\");\n }\n }\n\n /** A record with no usable timestamp takes the latest one seen, so it still lands in order. */\n private clock(timestamp: string | null): number | null {\n const parsed = timestamp === null ? Number.NaN : Date.parse(timestamp);\n if (!Number.isFinite(parsed)) return this.endMs;\n if (this.startMs === null || parsed < this.startMs) this.startMs = parsed;\n if (this.endMs === null || parsed > this.endMs) this.endMs = parsed;\n return parsed;\n }\n}\n\n/** The read model behind every session view: turns, minute buckets, the token and cost series, and tool, file and error breakdowns. */\nexport function buildSessionTimeline(\n observations: Iterable<NormalizedSessionObservation>,\n options: SessionTimelineOptions = {},\n): SessionTimeline {\n const accumulator = new SessionTimelineAccumulator(options);\n for (const observation of observations) accumulator.add(observation);\n return accumulator.result();\n}\n\n/** Rebuilds each turn's sums from scratch, so `result` can run more than once. */\nfunction attributeRequests(turns: readonly TimelineTurn[], tokens: TokenFoldResult): void {\n for (const turn of turns) {\n turn.tokens = emptyTokens();\n turn.costUsd = 0;\n }\n for (const request of tokens.requests) {\n const turn = request.turnIndex === null ? undefined : turns[request.turnIndex];\n if (!turn) continue;\n addTokens(turn.tokens, request.tokens);\n turn.costUsd += request.costUsd;\n }\n}\n\nfunction totalsOf(turns: readonly TimelineTurn[], toolCalls: number, errors: number, tokens: TokenFoldResult): TimelineTotals {\n return {\n turns: turns.length,\n userMessages: turns.filter((turn) => turn.user !== null).length,\n assistantMessages: turns.reduce((sum, turn) => sum + turn.assistant.length, 0),\n toolCalls,\n errors,\n compactions: tokens.timeline.compactions.length,\n requests: tokens.requestCount,\n unpricedRequests: tokens.requests.filter((request) => !request.priced).length,\n tokens: tokens.tokens,\n costUsd: tokens.requests.reduce((sum, request) => sum + request.costUsd, 0),\n };\n}\n","/** How many of the ascending `sortedMs` are at or before `targetMs`, by binary search. */\nexport function countAtOrBefore(sortedMs: readonly number[], targetMs: number): number {\n let lo = 0;\n let hi = sortedMs.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if ((sortedMs[mid] as number) <= targetMs) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n","import type { Db } from \"@titan-design/store-sqlite\";\nimport { z } from \"zod\";\nimport { contextBand } from \"./bands.js\";\nimport type { ReportWindow } from \"./cost-report-queries.js\";\n\nconst APPROVE = \"approve\";\nconst CHANGES_REQUESTED = \"changes_requested\";\nconst CHAT_KEY = /^chat:([^:]+):/;\n\nconst VERDICTS = `\n SELECT source_key AS sourceKey, verdict, ts, pr_ref AS prRef, transcript_id AS transcriptId FROM pr_review\n WHERE (@since IS NULL OR ts >= @since) AND (@until IS NULL OR ts < @until)\n`;\nconst CHANGES = `SELECT pr_ref AS prRef, ts FROM pr_review WHERE verdict = '${CHANGES_REQUESTED}' AND pr_ref IS NOT NULL`;\n/** The ownership rule of request-owner.ts: the latest request at or before the tool use. That module drops the tool use id, so the lookup is repeated here. */\nconst ISSUER = `\n SELECT r.model, r.context_tokens AS tokens FROM tool_call c\n JOIN request r ON r.transcript_id = c.transcript_id AND r.byte_offset <= c.byte_offset\n WHERE c.tool_use_id = @toolUseId AND c.transcript_id = @transcriptId\n ORDER BY r.byte_offset DESC LIMIT 1\n`;\n\ninterface VerdictRow {\n sourceKey: string;\n verdict: string;\n ts: string;\n prRef: string | null;\n transcriptId: number | null;\n}\n\ninterface Issuer {\n model: string;\n tokens: number;\n}\n\nconst count = z.number().int().nonnegative();\nconst rate = z.number().min(0).max(1).nullable();\n\nexport const reviewFillSchema = z.object({\n window: z.object({ since: z.string().nullable(), until: z.string().nullable() }),\n /** Verdicts with no fill: GitHub-surface reviews, and chat verdicts whose issuing request is not in the graph. */\n unfilled: count,\n /** Verdicts whose `pr_ref` is not resolved; they count in their band but are never matched to another review. */\n unresolved: count,\n rows: z.array(\n z.object({\n band: z.string(),\n model: z.string(),\n verdicts: count,\n changesRequested: count,\n changesRate: rate,\n verdictErrors: count,\n /** Verdict errors over all verdicts in the cell, not over approvals. */\n errorRate: rate,\n }),\n ),\n});\n\nexport type ReviewFillReport = z.infer<typeof reviewFillSchema>;\ntype Cell = ReviewFillReport[\"rows\"][number];\n\n/** Review verdicts in the window by the reviewer's context fill when it issued them, and how often an approve was contradicted. */\nexport function reviewFillReport(db: Db, window: ReportWindow): ReviewFillReport {\n const changesByPr = readChangesByPr(db);\n const cells = new Map<string, Cell>();\n let unfilled = 0;\n let unresolved = 0;\n for (const row of db.prepare(VERDICTS).all(window) as VerdictRow[]) {\n if (!row.prRef) unresolved += 1;\n const issuer = issuerOf(db, row);\n const band = issuer ? contextBand(issuer.tokens) : null;\n if (!issuer || !band) {\n unfilled += 1;\n continue;\n }\n const key = `${band}|${issuer.model}`;\n cells.set(key, tally(cells.get(key) ?? emptyCell(band, issuer.model), row, changesByPr));\n }\n return { window, unfilled, unresolved, rows: [...cells.values()].map(withRates) };\n}\n\nfunction issuerOf(db: Db, row: VerdictRow): Issuer | null {\n const toolUseId = CHAT_KEY.exec(row.sourceKey)?.[1];\n if (!toolUseId || row.transcriptId === null) return null;\n return (db.prepare(ISSUER).get({ toolUseId, transcriptId: row.transcriptId }) as Issuer | undefined) ?? null;\n}\n\nfunction readChangesByPr(db: Db): Map<string, string[]> {\n const byPr = new Map<string, string[]>();\n for (const { prRef, ts } of db.prepare(CHANGES).all() as { prRef: string; ts: string }[]) byPr.set(prRef, [...(byPr.get(prRef) ?? []), ts]);\n return byPr;\n}\n\nfunction tally(cell: Cell, row: VerdictRow, changesByPr: Map<string, string[]>): Cell {\n const contradicted = row.verdict === APPROVE && row.prRef !== null && (changesByPr.get(row.prRef) ?? []).some((ts) => ts > row.ts);\n return {\n ...cell,\n verdicts: cell.verdicts + 1,\n changesRequested: cell.changesRequested + (row.verdict === CHANGES_REQUESTED ? 1 : 0),\n verdictErrors: cell.verdictErrors + (contradicted ? 1 : 0),\n };\n}\n\nfunction emptyCell(band: string, model: string): Cell {\n return { band, model, verdicts: 0, changesRequested: 0, changesRate: null, verdictErrors: 0, errorRate: null };\n}\n\nfunction withRates(cell: Cell): Cell {\n return { ...cell, changesRate: cell.changesRequested / cell.verdicts, errorRate: cell.verdictErrors / cell.verdicts };\n}\n"],"mappings":"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","names":["z","lines","agentSessions","sum","costOf","z","count","z","groupBy","sum","count","z","sum","byCostThenKey","buckets","gapBand","buckets","sum","lines","fraction","z","MTOK","count","z","bucketSchema","sum","IN_WINDOW","span","header","footer","z","MINUTE_MS","lines","z","z","count","sum","lines","minutesBetween","minutesBetween","minutesBetween","z","source","z","count","scopeTest","touch","MINUTE_MS","buckets","timeline","count","sum","z","count","z"]}