@tangle-network/agent-eval 0.118.3 → 0.119.1

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +26 -0
  3. package/dist/analyst/index.d.ts +172 -59
  4. package/dist/analyst/index.js +50 -12
  5. package/dist/analyst/index.js.map +1 -1
  6. package/dist/benchmarks/index.d.ts +50 -40
  7. package/dist/benchmarks/index.js +8 -8
  8. package/dist/campaign/index.d.ts +258 -184
  9. package/dist/campaign/index.js +7 -7
  10. package/dist/{chunk-JTMFT5QZ.js → chunk-4I2E3LLO.js} +2 -2
  11. package/dist/{chunk-KK2O4VWA.js → chunk-D7AEXSM5.js} +2 -2
  12. package/dist/{chunk-MLHRFWQK.js → chunk-JHOJHHU7.js} +85 -16
  13. package/dist/chunk-JHOJHHU7.js.map +1 -0
  14. package/dist/{chunk-F5A4GDQW.js → chunk-JM2SKQMS.js} +3 -15
  15. package/dist/chunk-JM2SKQMS.js.map +1 -0
  16. package/dist/{chunk-EGNRE7VA.js → chunk-PAHNGS65.js} +2 -2
  17. package/dist/{chunk-QWRLW4CT.js → chunk-PSXJ32SR.js} +160 -6
  18. package/dist/chunk-PSXJ32SR.js.map +1 -0
  19. package/dist/{chunk-6QIM2EAP.js → chunk-PXD6ZFNY.js} +99 -1
  20. package/dist/chunk-PXD6ZFNY.js.map +1 -0
  21. package/dist/{chunk-267UCQWI.js → chunk-QWMPPZ3X.js} +3 -3
  22. package/dist/{chunk-267UCQWI.js.map → chunk-QWMPPZ3X.js.map} +1 -1
  23. package/dist/{chunk-VNLWDTDA.js → chunk-S5TT5R3L.js} +1010 -285
  24. package/dist/chunk-S5TT5R3L.js.map +1 -0
  25. package/dist/{chunk-ZYHJNKI3.js → chunk-ULOKLHIQ.js} +42 -5
  26. package/dist/chunk-ULOKLHIQ.js.map +1 -0
  27. package/dist/{chunk-FIUFRXP3.js → chunk-WW2A73HW.js} +49 -91
  28. package/dist/chunk-WW2A73HW.js.map +1 -0
  29. package/dist/{chunk-7V3QDWNL.js → chunk-XJ7JVCHB.js} +2 -2
  30. package/dist/{chunk-EKHHBKS6.js → chunk-XMBOU5W7.js} +48 -190
  31. package/dist/chunk-XMBOU5W7.js.map +1 -0
  32. package/dist/cli.js +2 -2
  33. package/dist/contract/index.d.ts +281 -175
  34. package/dist/contract/index.js +284 -8
  35. package/dist/contract/index.js.map +1 -1
  36. package/dist/fuzz.d.ts +19 -1
  37. package/dist/fuzz.js +1 -1
  38. package/dist/index.d.ts +223 -114
  39. package/dist/index.js +38 -37
  40. package/dist/index.js.map +1 -1
  41. package/dist/openapi.json +1 -1
  42. package/dist/primeintellect/index.d.ts +311 -0
  43. package/dist/primeintellect/index.js +348 -0
  44. package/dist/primeintellect/index.js.map +1 -0
  45. package/dist/rl.d.ts +4 -0
  46. package/dist/{run-campaign-DWC67KJP.js → run-campaign-OBXSN5WK.js} +3 -3
  47. package/dist/traces.d.ts +39 -25
  48. package/dist/traces.js +3 -5
  49. package/dist/wire/index.d.ts +19 -1
  50. package/dist/wire/index.js +2 -2
  51. package/docs/trace-analysis.md +6 -2
  52. package/package.json +7 -2
  53. package/dist/chunk-6QIM2EAP.js.map +0 -1
  54. package/dist/chunk-EKHHBKS6.js.map +0 -1
  55. package/dist/chunk-F5A4GDQW.js.map +0 -1
  56. package/dist/chunk-FIUFRXP3.js.map +0 -1
  57. package/dist/chunk-MLHRFWQK.js.map +0 -1
  58. package/dist/chunk-QWRLW4CT.js.map +0 -1
  59. package/dist/chunk-VNLWDTDA.js.map +0 -1
  60. package/dist/chunk-ZYHJNKI3.js.map +0 -1
  61. /package/dist/{chunk-JTMFT5QZ.js.map → chunk-4I2E3LLO.js.map} +0 -0
  62. /package/dist/{chunk-KK2O4VWA.js.map → chunk-D7AEXSM5.js.map} +0 -0
  63. /package/dist/{chunk-EGNRE7VA.js.map → chunk-PAHNGS65.js.map} +0 -0
  64. /package/dist/{chunk-7V3QDWNL.js.map → chunk-XJ7JVCHB.js.map} +0 -0
  65. /package/dist/{run-campaign-DWC67KJP.js.map → run-campaign-OBXSN5WK.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/analyst/ax-service.ts","../src/locked-jsonl-appender.ts","../src/analyst/findings-store.ts","../src/analyst/kinds/skill-usage.ts","../src/run-critic.ts","../src/semantic-concept-judge.ts"],"sourcesContent":["import type { AxAIService } from '@ax-llm/ax'\nimport { ai } from '@ax-llm/ax'\n\nexport interface CreateAnalystAiConfig {\n /** OpenAI-compatible API key forwarded as `Authorization: Bearer`.\n * cli-bridge ignores the value on loopback but Ax requires a non-empty string. */\n apiKey: string\n /** OpenAI-compatible base URL — e.g. `https://router.tangle.tools/v1` or a\n * cli-bridge loopback. */\n baseUrl: string\n /** Model id forwarded to the analyst actor + responder. */\n model: string\n /** Ax provider name. Defaults to the OpenAI-compatible client. */\n provider?: 'openai' | 'anthropic'\n}\n\n/**\n * Construct the `AxAIService` an analyst kind calls through\n * (`createTraceAnalystKind({ ai })`).\n *\n * Ax's `ai()` pins `config.model` to the OpenAI catalog enum, but every\n * OpenAI-compatible router an analyst points at (router.tangle.tools,\n * cli-bridge) accepts arbitrary model ids (claude-code/sonnet, openai/gpt-5.4,\n * …). Consumers were each re-rolling `ai({ name, apiKey, apiURL, config })`\n * behind an `as (a: any) => any` cast to dodge the enum; this is the one\n * canonical constructor so they don't have to — and don't take a direct\n * `@ax-llm/ax` dependency for it.\n */\nexport function createAnalystAi(config: CreateAnalystAiConfig): AxAIService {\n return ai({\n name: config.provider ?? 'openai',\n apiKey: config.apiKey,\n apiURL: config.baseUrl,\n config: { model: config.model },\n })\n}\n","/**\n * LockedJsonlAppender — mutex-serialized JSONL append helper for arbitrary\n * payloads. The reference-replay store does the same thing for typed\n * `ReferenceReplayRun` rows; this is the generic version used by\n * `MutationTelemetry`, `TrialTelemetry`, and any other consumer that wants\n * append-only durable telemetry without rolling its own lock.\n *\n * Locks are per absolute file path (process-local). Cross-process\n * concurrency is NOT addressed — that's an fcntl/flock problem.\n */\n\nimport { appendFileSync, existsSync, mkdirSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { Mutex } from './concurrency'\n\nconst mutexes = new Map<string, Mutex>()\n\nfunction getMutex(path: string): Mutex {\n let m = mutexes.get(path)\n if (!m) {\n m = new Mutex()\n mutexes.set(path, m)\n }\n return m\n}\n\nexport class LockedJsonlAppender {\n private readonly mutex: Mutex\n constructor(public readonly path: string) {\n this.mutex = getMutex(path)\n if (!existsSync(dirname(path))) {\n mkdirSync(dirname(path), { recursive: true })\n }\n }\n\n async append(entry: unknown): Promise<void> {\n const line = `${JSON.stringify(entry)}\\n`\n await this.mutex.runExclusive(() => {\n appendFileSync(this.path, line)\n })\n }\n}\n\n/** Reset all internal mutex state — tests only. */\nexport function resetLockedAppendersForTesting(): void {\n mutexes.clear()\n}\n","/**\n * FindingsStore — durable persistence for AnalystFinding rows + a diff\n * helper so we can answer \"what changed since the last run?\" without\n * recomputing analysts.\n *\n * On-disk shape is JSONL: one finding per line, append-only, locked via\n * LockedJsonlAppender. Operators get crash-safety (no partial JSON),\n * cheap reads (sequential parse), and trivial backup (rsync the file).\n *\n * Reads are non-locking: a reader sees a consistent snapshot of all\n * fully-written lines and skips an incomplete trailing line if the\n * writer is mid-append. Cross-process locking is intentionally out of\n * scope (see locked-jsonl-appender.ts).\n *\n * The store is run-scoped: callers pass `runId` on append and on load,\n * which keeps multi-run files cleanly partitioned. The `diffFindings`\n * helper compares two run-id sets using stable `finding_id` semantics —\n * the diff is the cross-run signal the regression dashboard renders.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\n\nimport { LockedJsonlAppender } from '../locked-jsonl-appender'\nimport type { AnalystFinding } from './types'\n\n/**\n * One persisted row. We attach `run_id` on disk so a single file can\n * hold multiple runs and the diff helper can query without re-walking\n * separate files.\n */\nexport interface PersistedFinding extends AnalystFinding {\n run_id: string\n}\n\nexport class FindingsStore {\n private readonly appender: LockedJsonlAppender\n\n constructor(public readonly path: string) {\n this.appender = new LockedJsonlAppender(path)\n }\n\n async append(runId: string, findings: AnalystFinding[]): Promise<void> {\n for (const f of findings) {\n const row: PersistedFinding = { ...f, run_id: runId }\n await this.appender.append(row)\n }\n }\n\n /** Load every persisted finding. Discards malformed trailing lines silently. */\n loadAll(): PersistedFinding[] {\n if (!existsSync(this.path)) return []\n const raw = readFileSync(this.path, 'utf8')\n if (!raw) return []\n const out: PersistedFinding[] = []\n for (const line of raw.split('\\n')) {\n if (!line) continue\n try {\n out.push(JSON.parse(line) as PersistedFinding)\n } catch {\n // Skip torn trailing line — the lock guarantees no torn lines\n // mid-file, only at EOF when a writer is in-flight.\n }\n }\n return out\n }\n\n /** Filter to a single run. */\n loadRun(runId: string): PersistedFinding[] {\n return this.loadAll().filter((r) => r.run_id === runId)\n }\n}\n\n// ── Cross-run diff ──────────────────────────────────────────────────\n\nexport interface FindingsDiff {\n /** New finding ids in `current` that weren't in `previous`. */\n appeared: PersistedFinding[]\n /** Finding ids in `previous` that aren't in `current`. */\n disappeared: PersistedFinding[]\n /** Same finding id present in both runs and unchanged per the materiality test. */\n persisted: PersistedFinding[]\n /**\n * Same finding id in both runs but at least one non-identity field\n * shifted per `DiffPolicy.isMaterial`. Reported as [previous, current].\n */\n changed: Array<{ previous: PersistedFinding; current: PersistedFinding }>\n}\n\nexport interface DiffPolicy {\n /**\n * Predicate that decides whether two findings (same finding_id) count\n * as a material change. Defaults to {@link defaultIsMaterial}: severity\n * shift, confidence Δ > 0.05, or evidence count change. Compliance /\n * perf consumers MAY supply a stricter predicate (e.g. rationale text\n * diff, metric Δ thresholds).\n */\n isMaterial?: (previous: AnalystFinding, current: AnalystFinding) => boolean\n}\n\n/**\n * Default materiality test. Deliberately narrow so LLM-reword churn\n * doesn't flood the diff. Stricter tests are opt-in via DiffPolicy.\n */\nexport function defaultIsMaterial(a: AnalystFinding, b: AnalystFinding): boolean {\n if (a.severity !== b.severity) return true\n if (Math.abs((a.confidence ?? 0) - (b.confidence ?? 0)) > 0.05) return true\n if (a.evidence_refs.length !== b.evidence_refs.length) return true\n return false\n}\n\n/**\n * Diff two findings sets by stable finding_id. Callers typically load\n * the two run-id slices from the same store and pass them in.\n */\nexport function diffFindings(\n previous: PersistedFinding[],\n current: PersistedFinding[],\n policy: DiffPolicy = {},\n): FindingsDiff {\n const isMaterial = policy.isMaterial ?? defaultIsMaterial\n const prevById = new Map(previous.map((f) => [f.finding_id, f]))\n const curById = new Map(current.map((f) => [f.finding_id, f]))\n\n const appeared: PersistedFinding[] = []\n const disappeared: PersistedFinding[] = []\n const persisted: PersistedFinding[] = []\n const changed: FindingsDiff['changed'] = []\n\n for (const [id, cur] of curById) {\n const prev = prevById.get(id)\n if (!prev) {\n appeared.push(cur)\n continue\n }\n if (isMaterial(prev, cur)) {\n changed.push({ previous: prev, current: cur })\n } else {\n persisted.push(cur)\n }\n }\n for (const [id, prev] of prevById) {\n if (!curById.has(id)) disappeared.push(prev)\n }\n return { appeared, disappeared, persisted, changed }\n}\n","/**\n * Skill-usage analyst — a DETERMINISTIC `Analyst` over a Claude/Codex skill\n * library + its trace corpus. Unlike the trace-store kinds (failure-mode,\n * improvement, ...) this kind calls no LLM: it mines real usage and skill\n * structure and emits findings by rule.\n *\n * It exists because the naive \"Skill-tool invocation count\" lies low — it\n * misses orchestrated sub-dispatch (a leaf skill run BY /pursue or /governor\n * logs under the parent), slash-command entry, local-script bypass, and\n * on-disk artifacts. The 2026-05-30 skill audit found 39/53 skills at zero\n * direct invocations, yet only one was a genuine cut: the rest were\n * measurement-invisible or discovery-limited. This analyst encodes that\n * lesson as a multi-signal usage model so a cheap repeatable pass can keep\n * the library honest, and so the expensive audit workflow's verdicts can\n * GEPA-distill it toward agreement (see `gold/skill-verdicts.gold.jsonl`).\n *\n * Report-building (`buildSkillUsageReport`, an fs scan) is separated from\n * finding emission (`SkillUsageAnalyst.analyze`, pure) so the slow scan runs\n * once at the registry boundary and the rule logic stays unit-testable.\n */\n\nimport { type Dirent, existsSync, readdirSync, readFileSync, statSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { Analyst, AnalystContext, AnalystFinding, AnalystSeverity } from '../types'\nimport { computeFindingId } from '../types'\n\n// ── Input model ──────────────────────────────────────────────────────\n\nexport type SkillKind = 'public' | 'private'\n\n/** One skill's multi-signal usage + structure. All counts are deterministic. */\nexport interface SkillUsageRecord {\n name: string\n kind: SkillKind\n /** Absolute path to the skill's SKILL.md. */\n path: string\n lines: number\n /** `\"skill\":\"<name>\"` Skill-tool invocations across the trace corpus. */\n directInvocations: number\n /** `<command-name>/<name>` slash invocations across the trace corpus. */\n slashInvocations: number\n /** Sibling skills whose SKILL.md dispatches to this one (`/<name>`). Proxy\n * for orchestrated sub-dispatch the per-skill counter cannot see. */\n inboundRefs: number\n /** On-disk artifacts attributable to the skill (e.g. `.evolve/<name>/**`). */\n artifactCount: number\n /** Tangle-private reference count in the body (leak signal for public skills). */\n tanglePrivateRefs: number\n hasReferencesDir: boolean\n hasEvalsDir: boolean\n /** Body mentions `skill-runs.jsonl` (visible to /reflect + /governor). */\n logsRuns: boolean\n /** Description carries an explicit `Triggers:` clause / trigger phrases. */\n hasTriggerPhrases: boolean\n}\n\nexport interface SkillUsageReport {\n generatedFromTraces: number\n records: SkillUsageRecord[]\n}\n\nexport interface SkillUsageScanConfig {\n /** Dirs holding `*.jsonl` transcripts (Claude `~/.claude/projects`, Codex sessions). */\n transcriptDirs: string[]\n /** Skill roots to scan; each dir directly under `root` with a `SKILL.md` is a skill. */\n skillRoots: { root: string; kind: SkillKind }[]\n /** Roots scanned for `<root>/.evolve/<skill>` artifact dirs. */\n artifactRoots?: string[]\n /** Token-prefixed mappings: skill name → extra artifact subpaths under an artifactRoot\n * (e.g. reflect → `.evolve/reflections`). Catches non-eponymous artifact dirs. */\n artifactAliases?: Record<string, string[]>\n /** Cap files read per transcript dir (bounds a huge corpus); 0 = unbounded. */\n maxTranscriptsPerDir?: number\n}\n\n// ── Deterministic thresholds ─────────────────────────────────────────\n\n/** Anthropic's authoring guidance keeps SKILL.md short; past this with no\n * `references/` split the body burns context budget every session. */\nconst BLOAT_LINE_THRESHOLD = 300\n\nconst TANGLE_PRIVATE_RE =\n /\\b(cli-bridge|tangletools|ops-board|drew-gtr-pro|@tangle-network\\/|~\\/company|tangle\\.tools|gtm-agent)\\b|\\bkimi\\b|\\btcloud\\b/gi\nconst TRIGGER_RE = /triggers?\\s*[:-]/i\n\n// ── Report builder (fs scan — slow, runs once at the registry boundary) ──\n\nfunction listSkillDirs(root: string): { name: string; path: string }[] {\n if (!existsSync(root)) return []\n const out: { name: string; path: string }[] = []\n for (const entry of readdirSync(root, { withFileTypes: true })) {\n if (!entry.isDirectory() && !entry.isSymbolicLink()) continue\n const skillMd = join(root, entry.name, 'SKILL.md')\n if (existsSync(skillMd)) out.push({ name: entry.name, path: skillMd })\n }\n return out\n}\n\nfunction walkJsonl(dir: string, cap: number): string[] {\n if (!existsSync(dir)) return []\n const files: string[] = []\n const stack = [dir]\n while (stack.length) {\n const cur = stack.pop()!\n let entries: Dirent[]\n try {\n entries = readdirSync(cur, { withFileTypes: true })\n } catch {\n continue\n }\n for (const e of entries) {\n const full = join(cur, e.name)\n if (e.isDirectory()) stack.push(full)\n else if (e.name.endsWith('.jsonl')) {\n files.push(full)\n if (cap > 0 && files.length >= cap) return files\n }\n }\n }\n return files\n}\n\nfunction frontmatterDescription(body: string): string {\n const fm = /^---\\n([\\s\\S]*?)\\n---/.exec(body)\n const block = fm?.[1] ?? ''\n const m = /description:\\s*(.+)/i.exec(block)\n return m?.[1] ?? ''\n}\n\nfunction countArtifacts(roots: string[], name: string, aliases: string[]): number {\n let n = 0\n for (const root of roots) {\n const candidates = [join(root, '.evolve', name), ...aliases.map((a) => join(root, a))]\n for (const dir of candidates) {\n if (!existsSync(dir)) continue\n try {\n if (statSync(dir).isDirectory()) n += readdirSync(dir).length\n else n += 1\n } catch {\n /* unreadable — skip */\n }\n }\n }\n return n\n}\n\n/** Scan the corpus + skill roots into a {@link SkillUsageReport}. Deterministic. */\nexport function buildSkillUsageReport(config: SkillUsageScanConfig): SkillUsageReport {\n const skills = config.skillRoots.flatMap(({ root, kind }) =>\n listSkillDirs(root).map((s) => ({ ...s, kind })),\n )\n const names = skills.map((s) => s.name)\n\n // One pass over the corpus accumulating direct + slash counts per skill.\n const direct = new Map<string, number>(names.map((n) => [n, 0]))\n const slash = new Map<string, number>(names.map((n) => [n, 0]))\n const skillRe = /\"skill\"\\s*:\\s*\"([a-z0-9_:-]+)\"/g\n const cmdRe = /<command-name>\\/?([a-z0-9_:-]+)<\\/command-name>/g\n let transcripts = 0\n for (const dir of config.transcriptDirs) {\n for (const file of walkJsonl(dir, config.maxTranscriptsPerDir ?? 0)) {\n transcripts += 1\n let data: string\n try {\n data = readFileSync(file, 'utf8')\n } catch {\n continue\n }\n for (const m of data.matchAll(skillRe)) {\n const g = m[1]\n if (!g) continue\n const n = g.split(':').pop() ?? g\n const prev = direct.get(n)\n if (prev !== undefined) direct.set(n, prev + 1)\n }\n for (const m of data.matchAll(cmdRe)) {\n const g = m[1]\n if (g === undefined) continue\n const prev = slash.get(g)\n if (prev !== undefined) slash.set(g, prev + 1)\n }\n }\n }\n\n // Read each skill body once; compute structure + inbound refs across siblings.\n const bodies = new Map<string, string>()\n for (const s of skills) {\n try {\n bodies.set(s.name, readFileSync(s.path, 'utf8'))\n } catch {\n bodies.set(s.name, '')\n }\n }\n const inbound = new Map<string, number>(names.map((n) => [n, 0]))\n for (const target of names) {\n const ref = new RegExp(`/${target}\\\\b|\\\\[\\\\[${target}\\\\]\\\\]`)\n for (const s of skills) {\n if (s.name === target) continue\n if (ref.test(bodies.get(s.name) ?? '')) inbound.set(target, inbound.get(target)! + 1)\n }\n }\n\n const records: SkillUsageRecord[] = skills.map((s) => {\n const body = bodies.get(s.name) ?? ''\n const dir = s.path.replace(/\\/SKILL\\.md$/, '')\n return {\n name: s.name,\n kind: s.kind,\n path: s.path,\n lines: body ? body.split('\\n').length : 0,\n directInvocations: direct.get(s.name) ?? 0,\n slashInvocations: slash.get(s.name) ?? 0,\n inboundRefs: inbound.get(s.name) ?? 0,\n artifactCount: countArtifacts(\n config.artifactRoots ?? [],\n s.name,\n config.artifactAliases?.[s.name] ?? [],\n ),\n tanglePrivateRefs: (body.match(TANGLE_PRIVATE_RE) ?? []).length,\n hasReferencesDir: existsSync(join(dir, 'references')),\n hasEvalsDir: existsSync(join(dir, 'evals')),\n logsRuns: body.includes('skill-runs.jsonl'),\n hasTriggerPhrases: TRIGGER_RE.test(frontmatterDescription(body) || body.slice(0, 600)),\n }\n })\n return { generatedFromTraces: transcripts, records }\n}\n\n// ── Finding emission (pure — unit-testable, no LLM, no fs) ────────────\n\nconst ANALYST_ID = 'skill-usage'\n\nfunction finding(\n area: string,\n subject: string,\n claim: string,\n severity: AnalystSeverity,\n confidence: number,\n producedAt: string,\n recommended: string,\n evidenceUri: string,\n rationale?: string,\n): AnalystFinding {\n return {\n schema_version: '1.0.0',\n finding_id: computeFindingId({ analyst_id: ANALYST_ID, area, subject, claim }),\n analyst_id: ANALYST_ID,\n produced_at: producedAt,\n severity,\n area,\n claim,\n rationale,\n evidence_refs: [{ kind: 'artifact', uri: evidenceUri }],\n recommended_action: recommended,\n confidence,\n subject,\n }\n}\n\n/** Pure rule pass over a report → findings. Exported for direct/unit use. */\nexport function emitSkillUsageFindings(\n report: SkillUsageReport,\n producedAt: string,\n): AnalystFinding[] {\n const out: AnalystFinding[] = []\n for (const r of report.records) {\n const directTotal = r.directInvocations + r.slashInvocations\n const trueUsage = directTotal + r.inboundRefs + r.artifactCount\n\n // 1. Dead: no usage signal of ANY kind. The only real deprecation candidate.\n if (trueUsage === 0) {\n out.push(\n finding(\n 'skill-usage',\n r.name,\n `Skill '${r.name}' has zero usage across all signals (direct, slash, inbound-refs, artifacts)`,\n 'high',\n 0.6,\n producedAt,\n 'Confirm the skill covers a real recurring job; if not, deprecate. Zero true usage is the only deterministic deprecation candidate.',\n r.path,\n 'No Skill-tool call, no slash invocation, no sibling dispatches to it, and no on-disk artifacts.',\n ),\n )\n } else if (directTotal === 0 && r.inboundRefs + r.artifactCount > 0) {\n // 2. Measurement-invisible: real use via orchestration/artifacts, never invoked directly.\n out.push(\n finding(\n 'skill-usage',\n r.name,\n `Skill '${r.name}' shows 0 direct invocations but is used via orchestration/artifacts (inbound=${r.inboundRefs}, artifacts=${r.artifactCount})`,\n 'info',\n 0.8,\n producedAt,\n 'Do NOT treat as unused — usage is real but logged under parent skills or on disk. Strengthen direct-invocation discovery only if direct use is desired.',\n r.path,\n 'The Skill-tool counter undercounts orchestrated/chained leaf skills.',\n ),\n )\n }\n\n // 3. Discovery gap: low direct use AND weak trigger surface.\n if (directTotal <= 2 && !r.hasTriggerPhrases) {\n out.push(\n finding(\n 'discoverability',\n r.name,\n `Skill '${r.name}' is rarely invoked directly and its description has no explicit trigger phrases`,\n 'medium',\n 0.7,\n producedAt,\n 'Add a `Triggers:` clause with verbatim user phrases to the frontmatter description so the model auto-invokes it.',\n r.path,\n ),\n )\n }\n\n // 4. Public-repo leak.\n if (r.kind === 'public' && r.tanglePrivateRefs > 0) {\n out.push(\n finding(\n 'safety',\n r.name,\n `Public skill '${r.name}' carries ${r.tanglePrivateRefs} Tangle-private reference(s)`,\n 'high',\n 0.75,\n producedAt,\n 'Sanitize incidental internal refs (cli-bridge/kimi/tcloud/~company/private repos) or relocate to a private repo. Verify @tangle-network/* refs are to PUBLISHED packages before treating as a leak.',\n r.path,\n ),\n )\n }\n\n // 5. Bloat / no progressive disclosure.\n if (r.lines > BLOAT_LINE_THRESHOLD && !r.hasReferencesDir) {\n out.push(\n finding(\n 'maintainability',\n r.name,\n `Skill '${r.name}' is ${r.lines} lines with no references/ split (progressive disclosure)`,\n 'medium',\n 0.8,\n producedAt,\n `Split detail into references/ loaded on demand; keep SKILL.md a short overview. ${r.lines} lines load into every session's context budget.`,\n r.path,\n ),\n )\n }\n\n // 6. No evals (Anthropic's \">=3 evals before docs\" rule).\n if (!r.hasEvalsDir) {\n out.push(\n finding(\n 'data-quality',\n r.name,\n `Skill '${r.name}' ships no evals/`,\n 'low',\n 0.6,\n producedAt,\n 'Add evals/evals.json with >=3 scenarios proving the skill beats baseline; gives regression coverage.',\n r.path,\n ),\n )\n }\n\n // 7. No run logging → invisible to /reflect and /governor.\n if (!r.logsRuns) {\n out.push(\n finding(\n 'observability',\n r.name,\n `Skill '${r.name}' never appends to .evolve/skill-runs.jsonl`,\n 'low',\n 0.55,\n producedAt,\n 'Append one run line to .evolve/skill-runs.jsonl on completion, or declare it a non-logging leaf, so the self-improvement loop can see it ran.',\n r.path,\n ),\n )\n }\n }\n return out\n}\n\n// ── The Analyst ──────────────────────────────────────────────────────\n\nexport class SkillUsageAnalyst implements Analyst<SkillUsageReport> {\n readonly id = ANALYST_ID\n readonly description =\n 'Deterministic multi-signal skill-usage analysis: flags dead skills, measurement-invisible (orchestrated) usage, discovery gaps, public-repo leaks, bloat, missing evals, and missing run-logging.'\n readonly inputKind = 'custom' as const\n readonly cost = { kind: 'deterministic' as const, est_usd_per_run: 0 }\n readonly version = '1.0.0'\n\n async analyze(input: SkillUsageReport, ctx: AnalystContext): Promise<AnalystFinding[]> {\n const producedAt = ctx.tags?.producedAt ?? new Date().toISOString()\n ctx.log?.(\n `skill-usage: ${input.records.length} skills over ${input.generatedFromTraces} transcripts`,\n )\n return emitSkillUsageFindings(input, producedAt)\n }\n}\n\nexport const SKILL_USAGE_ANALYST = new SkillUsageAnalyst()\n","import { NotFoundError } from './errors'\nimport { aggregateRunScore, clamp01, type RunScore, type RunScoreWeights } from './run-score'\nimport type { Artifact, BudgetLedgerEntry, Run, Span, TraceEvent, TraceStore } from './trace'\n\nexport interface RunTrace {\n run: Run\n spans: Span[]\n events: TraceEvent[]\n artifacts: Artifact[]\n budget: BudgetLedgerEntry[]\n}\n\nexport interface RunCriticOptions {\n weights?: Partial<RunScoreWeights>\n driftPatterns?: RegExp[]\n}\n\nconst DEFAULT_DRIFT_PATTERNS = [\n /https?:\\/\\//i,\n /\\btitle:\\s/i,\n /\\bsummary:\\s/i,\n /\\burl:\\s/i,\n /\\bnpm package usage\\b/i,\n /\\bnews\\b/i,\n]\n\nexport class RunCritic {\n private readonly weights?: Partial<RunScoreWeights>\n private readonly driftPatterns: RegExp[]\n\n constructor(options: RunCriticOptions = {}) {\n this.weights = options.weights\n this.driftPatterns = options.driftPatterns ?? DEFAULT_DRIFT_PATTERNS\n }\n\n async score(store: TraceStore, runId: string): Promise<RunScore> {\n const run = await store.getRun(runId)\n if (!run) throw new NotFoundError(`run ${runId} not found`)\n const [spans, events, artifacts, budget] = await Promise.all([\n store.spans({ runId }),\n store.events({ runId }),\n store.artifacts(runId),\n store.budget(runId),\n ])\n return this.scoreTrace({ run, spans, events, artifacts, budget })\n }\n\n scoreTrace(trace: RunTrace): RunScore {\n const notes: string[] = []\n const llmSpans = trace.spans.filter(\n (s): s is Extract<Span, { kind: 'llm' }> => s.kind === 'llm',\n )\n const toolSpans = trace.spans.filter(\n (s): s is Extract<Span, { kind: 'tool' }> => s.kind === 'tool',\n )\n const judgeSpans = trace.spans.filter(\n (s): s is Extract<Span, { kind: 'judge' }> => s.kind === 'judge',\n )\n const sandboxSpans = trace.spans.filter(\n (s): s is Extract<Span, { kind: 'sandbox' }> => s.kind === 'sandbox',\n )\n const finalGateSpans = judgeSpans.filter(\n (span) => span.dimension === 'final_gate' || span.attributes?.finalGate === true,\n )\n\n const success =\n trace.run.outcome?.pass === true ? 1 : trace.run.status === 'completed' ? 0.5 : 0\n if (!success) notes.push('run did not complete with pass=true')\n\n const judgeAverage = judgeSpans.length\n ? judgeSpans.reduce((sum, span) => sum + normalizeJudgeScore(span.score), 0) /\n judgeSpans.length\n : undefined\n const outcomeScore =\n typeof trace.run.outcome?.score === 'number'\n ? clamp01(\n trace.run.outcome.score > 1 ? trace.run.outcome.score / 100 : trace.run.outcome.score,\n )\n : undefined\n const goalProgress = outcomeScore ?? judgeAverage ?? success\n\n const successfulTools = toolSpans.filter((span) => span.status !== 'error').length\n const toolUseQuality = toolSpans.length === 0 ? 0 : successfulTools / toolSpans.length\n if (toolSpans.length === 0) notes.push('no tool spans recorded')\n\n const patchEvidence =\n trace.artifacts.length +\n toolSpans.filter((span) => /write|edit|patch|apply/i.test(span.toolName)).length\n const patchQuality = patchEvidence > 0 ? clamp01(patchEvidence / 4) : 0\n if (!patchQuality) notes.push('no artifact or edit evidence recorded')\n\n const sandboxTests = sandboxSpans.filter(\n (span) => typeof span.testsTotal === 'number' && span.testsTotal > 0,\n )\n const testReality = sandboxTests.length\n ? sandboxTests.reduce(\n (sum, span) => sum + (span.testsPassed ?? 0) / Math.max(1, span.testsTotal ?? 1),\n 0,\n ) / sandboxTests.length\n : toolSpans.some((span) =>\n /\\btest|vitest|pytest|jest|build|tsc\\b/i.test(JSON.stringify(span.args)),\n )\n ? 0.4\n : 0\n if (!testReality) notes.push('no real test/build evidence recorded')\n\n const blockerSpans = judgeSpans.filter((span) => isBlockingJudge(span))\n const finalGateBlockers = finalGateSpans.filter((span) => isBlockingJudge(span))\n const finalGate = finalGateSpans.length ? (finalGateBlockers.length ? 0 : 1) : success\n if (finalGateBlockers.length)\n notes.push(`final gate blocked by ${finalGateBlockers.length} reviewer(s)`)\n else if (!finalGateSpans.length) notes.push('no final gate judgment recorded')\n\n const reviewerBlockers = judgeSpans.length ? blockerSpans.length / judgeSpans.length : 0\n if (reviewerBlockers) notes.push(`detected ${blockerSpans.length} blocking reviewer signal(s)`)\n\n const positiveGroundingSignals =\n patchEvidence +\n sandboxSpans.length +\n llmSpans.filter((span) => looksRepoGrounded(span.output ?? '')).length\n const driftSignals =\n llmSpans.filter((span) => this.isDrift(span.output ?? '')).length +\n trace.events.filter((event) => this.isDrift(JSON.stringify(event.payload))).length\n const repoGroundedness =\n positiveGroundingSignals + driftSignals === 0\n ? 0\n : positiveGroundingSignals / (positiveGroundingSignals + driftSignals)\n const driftPenalty =\n positiveGroundingSignals + driftSignals === 0\n ? 0\n : driftSignals / (positiveGroundingSignals + driftSignals)\n if (driftSignals > 0) notes.push(`detected ${driftSignals} drift signal(s)`)\n\n const costUsd = trace.budget.length\n ? Math.max(\n ...trace.budget\n .filter((entry: BudgetLedgerEntry) => entry.dimension === 'usd')\n .map((entry: BudgetLedgerEntry) => entry.consumed),\n 0,\n )\n : llmSpans.reduce((sum, span) => sum + (span.costUsd ?? 0), 0)\n const wallSeconds =\n trace.run.endedAt && trace.run.startedAt\n ? Math.max(0, (trace.run.endedAt - trace.run.startedAt) / 1000)\n : 0\n\n return {\n success,\n goalProgress,\n repoGroundedness,\n driftPenalty,\n toolUseQuality,\n patchQuality,\n testReality,\n finalGate,\n reviewerBlockers,\n costUsd,\n wallSeconds,\n notes,\n }\n }\n\n rank(score: RunScore): number {\n return aggregateRunScore(score, this.weights)\n }\n\n private isDrift(text: string): boolean {\n return this.driftPatterns.some((pattern) => pattern.test(text))\n }\n}\n\nfunction normalizeJudgeScore(score: number): number {\n return score > 1 ? clamp01(score / 10) : clamp01(score)\n}\n\nfunction looksRepoGrounded(text: string): boolean {\n return /(?:src\\/|tests?\\/|package\\.json|tsconfig|\\.ts\\b|\\.tsx\\b|git status|pnpm |npm |vitest|pytest|jest)/i.test(\n text,\n )\n}\n\nfunction isBlockingJudge(span: Extract<Span, { kind: 'judge' }>): boolean {\n return (\n span.attributes?.blocking === true ||\n span.attributes?.verdict === 'BLOCKING' ||\n positiveNumber(span.attributes?.blockingFindings) ||\n positiveNumber(span.attributes?.highFindings) ||\n span.score <= 2\n )\n}\n\nfunction positiveNumber(value: unknown): boolean {\n return typeof value === 'number' && value > 0\n}\n","/**\n * Semantic concept judge — \"does the built artifact actually implement\n * the features the user asked for?\"\n *\n * Distinct from the domain/code/coherence judges in `judges.ts`:\n * - those judges score free-form conversational agent outputs along\n * quality dimensions (accuracy, depth, etc.)\n * - this judge scores a *built artifact* (served HTML + source files)\n * against an explicit list of expected concepts, returning per-concept\n * {present, score 0-10, evidence, severity}.\n *\n * The judge is strict about distinguishing (a) a working implementation\n * from (b) a keyword-present stub. \"// TODO: mint button\" is NOT present.\n * Only real, functional, wired-up code counts.\n *\n * Use via {@link createSemanticConceptJudge} or directly via\n * {@link runSemanticConceptJudge}. Soft-fails (available=false) on LLM\n * or JSON-parse errors so the caller can treat that as \"layer skipped\"\n * rather than \"layer failed\" in a multi-layer pipeline.\n */\n\nimport { CostLedger, type CostLedgerHandle, type CostReceipt } from './cost-ledger'\nimport {\n callLlmJson,\n costReceiptFromLlm,\n costReceiptFromLlmError,\n type LlmCallRequest,\n type LlmClientOptions,\n maximumChargeForLlmRequest,\n} from './llm-client'\nimport type { Severity } from './multi-layer-verifier'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\n/**\n * Implementation complexity class for weighted scoring.\n *\n * - `render` (default): the concept is a UI surface that displays static\n * data — render a list, show a counter, lay out a button. Single-file\n * work, no external integration.\n * - `integrate`: the concept requires wiring a real external system —\n * wallet connect (wagmi + RainbowKit + chain config), payment provider\n * (Stripe Elements + intent + webhook), an API client with auth.\n * Multi-file, library-knowledge, runtime correctness matters.\n * - `compute`: the concept requires algorithmic work — solver, simulator,\n * constraint propagation, ML inference. Correctness > UI polish.\n *\n * Default weights (when applied via `weightConcepts: 'complexity'`):\n * render=1.0, integrate=2.0, compute=2.5\n *\n * Cross-vertical scoring without complexity weighting silently inflates\n * the rate of UI-heavy verticals (healthcare, fintech dashboards) vs\n * integration-heavy verticals (DeFi, wallets) — all concepts treated\n * equally even though the agent does 2-3x the work for `integrate`.\n */\nexport type ConceptComplexity = 'render' | 'integrate' | 'compute'\n\nexport interface ConceptSpec {\n name: string\n /** Short hints that help the judge; not used for matching. */\n keywords?: string[]\n /** Optional explicit weight; default 1.0. Overrides complexity-derived weight. */\n weight?: number\n /** Implementation complexity class. Default `render`. */\n complexity?: ConceptComplexity\n}\n\nexport interface ConceptFinding {\n concept: string\n present: boolean\n /** 0..10. 10 = production-ready; 7 = functional thin; 4 = partial; 0 = absent. */\n score: number\n evidence: string\n severity: Severity\n}\n\nexport interface SemanticConceptJudgeInput {\n /** Full natural-language prompt the agent was handed. */\n userRequest: string\n /** Rendered HTML the preview returns (UI artifacts). Optional. */\n servedHtml?: string\n /** Top-level source files from the agent's workdir. */\n sourceFiles: Array<{ path: string; content: string }>\n /** The expected concept list. */\n expectedConcepts: ConceptSpec[]\n /** Free-form metadata (id, difficulty) to inject into the prompt. */\n artifactLabel?: string\n artifactDescription?: string\n}\n\nexport interface SemanticConceptJudgeResult {\n kind: 'semantic-concept'\n version: string\n /** Normalized 0..1 score — mean of per-concept scores / 10. */\n score: number\n presentCount: number\n totalCount: number\n findings: ConceptFinding[]\n summary: string\n durationMs: number\n costUsd: number | null\n /** False on LLM/JSON error — treat as \"skipped / unable to judge\" in pipelines. */\n available: boolean\n error?: string\n}\n\n/**\n * Score-aggregation strategy. `mean` averages 0-10 scores uniformly.\n * `complexity` applies the default weight table (render=1, integrate=2,\n * compute=2.5) unless a concept has an explicit `weight`. `explicit`\n * honors only `weight` (defaulting to 1 for unspecified).\n */\nexport type ConceptWeightStrategy = 'mean' | 'complexity' | 'explicit'\n\nexport const DEFAULT_COMPLEXITY_WEIGHTS: Record<ConceptComplexity, number> = {\n render: 1.0,\n integrate: 2.0,\n compute: 2.5,\n}\n\nexport interface SemanticConceptJudgeOptions {\n /** Model id to call. Default 'claude-sonnet-4-6' via agent-eval defaults. */\n model?: string\n /** Per-call timeout. Default 300s. */\n timeoutMs?: number\n /** Provider-enforced output limit. Default 16000. */\n maxTokens?: number\n /** Pipeline budget for the prompt (source blob truncation). Default 45000. */\n maxSourceChars?: number\n /** Per-file cap before inclusion. Default 20000. */\n maxPerFileChars?: number\n /** HTML cap. Default 30000. */\n maxHtmlChars?: number\n /** LlmClient config (baseUrl, apiKey, authHeader, …). */\n llm?: LlmClientOptions\n costLedger?: CostLedgerHandle\n costPhase?: string\n signal?: AbortSignal\n /**\n * Score aggregation strategy. Default `mean` — uniform average across\n * concepts. Cross-vertical comparisons should use `complexity` to\n * neutralize the integrate-vs-render asymmetry.\n */\n weightConcepts?: ConceptWeightStrategy\n /** Override the default complexity → weight table. */\n complexityWeights?: Partial<Record<ConceptComplexity, number>>\n}\n\n// ─── Prompt assembly ────────────────────────────────────────────────────\n\nexport const SEMANTIC_CONCEPT_JUDGE_VERSION = 'semantic-concept-judge-v1-2026-04-24'\n\nconst DEFAULT_MAX_SOURCE = 45_000\nconst DEFAULT_MAX_HTML = 30_000\nconst DEFAULT_MAX_PER_FILE = 20_000\nconst DEFAULT_TIMEOUT = 300_000\nconst DEFAULT_MAX_TOKENS = 16_000\nconst DEFAULT_MODEL = 'claude-sonnet-4-6'\n\nconst SEMANTIC_SCHEMA = {\n type: 'object',\n additionalProperties: false,\n required: ['summary', 'concepts'],\n properties: {\n summary: { type: 'string', minLength: 20, maxLength: 600 },\n concepts: {\n type: 'array',\n minItems: 1,\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['concept', 'present', 'score', 'evidence', 'severity'],\n properties: {\n concept: { type: 'string', minLength: 1, maxLength: 120 },\n present: { type: 'boolean' },\n score: { type: 'number', minimum: 0, maximum: 10 },\n evidence: { type: 'string', minLength: 5, maxLength: 400 },\n severity: { type: 'string', enum: ['critical', 'major', 'minor', 'info'] },\n },\n },\n },\n },\n}\n\nfunction truncate(body: string, cap: number, label: string): string {\n if (body.length <= cap) return body\n return `${body.slice(0, cap)}\\n… [truncated ${body.length - cap} chars of ${label}]`\n}\n\nfunction buildPrompt(\n input: SemanticConceptJudgeInput,\n opts: Required<SemanticConceptJudgeOptions>,\n): string {\n const sourceBlob = input.sourceFiles\n .filter((f) => f.content.length <= opts.maxPerFileChars)\n .map((f) => `--- FILE: ${f.path} ---\\n${f.content}`)\n .join('\\n\\n')\n\n const html = input.servedHtml ?? ''\n\n return `You are a strict code-review judge evaluating whether an agent's 0-to-1 build actually implements the features the user asked for.\n\nYou MUST distinguish:\n (a) WORKING code that implements the concept (rendered UI, wired handler, real API call),\n (b) KEYWORD-PRESENT stub (comments mentioning the concept, variable names, TODOs),\n (c) ABSENT (concept nowhere).\n\nA comment like \"// TODO: add mint button\" is NOT present — score 2-3. Only count a concept as present if there is real functional code: a rendered component, a call handler wired to state or a network call, a computed value actually used.\n\nUSER REQUEST (what the agent was asked to build):\n${input.userRequest}\n\n${input.artifactLabel ? `ARTIFACT METADATA:\\n name: ${input.artifactLabel}\\n description: ${input.artifactDescription ?? ''}\\n\\n` : ''}EXPECTED CONCEPTS (each must be graded independently):\n${input.expectedConcepts\n .map(\n (c, i) =>\n ` ${i + 1}. \"${c.name}\"${c.keywords?.length ? ` — hints: [${c.keywords.slice(0, 6).join(' | ')}]` : ''}`,\n )\n .join('\\n')}\n\n${html ? `SERVED HTML (what the preview returns when hit):\\n${truncate(html, opts.maxHtmlChars, 'HTML')}\\n\\n` : ''}SOURCE FILES (the agent's workdir):\n${truncate(sourceBlob, opts.maxSourceChars, 'source')}\n\nFor EACH concept, return:\n - concept: the concept name as given (match exactly)\n - present: boolean — does a working implementation exist?\n - score: 0-10 — 10 = production-ready; 7 = functional but thin; 4 = partial/stubbed; 2 = keyword-only comment; 0 = absent\n - evidence: cite \"<file>:<line>\" or \"served-html:<selector>\" pointing at the strongest supporting code. If the concept is absent or stubbed, explain what's missing.\n - severity:\n \"info\" when present: true AND score >= 7\n \"minor\" when present: true AND 4 <= score < 7\n \"major\" when present: false OR score < 4\n \"critical\" when the concept is not only absent but a core user flow depends on it\n\nAlso produce a \"summary\" (one sentence, 20-600 chars): overall verdict on whether this is a shippable implementation of the user request vs a keyword-dense placeholder.\n\nBE SKEPTICAL. Keyword matching already passed — your job is to catch what keyword matching misses. If the agent shipped a working build, say so. If it shipped a stub, say so. Don't grade on effort.\n\nReturn STRICT JSON. No prose outside the JSON.`\n}\n\n// ─── Runner ─────────────────────────────────────────────────────────────\n\n/**\n * Run the semantic concept judge. Soft-fails to available=false on\n * LLM/JSON errors — callers in a MultiLayerVerifier pipeline can treat\n * that as \"skip\" rather than \"fail.\"\n */\nexport async function runSemanticConceptJudge(\n input: SemanticConceptJudgeInput,\n options: SemanticConceptJudgeOptions = {},\n): Promise<SemanticConceptJudgeResult> {\n const start = Date.now()\n const totalCount = input.expectedConcepts.length\n\n if (totalCount === 0) {\n return {\n kind: 'semantic-concept',\n version: SEMANTIC_CONCEPT_JUDGE_VERSION,\n score: 0,\n presentCount: 0,\n totalCount: 0,\n findings: [],\n summary: 'no expected concepts declared',\n durationMs: 0,\n costUsd: null,\n available: false,\n error: 'no expected concepts declared',\n }\n }\n\n const opts: Required<SemanticConceptJudgeOptions> = {\n model: options.model ?? DEFAULT_MODEL,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT,\n maxTokens: options.maxTokens ?? DEFAULT_MAX_TOKENS,\n maxSourceChars: options.maxSourceChars ?? DEFAULT_MAX_SOURCE,\n maxPerFileChars: options.maxPerFileChars ?? DEFAULT_MAX_PER_FILE,\n maxHtmlChars: options.maxHtmlChars ?? DEFAULT_MAX_HTML,\n llm: options.llm ?? {},\n costLedger: options.costLedger ?? new CostLedger(),\n costPhase: options.costPhase ?? 'judge.semantic-concept',\n signal: options.signal ?? new AbortController().signal,\n weightConcepts: options.weightConcepts ?? 'mean',\n complexityWeights: { ...DEFAULT_COMPLEXITY_WEIGHTS, ...(options.complexityWeights ?? {}) },\n }\n\n // Build a name → weight map for aggregation. Mean strategy keeps every\n // weight at 1 (uniform average). Complexity strategy reads the table\n // and lets an explicit `weight` override. Explicit strategy uses ONLY\n // the spec's `weight` (defaulting to 1).\n const weightForConcept = (spec: ConceptSpec): number => {\n if (opts.weightConcepts === 'mean') return 1\n if (spec.weight != null) return spec.weight\n if (opts.weightConcepts === 'complexity') {\n return opts.complexityWeights[spec.complexity ?? 'render'] ?? 1\n }\n return 1\n }\n const weightByName = new Map<string, number>(\n input.expectedConcepts.map((c) => [c.name, weightForConcept(c)]),\n )\n\n let receipt: CostReceipt | undefined\n try {\n const request = {\n model: opts.model,\n messages: [\n {\n role: 'system' as const,\n content:\n 'You are a strict code-review judge. Return strict JSON only. No prose outside the JSON. A keyword in a comment is NOT a working implementation.',\n },\n { role: 'user' as const, content: buildPrompt(input, opts) },\n ],\n jsonSchema: { name: 'semantic_concept_judge', schema: SEMANTIC_SCHEMA },\n temperature: 0,\n maxTokens: opts.maxTokens,\n timeoutMs: opts.timeoutMs,\n } satisfies LlmCallRequest\n const paid = await opts.costLedger.runPaidCall({\n channel: 'judge',\n phase: opts.costPhase,\n actor: 'semantic-concept',\n model: opts.model,\n maximumCharge: maximumChargeForLlmRequest(request, opts.llm),\n signal: opts.signal,\n execute: (signal, callId) =>\n callLlmJson<{ summary: string; concepts: ConceptFinding[] }>(request, {\n ...opts.llm,\n signal,\n idempotencyKey: callId,\n }),\n receipt: ({ result }) => costReceiptFromLlm(result),\n receiptFromError: costReceiptFromLlmError,\n })\n receipt = paid.receipt\n if (!paid.succeeded) throw paid.error\n const { value } = paid.value\n\n if (!value?.concepts || !Array.isArray(value.concepts)) {\n throw new Error('judge returned malformed response — expected array under \"concepts\"')\n }\n\n const findings: ConceptFinding[] = value.concepts.map((c) => ({\n concept: String(c.concept),\n present: Boolean(c.present),\n score: Math.max(0, Math.min(10, Number(c.score ?? 0))),\n evidence: String(c.evidence ?? ''),\n severity: (['critical', 'major', 'minor', 'info'] as const).includes(c.severity)\n ? c.severity\n : 'info',\n }))\n\n const presentCount = findings.filter((f) => f.present && f.score >= 7).length\n let weightSum = 0\n let weightedScoreSum = 0\n for (const f of findings) {\n const w = weightByName.get(f.concept) ?? 1\n weightSum += w\n weightedScoreSum += w * f.score\n }\n const scoreAvg =\n weightSum > 0\n ? weightedScoreSum / weightSum\n : findings.reduce((a, f) => a + f.score, 0) / Math.max(1, findings.length)\n\n return {\n kind: 'semantic-concept',\n version: SEMANTIC_CONCEPT_JUDGE_VERSION,\n score: Number((scoreAvg / 10).toFixed(3)),\n presentCount,\n totalCount,\n findings,\n summary: String(value.summary ?? ''),\n durationMs: Date.now() - start,\n costUsd: paid.receipt.costUnknown ? null : paid.receipt.costUsd,\n available: true,\n }\n } catch (err) {\n return {\n kind: 'semantic-concept',\n version: SEMANTIC_CONCEPT_JUDGE_VERSION,\n score: 0,\n presentCount: 0,\n totalCount,\n findings: [],\n summary: '',\n durationMs: Date.now() - start,\n costUsd: receipt && !receipt.costUnknown ? receipt.costUsd : null,\n available: false,\n error: err instanceof Error ? err.message : String(err),\n }\n }\n}\n\n/**\n * Factory: pin LLM options once, return a closure that accepts inputs.\n * Convenient for pipelines that want to share a single LlmClient config.\n */\nexport function createSemanticConceptJudge(\n options: SemanticConceptJudgeOptions = {},\n): (input: SemanticConceptJudgeInput) => Promise<SemanticConceptJudgeResult> {\n return (input) => runSemanticConceptJudge(input, options)\n}\n"],"mappings":"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","names":["existsSync","existsSync","existsSync","readFileSync","existsSync","readFileSync"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/trace-analyst/prompts.ts","../src/trace-analyst/analyst.ts"],"sourcesContent":["/** Ax RLM prompt for bounded trace discovery and evidence-backed analysis. */\n\nexport const TRACE_ANALYST_ACTOR_DESCRIPTION = `You answer questions about an OTLP-shaped JSONL trace dataset using the trace tools provided in the \\`traces\\` namespace.\n\nDISCOVERY → NARROW → DEEP-READ protocol — follow exactly:\n\n1. ALWAYS call \\`traces.getDatasetOverview({})\\` FIRST without a regex_pattern. The result tells you total_traces, raw_jsonl_bytes, services, agents, models, and sample_trace_ids (real ids — never fabricate one).\n\n2. Use raw_jsonl_bytes to gauge how expensive raw scans will be. \\`filters.regex_pattern\\` is the one scan-heavy filter on getDatasetOverview / queryTraces / countTraces — narrow with indexed fields (has_errors, model_names, service_names, agent_names, time bounds) BEFORE adding a regex on a large dataset.\n\n3. To list more traces than the sample, call \\`traces.queryTraces({ filters?, limit, offset? })\\`. Each summary carries raw_jsonl_bytes — use it to choose between viewTrace and searchTrace BEFORE calling either.\n\n4. Per-trace inspection:\n - SMALL trace (raw_jsonl_bytes well under 150_000): call \\`traces.viewTrace({ trace_id })\\`. Returns all spans. Per-attribute payloads are head-capped at ~4KB; large \\`input.value\\` / \\`output.value\\` / \\`llm.input_messages\\` will show a \\`[trace-analyst truncated: N bytes]\\` marker.\n - LARGE trace (raw_jsonl_bytes near or above 150_000, or you saw an \\`oversized\\` response): use \\`traces.searchTrace({ trace_id, regex_pattern })\\` to get bounded SpanMatchRecords (span metadata + matched text + surrounding context). Then call \\`traces.viewSpans({ trace_id, span_ids: [...] })\\` for surgical reads (~16KB cap, 4× higher than discovery), or \\`traces.searchSpan({ trace_id, span_id, regex_pattern })\\` for one large span. Stays bounded regardless of trace size.\n - Useful regex patterns: \\`STATUS_CODE_ERROR\\` (failures), tool names like \\`grep\\` or \\`view_trace\\`, error strings like \\`MaxTurnsExceeded\\`, model names, attribute keys.\n\n5. ONLY call viewTrace / viewSpans / searchTrace / searchSpan with trace/span ids you have already seen in sample_trace_ids, a queryTraces page, or a previous search result. Never invent ids.\n\n5a. **Result-shape contract** — searchTrace and searchSpan return \\`{ trace_id, hits, total_matches, has_more }\\`. Iterate \\`result.hits\\` (NOT result.matches). Each hit has \\`{ span_id, span_name, span_kind, attribute_path, matched_text, context_before, context_after, match_offset }\\`. viewTrace returns \\`{ trace_id, spans }\\` (or \\`oversized\\`). viewSpans returns \\`{ trace_id, spans, missing_span_ids, truncated_attribute_count }\\`. Never assume a field name — log the result shape first if unsure.\n\n6. If viewTrace returns an \\`oversized\\` summary instead of \\`spans\\`, DO NOT retry the same call. Read the summary's top_span_names, span_count, span_response_bytes_max, error_span_count to plan a follow-up: switch to searchTrace (or searchSpan for one large span), then viewSpans on a smaller, surgical span_ids set.\n\n7. If searchTrace or searchSpan returns has_more=true, REFINE the regex to be more specific rather than blindly raising max_matches.\n\n8. If a tool errors (invalid regex, range error), STOP and reconsider — don't retry with a guessed id or argument. Use the discovery tools above to recover.\n\n9. If a ~4KB-truncated payload from viewTrace / searchTrace matters for your answer, first try viewSpans on that span id (~16KB cap). If a 16KB-truncated payload from viewSpans still matters, narrow further with searchSpan against a more specific regex rather than asking for the full payload again.\n\n10. If maxDepth > 0 and the question splits into independent semantic branches, delegate well-defined subtasks to subagents using \\`await llmQuery(...)\\`. Pass narrow context and a focused query. Examples:\n\n const reviews = await llmQuery([\n { query: 'Drill into trace abc123 — what tool calls preceded the failure?', context: { trace_id: 'abc123' } },\n { query: 'Drill into trace def456 — same failure mode?', context: { trace_id: 'def456' } },\n ]);\n\nOBSERVABILITY rules:\n- Each non-final actor turn must emit at least one \\`console.log(...)\\` for evidence. Up to 3 logs per turn is fine when correlating multiple data sources (e.g. one log for findings list, one for source-file content, one for derived analysis).\n- Do NOT combine \\`console.log\\` with \\`final(...)\\` or \\`askClarification(...)\\` in the same turn — finish gathering data first, then call final on its own turn.\n- Reuse runtime variables across turns; don't recompute.\n- When done, call \\`await final(answer)\\` with the fully-formed report. The responder rewrites the answer into output fields; if you only pass a vague summary string the responder has nothing concrete to format.\n\nCRITICAL — \\`final()\\` payload contract for evidence-grounded analysis tasks:\n- Pass a STRUCTURED object as the second arg with the actual data the responder needs to format the answer. Do NOT pass abstract instructions; pass evidence.\n- Example for per-item verdict tasks:\n \\`\\`\\`js\n await final(\"Format the per-item verdict report from the evidence below.\", {\n findings: [\n { id: 'sub-1-finding-1', claim: '...', verdict: 'TRUE-POSITIVE', evidence: 'lines 42-45 of contracts/X.sol show ...' },\n ...all items\n ],\n systemic_summary: '3 sentences I wrote based on the evidence above'\n });\n \\`\\`\\`\n- Calling \\`final(\"answer\", {})\\` with no evidence is a failure mode — the responder will hallucinate or echo back the field names. Always include the gathered data.\n- Premature final after a single viewSpans call is INSUFFICIENT for per-finding analysis tasks. Read the requested attributes (e.g. \\`spans[i].attributes['redteam.finding.title']\\`), and for each one perform the requested cross-reference (e.g. read the source SPAN's \\`attributes['source.content']\\`).\n\nOUTPUT contract — your final answer must include:\n- A clear prose conclusion answering the user's question.\n- Trace ids and span ids cited as evidence for each claim.\n- Failure modes named in the user's domain language, with frequency and concrete examples.\n\nDo NOT invent trace ids, span ids, error messages, or model names. Every fact must be traceable to a tool result.`\n\nexport const TRACE_ANALYST_ACTOR_DESCRIPTION_VERSION = 'trace-analyst-actor-v5-2026-05-06'\n\n/** Subagent prompt for focused trace-inspection subtasks. */\nexport const TRACE_ANALYST_SUBAGENT_DESCRIPTION = `You are a trace-analyst subagent. Your parent has delegated a focused trace-inspection question. Use the same DISCOVERY → NARROW → DEEP-READ protocol but stay tightly scoped: do exactly what was asked, return a concise compact answer, do NOT spawn further subagents unless the parent's question is genuinely multi-branch.\n\nCite trace ids and span ids for every claim. Do NOT invent ids.`\n","import { type AxActorTurn, type AxAIService, type AxFunction, AxJSRuntime, agent } from '@ax-llm/ax'\nimport {\n TRACE_ANALYST_ACTOR_DESCRIPTION,\n TRACE_ANALYST_ACTOR_DESCRIPTION_VERSION,\n TRACE_ANALYST_SUBAGENT_DESCRIPTION,\n} from './prompts'\nimport type { TraceAnalysisStore } from './store'\nimport { OtlpFileTraceStore, TraceFileMissingError } from './store-otlp'\nimport { buildTraceAnalystTools } from './tools'\n\nexport interface AnalyzeTracesInput {\n /** The user-facing question. Domain framing belongs here, not in the\n * actor description. */\n question: string\n}\n\nexport interface AnalyzeTracesResult {\n /** The responder's prose answer. */\n answer: string\n /** Bulleted findings extracted from the responder's structured output. */\n findings: string[]\n /** Per-actor-turn snapshots captured via `actorTurnCallback`. */\n turns: AnalyzeTracesTurnSnapshot[]\n /** Total turns the actor took. */\n turnCount: number\n /** Token usage by role. */\n usage: TraceAnalystUsage\n /** Full system + assistant + tool message log by role. */\n chatLog: TraceAnalystChatLog\n /** Prompt version that produced this run. */\n actorPromptVersion: string\n}\n\nexport interface TraceAnalystUsage {\n actor: TraceAnalystUsageEntry[]\n responder: TraceAnalystUsageEntry[]\n}\n\nexport interface TraceAnalystUsageEntry {\n [key: string]: unknown\n}\n\nexport interface TraceAnalystChatLog {\n actor: TraceAnalystChatMessage[]\n responder: TraceAnalystChatMessage[]\n}\n\nexport interface TraceAnalystChatMessage {\n [key: string]: unknown\n}\n\nexport interface AnalyzeTracesTurnSnapshot {\n turn: number\n isError: boolean\n /** The JS code the actor produced for this turn. */\n code: string\n /** The formatted action-log entry the actor sees on the next turn. */\n output: string\n /** Provider thought (when `actorOptions.showThoughts` is true and the\n * provider returns it). */\n thought?: string\n}\n\nexport interface AnalyzeTracesOptions {\n /** Trace data source. Pass either an OTLP-JSONL path or a custom store. */\n source: string | TraceAnalysisStore\n /** Caller-provided AxAIService. */\n ai: AxAIService\n /** Model id forwarded to actor + responder. */\n model?: string\n /** Recursion depth. 0 = no sub-agent dispatch. Default 1. */\n maxDepth?: number\n /** Maximum actor turns. Default 12. */\n maxTurns?: number\n /** Maximum parallel sub-agent calls in batched llmQuery. Default 2. */\n maxParallelSubagents?: number\n /** Override the actor description. */\n actorDescription?: string\n /** Override the subagent description. */\n subagentDescription?: string\n /** Per-turn observability hook. */\n onTurn?: (turn: AnalyzeTracesTurnSnapshot) => void | Promise<void>\n /** Override max runtime characters per turn. Default 6000. */\n maxRuntimeChars?: number\n /** When set, every turn's snapshot is appended to this JSONL file\n * immediately. If the analyst crashes mid-loop (provider 503,\n * network error, validator reject) the partial reasoning is still\n * on disk. Replay the file with the responder afterward to recover\n * evidence. */\n progressLogPath?: string\n}\n\n/**\n * Run the trace analyst.\n *\n * Throws:\n * - `TraceFileMissingError` if `source` is a path and doesn't exist.\n * - `AxAgentClarificationError` if the analyst asks for clarification.\n * - Provider errors (auth, rate limits) propagate from the AI service.\n */\nexport async function analyzeTraces(\n input: AnalyzeTracesInput,\n options: AnalyzeTracesOptions,\n): Promise<AnalyzeTracesResult> {\n if (!input.question || typeof input.question !== 'string') {\n throw new TypeError('analyzeTraces: input.question must be a non-empty string')\n }\n\n const store: TraceAnalysisStore =\n typeof options.source === 'string'\n ? new OtlpFileTraceStore({ path: options.source })\n : options.source\n\n // Pre-warm file stores so missing inputs fail before the RLM starts.\n if (store instanceof OtlpFileTraceStore) {\n await store.ensureIndexed()\n }\n\n const tools: AxFunction[] = buildTraceAnalystTools({ store })\n const turns: AnalyzeTracesTurnSnapshot[] = []\n\n // Persist each turn as JSONL so interrupted analyst runs keep useful evidence.\n let progressFs: import('node:fs').WriteStream | undefined\n if (options.progressLogPath) {\n const { createWriteStream } = await import('node:fs')\n const { mkdir } = await import('node:fs/promises')\n const { dirname } = await import('node:path')\n await mkdir(dirname(options.progressLogPath), { recursive: true })\n progressFs = createWriteStream(options.progressLogPath, { flags: 'a' })\n }\n\n const actorTurnCallback = async (turn: AxActorTurn): Promise<void> => {\n const snap: AnalyzeTracesTurnSnapshot = {\n turn: turn.turn,\n isError: turn.isError,\n code: turn.code,\n output: turn.output,\n thought: turn.thought,\n }\n turns.push(snap)\n if (progressFs) {\n try {\n progressFs.write(`${JSON.stringify({ ...snap, ts: Date.now() })}\\n`)\n } catch {\n // Progress logging must never fail the analyst.\n }\n }\n if (options.onTurn) await options.onTurn(snap)\n }\n\n const maxDepth = options.maxDepth ?? 1\n const maxTurns = options.maxTurns ?? 12\n const maxParallelSubagents = options.maxParallelSubagents ?? 2\n const maxRuntimeChars = options.maxRuntimeChars ?? 6000\n const functions = tools as unknown as NonNullable<Parameters<typeof agent>[1]>['functions']\n\n const analyst = agent<{ question: string }, { answer: string; findings: string[] }>(\n // `reasoning!` is an internal (Ax `!`) scratchpad field: generated first to\n // force reason-before-conclude, stripped from the returned output — so the\n // consumed shape stays { answer, findings }. Brings the trace-analyst to the\n // same prose-first CoT ordering the kind-factory gets from its `report` field.\n 'question:string -> reasoning!:string, answer:string, findings:string[]',\n {\n agentIdentity: {\n name: 'TraceAnalyst',\n description:\n 'Analyzes OTLP-shaped JSONL traces using bounded discovery tools to identify systemic failure modes.',\n },\n contextFields: ['question'],\n runtime: new AxJSRuntime({\n permissions: [],\n blockDynamicImport: true,\n allowedModules: [],\n freezeIntrinsics: true,\n blockShadowRealm: true,\n // RLM stdout mode relies on runtime bindings persisting across turns.\n preventGlobalThisExtensions: false,\n }),\n mode: maxDepth > 0 ? 'advanced' : 'simple',\n recursionOptions: maxDepth > 0 ? { maxDepth } : undefined,\n maxTurns,\n maxRuntimeChars,\n maxBatchedLlmQueryConcurrency: maxParallelSubagents,\n promptLevel: 'detailed',\n // Trace analysis depends on exact prior tool results and runtime variables.\n contextPolicy: { preset: 'full', budget: 'balanced' },\n functions,\n actorOptions: {\n description: options.actorDescription ?? TRACE_ANALYST_ACTOR_DESCRIPTION,\n ...(options.model ? { model: options.model } : {}),\n // Keep actor messages tool-call/content shaped across reasoning models.\n showThoughts: false,\n thinkingTokenBudget: 'none',\n },\n responderOptions: {\n ...(options.model ? { model: options.model } : {}),\n description: options.subagentDescription ?? TRACE_ANALYST_SUBAGENT_DESCRIPTION,\n showThoughts: false,\n },\n actorTurnCallback,\n bubbleErrors: [TraceFileMissingError],\n },\n )\n\n let result: { answer: unknown; findings: unknown }\n try {\n result = await analyst.forward(options.ai, { question: input.question })\n } finally {\n if (progressFs) {\n await new Promise<void>((resolve) => progressFs!.end(() => resolve()))\n }\n }\n\n return {\n answer: typeof result.answer === 'string' ? result.answer : String(result.answer ?? ''),\n findings: Array.isArray(result.findings)\n ? result.findings.filter((s): s is string => typeof s === 'string')\n : [],\n turns,\n turnCount: turns.length,\n usage: normalizeRoleArrays(analyst.getUsage()),\n chatLog: normalizeRoleArrays(analyst.getChatLog()),\n actorPromptVersion: TRACE_ANALYST_ACTOR_DESCRIPTION_VERSION,\n }\n}\n\nfunction normalizeRoleArrays(value: unknown): {\n actor: Record<string, unknown>[]\n responder: Record<string, unknown>[]\n} {\n const record = value && typeof value === 'object' ? (value as Record<string, unknown>) : {}\n return {\n actor: normalizeRecordArray(record.actor),\n responder: normalizeRecordArray(record.responder),\n }\n}\n\nfunction normalizeRecordArray(value: unknown): Record<string, unknown>[] {\n if (!Array.isArray(value)) return []\n return value.map((item) =>\n item && typeof item === 'object' ? { ...(item as Record<string, unknown>) } : { value: item },\n )\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cost-ledger.ts"],"sourcesContent":["import { z } from 'zod'\nimport { ValidationError } from './errors'\nimport { estimateCost, isModelPriced, resolveModelPricing } from './metrics'\n\nexport type CostChannel = 'agent' | 'judge' | 'verifier' | 'analyst' | 'driver' | (string & {})\n\nexport interface CostUsage {\n inputTokens: number\n outputTokens: number\n cachedTokens?: number\n}\n\ninterface CostCallBase {\n callId: string\n channel: CostChannel\n phase: string\n actor: string\n model: string\n maximumCostUsd?: number\n tags?: Record<string, string>\n timestamp: number\n}\n\nexport interface PendingCostCall extends CostCallBase {\n status: 'pending'\n}\n\nexport interface CostReceipt extends CostCallBase, CostUsage {\n status: 'settled'\n costUsd: number\n costUnknown: boolean\n usageUnknown?: boolean\n pricing?: {\n inputUsdPerThousand: number\n outputUsdPerThousand: number\n }\n actualCostUsd?: number\n error?: string\n}\n\nexport type CostLedgerRecord = PendingCostCall | CostReceipt\n\n/** @deprecated Read-only compatibility shape. New paid work uses `runPaidCall`. */\nexport type CostLedgerEntry = Omit<\n CostReceipt,\n 'status' | 'callId' | 'phase' | 'actor' | 'maximumCostUsd' | 'usageUnknown' | 'pricing' | 'error'\n>\n\nexport interface CostReceiptInput extends CostUsage {\n model: string\n actualCostUsd?: number\n costUnknown?: boolean\n usageUnknown?: boolean\n}\n\nexport type MaximumCharge =\n | { externallyEnforcedMaximumUsd: number }\n | ({ model: string } & CostUsage)\n\nexport interface RunPaidCallInput<T> {\n callId?: string\n channel: CostChannel\n phase: string\n actor: string\n /** Used before a provider receipt exists and on failures without one. */\n model?: string\n tags?: Record<string, string>\n signal?: AbortSignal\n /** Provider-enforced dollar maximum, or maximum priced token usage. Required when capped. */\n maximumCharge?: MaximumCharge\n /** `callId` can be forwarded as the provider's idempotency key. */\n execute(signal: AbortSignal, callId: string): Promise<T>\n receipt(value: T): CostReceiptInput\n receiptFromError?(error: Error): CostReceiptInput | undefined\n}\n\nexport type PaidCallResult<T> =\n | { succeeded: true; callId: string; value: T; receipt: CostReceipt }\n | { succeeded: false; callId?: string; error: Error; receipt?: CostReceipt }\n\nexport interface ChannelRollup {\n channel: CostChannel\n calls: number\n inputTokens: number\n outputTokens: number\n cachedTokens: number\n costUsd: number\n unpricedCalls: number\n unknownUsageCalls: number\n}\n\nexport interface CostLedgerSummary {\n totalCalls: number\n pendingCalls: number\n unresolvedCalls: number\n reservedCostUsd: number\n inputTokens: number\n outputTokens: number\n cachedTokens: number\n totalCostUsd: number\n byChannel: ChannelRollup[]\n unpricedModels: string[]\n fullyPriced: boolean\n usageComplete: boolean\n accountingComplete: boolean\n incompleteReasons: string[]\n}\n\nexport interface CostLedgerFilter {\n channel?: CostChannel\n phase?: string\n tags?: Record<string, string>\n}\n\n/** Append-only storage. `append` must atomically reject stale revisions. */\nexport interface CostLedgerPersistence {\n read(): { revision: string; events: string }\n append(expectedRevision: string, event: string): string | undefined\n}\n\nexport interface CostLedgerOptions {\n costCeilingUsd?: number\n persistence?: CostLedgerPersistence\n /** Import already-settled receipts without admitting new paid work. */\n receipts?: readonly CostReceipt[]\n}\n\nexport class CostCeilingReachedError extends ValidationError {\n constructor(\n ceilingUsd: number,\n committedAndReservedUsd: number,\n requestedUsd: number,\n phase: string,\n actor: string,\n ) {\n super(\n `CostLedger: reserving ${requestedUsd} for '${actor}' during '${phase}' would exceed ceiling ${ceilingUsd} with ${committedAndReservedUsd} already committed or reserved`,\n )\n }\n}\n\nexport class CostAccountingIncompleteError extends ValidationError {}\n\nexport class CostReservationExceededError extends ValidationError {\n constructor(actor: string, actualUsd: number, maximumUsd: number) {\n super(\n `CostLedger: '${actor}' charged ${actualUsd}, exceeding its enforced maximum ${maximumUsd}`,\n )\n }\n}\n\nexport class CostCallConflictError extends ValidationError {\n readonly callId?: string\n readonly receipt?: CostReceipt\n\n constructor(\n message: string,\n options: { callId?: string; receipt?: CostReceipt; cause?: unknown } = {},\n ) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause })\n this.callId = options.callId\n this.receipt = options.receipt ? cloneReceipt(options.receipt) : undefined\n }\n}\n\nexport class CostLedgerPersistenceError extends ValidationError {\n readonly callId?: string\n readonly receipt?: CostReceipt\n\n constructor(cause: unknown, callId?: string, receipt?: CostReceipt) {\n super(\n `CostLedger: failed to persist${callId ? ` call '${callId}'` : ''}: ${toError(cause).message}`,\n { cause },\n )\n this.callId = callId\n this.receipt = receipt ? cloneReceipt(receipt) : undefined\n }\n}\n\nexport class CostReceiptCaptureError extends ValidationError {\n readonly callId: string\n readonly receipt?: CostReceipt\n readonly receiptError: Error\n\n constructor(callId: string, cause: unknown, receiptError: unknown, receipt?: CostReceipt) {\n super(`CostLedger: could not capture the provider receipt for call '${callId}'`, { cause })\n this.callId = callId\n this.receipt = receipt ? cloneReceipt(receipt) : undefined\n this.receiptError = toError(receiptError)\n }\n}\n\ninterface CostCallEvent {\n version: 1\n record: CostLedgerRecord\n}\n\ninterface CompletedTasksEvent {\n version: 1\n completedTasks: number\n}\n\ninterface CostLimitEvent {\n version: 1\n costCeilingUsd: number\n}\n\ntype CostLedgerEvent = CostCallEvent | CompletedTasksEvent | CostLimitEvent\n\n/** Run-wide paid-call admission, durable call state, receipts, and summaries. */\nexport class CostLedger {\n private readonly records = new Map<string, CostLedgerRecord>()\n private readonly activeCallIds = new Set<string>()\n private readonly lateCallIds = new Set<string>()\n private completedTasks = 0\n private revision = 'memory'\n private costLimitPersisted = false\n readonly costCeilingUsd?: number\n private readonly persistence?: CostLedgerPersistence\n\n constructor(input?: number | CostLedgerOptions) {\n const options = typeof input === 'number' ? { costCeilingUsd: input } : (input ?? {})\n this.persistence = options.persistence\n if (options.costCeilingUsd !== undefined) {\n assertNonNegative(options.costCeilingUsd, 'costCeilingUsd')\n }\n\n let persistedCostCeilingUsd: number | undefined\n if (this.persistence) {\n let stored: ReturnType<CostLedgerPersistence['read']>\n try {\n stored = this.persistence.read()\n } catch (cause) {\n throw new CostLedgerPersistenceError(cause)\n }\n assertString(stored.revision, 'persistence revision')\n this.revision = stored.revision\n const restored = parseEvents(stored.events)\n for (const record of restored.records) this.records.set(record.callId, record)\n this.completedTasks = restored.completedTasks\n persistedCostCeilingUsd = restored.costCeilingUsd\n }\n\n if (\n options.costCeilingUsd !== undefined &&\n persistedCostCeilingUsd !== undefined &&\n options.costCeilingUsd !== persistedCostCeilingUsd\n ) {\n throw new ValidationError(\n `CostLedger: requested cost ceiling ${options.costCeilingUsd} does not match persisted ceiling ${persistedCostCeilingUsd}`,\n )\n }\n this.costCeilingUsd = persistedCostCeilingUsd ?? options.costCeilingUsd\n this.costLimitPersisted =\n !this.persistence ||\n this.costCeilingUsd === undefined ||\n persistedCostCeilingUsd !== undefined\n\n if (\n this.costCeilingUsd !== undefined &&\n [...this.records.values()].some(\n (record) => record.status === 'pending' && record.maximumCostUsd === undefined,\n )\n ) {\n throw new ValidationError('CostLedger: capped event log contains an unbounded pending call')\n }\n\n if (options.receipts?.length) {\n const imported = options.receipts.map((receipt, index) =>\n parseImportedReceipt(receipt, `imported receipt ${index + 1}`),\n )\n this.ensureCostLimitPersisted()\n for (const receipt of imported) this.appendRecord(receipt)\n }\n }\n\n async runPaidCall<T>(input: RunPaidCallInput<T>): Promise<PaidCallResult<T>> {\n let callId: string | undefined\n let pending: PendingCostCall | undefined\n try {\n callId = resolveCallId(input.callId)\n validateAttribution(input)\n if (input.signal?.aborted) {\n return { succeeded: false, callId, error: abortError(input.signal) }\n }\n if (this.records.has(callId)) {\n return {\n succeeded: false,\n callId,\n error: new CostCallConflictError(`CostLedger: callId '${callId}' already exists`),\n }\n }\n this.ensureCostLimitPersisted(callId)\n\n const summary = this.summary()\n if (summary.unresolvedCalls > 0) {\n return {\n succeeded: false,\n callId,\n error: new CostAccountingIncompleteError(\n `CostLedger: ${summary.unresolvedCalls} unresolved call(s) must be reconciled before new paid work`,\n ),\n }\n }\n\n const maximumCostUsd = this.resolveMaximum(input.maximumCharge)\n if (this.costCeilingUsd !== undefined && this.hasIncompleteSettledCall()) {\n return {\n succeeded: false,\n callId,\n error: new CostAccountingIncompleteError(\n `CostLedger: accounting is incomplete; refusing paid call '${input.actor}' during '${input.phase}'`,\n ),\n }\n }\n if (this.costCeilingUsd !== undefined) {\n const committedAndReserved = summary.totalCostUsd + summary.reservedCostUsd\n if (committedAndReserved + maximumCostUsd! > this.costCeilingUsd) {\n return {\n succeeded: false,\n callId,\n error: new CostCeilingReachedError(\n this.costCeilingUsd,\n committedAndReserved,\n maximumCostUsd!,\n input.phase,\n input.actor,\n ),\n }\n }\n }\n\n pending = {\n status: 'pending',\n callId,\n channel: input.channel,\n phase: input.phase,\n actor: input.actor,\n model: pendingModel(input),\n ...(maximumCostUsd === undefined ? {} : { maximumCostUsd }),\n ...(input.tags ? { tags: { ...input.tags } } : {}),\n timestamp: Date.now(),\n }\n this.appendRecord(pending)\n this.activeCallIds.add(callId)\n } catch (error) {\n return { succeeded: false, ...(callId ? { callId } : {}), error: toError(error) }\n }\n\n try {\n return await this.execute(input, pending)\n } catch (error) {\n return { succeeded: false, callId: pending.callId, error: toError(error) }\n } finally {\n if (!this.lateCallIds.has(pending.callId)) this.activeCallIds.delete(pending.callId)\n }\n }\n\n /** Settle a call left pending by a crashed process after reconciling with the provider. */\n reconcile(\n callId: string,\n observed: CostReceiptInput,\n options: { error?: string } = {},\n ): CostReceipt {\n const pending = [...this.records.values()].find(\n (record): record is PendingCostCall =>\n record.callId === callId && record.status === 'pending',\n )\n if (!pending) throw new CostCallConflictError(`CostLedger: no pending call '${callId}'`)\n if (this.activeCallIds.has(callId)) {\n throw new CostCallConflictError(`CostLedger: call '${callId}' is still active`)\n }\n this.ensureCostLimitPersisted(callId)\n return this.commitReceipt(pending, observed, options.error)\n }\n\n list(filter?: CostLedgerFilter): CostReceipt[] {\n return [...this.records.values()]\n .filter((record): record is CostReceipt => record.status === 'settled')\n .filter((receipt) => matches(receipt, filter))\n .map(cloneReceipt)\n }\n\n summary(filter?: CostLedgerFilter): CostLedgerSummary {\n const records = [...this.records.values()].filter((record) => matches(record, filter))\n const pending = records.filter(\n (record): record is PendingCostCall => record.status === 'pending',\n )\n const receipts = records.filter((record): record is CostReceipt => record.status === 'settled')\n const byChannel = new Map<string, ChannelRollup>()\n const unpriced = new Set<string>()\n const incompleteReasons: string[] = pending.map(\n (record) => `call '${record.callId}' for '${record.actor}' is pending`,\n )\n let inputTokens = 0\n let outputTokens = 0\n let cachedTokens = 0\n let totalCostUsd = 0\n\n for (const receipt of receipts) {\n inputTokens += receipt.inputTokens\n outputTokens += receipt.outputTokens\n cachedTokens += receipt.cachedTokens ?? 0\n totalCostUsd += receipt.costUsd\n if (receipt.costUnknown) {\n unpriced.add(receipt.model)\n incompleteReasons.push(\n receipt.error ?? `cost unknown for '${receipt.actor}' using '${receipt.model}'`,\n )\n }\n if (receipt.usageUnknown) {\n incompleteReasons.push(\n `token usage unknown for '${receipt.actor}' using '${receipt.model}'`,\n )\n }\n if (receipt.maximumCostUsd !== undefined && receipt.costUsd > receipt.maximumCostUsd) {\n incompleteReasons.push(\n `'${receipt.actor}' charged ${receipt.costUsd}, exceeding its enforced maximum ${receipt.maximumCostUsd}`,\n )\n }\n const rollup = byChannel.get(receipt.channel) ?? emptyRollup(receipt.channel)\n rollup.calls += 1\n rollup.inputTokens += receipt.inputTokens\n rollup.outputTokens += receipt.outputTokens\n rollup.cachedTokens += receipt.cachedTokens ?? 0\n rollup.costUsd += receipt.costUsd\n if (receipt.costUnknown) rollup.unpricedCalls += 1\n if (receipt.usageUnknown) rollup.unknownUsageCalls += 1\n byChannel.set(receipt.channel, rollup)\n }\n\n return {\n totalCalls: receipts.length,\n pendingCalls: pending.length,\n unresolvedCalls: pending.filter(\n (record) => !this.activeCallIds.has(record.callId) || this.lateCallIds.has(record.callId),\n ).length,\n reservedCostUsd: pending.reduce((sum, record) => sum + (record.maximumCostUsd ?? 0), 0),\n inputTokens,\n outputTokens,\n cachedTokens,\n totalCostUsd,\n byChannel: [...byChannel.values()].sort((a, b) => a.channel.localeCompare(b.channel)),\n unpricedModels: [...unpriced].sort(),\n fullyPriced: unpriced.size === 0,\n usageComplete: receipts.every((receipt) => !receipt.usageUnknown),\n accountingComplete: incompleteReasons.length === 0,\n incompleteReasons: [...new Set(incompleteReasons)],\n }\n }\n\n markCompleted(count = 1): void {\n if (!Number.isInteger(count) || count < 0) {\n throw new ValidationError(\n `CostLedger.markCompleted: count must be a non-negative integer, got ${count}`,\n )\n }\n if (count === 0) return\n this.ensureCostLimitPersisted()\n this.appendEvent({ version: 1, completedTasks: count })\n this.completedTasks += count\n }\n\n costPerCompletedTask(): number | null {\n return this.completedTasks === 0 ? null : this.summary().totalCostUsd / this.completedTasks\n }\n\n private async execute<T>(\n input: RunPaidCallInput<T>,\n pending: PendingCostCall,\n ): Promise<PaidCallResult<T>> {\n const signal = input.signal ?? new AbortController().signal\n if (signal.aborted) {\n return this.commitOutcome(pending, abortError(signal), {\n model: pending.model,\n inputTokens: 0,\n outputTokens: 0,\n actualCostUsd: 0,\n })\n }\n\n const operation = Promise.resolve().then(() => input.execute(signal, pending.callId))\n const settled = await settle(operation, signal)\n if (settled.kind === 'aborted') {\n this.lateCallIds.add(pending.callId)\n this.captureLateOutcome(input, pending, operation)\n return paidFailure(pending.callId, abortError(signal))\n }\n if (settled.kind === 'error') {\n let observed: CostReceiptInput | undefined\n try {\n observed = input.receiptFromError?.(settled.error)\n } catch (receiptError) {\n return this.captureFailure(pending, settled.error, receiptError)\n }\n return this.commitOutcome(pending, settled.error, observed ?? unknownReceipt(pending.model))\n }\n\n try {\n const receipt = this.commitReceipt(pending, input.receipt(settled.value))\n if (receipt.maximumCostUsd !== undefined && receipt.costUsd > receipt.maximumCostUsd) {\n return paidFailure(\n pending.callId,\n new CostReservationExceededError(pending.actor, receipt.costUsd, receipt.maximumCostUsd),\n receipt,\n )\n }\n return { succeeded: true, callId: pending.callId, value: settled.value, receipt }\n } catch (receiptError) {\n if (\n receiptError instanceof CostLedgerPersistenceError ||\n receiptError instanceof CostCallConflictError\n ) {\n return paidFailure(pending.callId, receiptError)\n }\n return this.captureFailure(pending, receiptError, receiptError)\n }\n }\n\n private captureLateOutcome<T>(\n input: RunPaidCallInput<T>,\n pending: PendingCostCall,\n operation: Promise<T>,\n ): void {\n void operation\n .then(\n (value) => {\n if (this.records.get(pending.callId)?.status !== 'pending') return\n try {\n this.commitReceipt(pending, input.receipt(value))\n } catch {\n // A failed durable settlement leaves the reservation pending and blocks new paid work.\n }\n },\n (cause) => {\n if (this.records.get(pending.callId)?.status !== 'pending') return\n const error = toError(cause)\n try {\n const observed = input.receiptFromError?.(error)\n this.commitReceipt(pending, observed ?? unknownReceipt(pending.model), error.message)\n } catch (receiptError) {\n if (\n receiptError instanceof CostLedgerPersistenceError ||\n receiptError instanceof CostCallConflictError\n ) {\n return\n }\n this.captureFailure(pending, error, receiptError)\n }\n },\n )\n .finally(() => {\n this.lateCallIds.delete(pending.callId)\n this.activeCallIds.delete(pending.callId)\n })\n }\n\n private commitOutcome<T>(\n pending: PendingCostCall,\n error: Error,\n observed: CostReceiptInput,\n ): PaidCallResult<T> {\n try {\n const receipt = this.commitReceipt(pending, observed, error.message)\n return paidFailure(pending.callId, error, receipt)\n } catch (receiptError) {\n if (\n receiptError instanceof CostLedgerPersistenceError ||\n receiptError instanceof CostCallConflictError\n ) {\n return paidFailure(pending.callId, receiptError)\n }\n return this.captureFailure(pending, error, receiptError)\n }\n }\n\n private captureFailure<T>(\n pending: PendingCostCall,\n cause: unknown,\n receiptError: unknown,\n ): PaidCallResult<T> {\n try {\n const receipt = this.commitReceipt(\n pending,\n unknownReceipt(pending.model),\n toError(receiptError).message,\n )\n return paidFailure(\n pending.callId,\n new CostReceiptCaptureError(pending.callId, cause, receiptError, receipt),\n receipt,\n )\n } catch (error) {\n const typed = error instanceof Error ? error : toError(error)\n return paidFailure(pending.callId, typed)\n }\n }\n\n private commitReceipt(\n pending: PendingCostCall,\n observed: CostReceiptInput,\n error?: string,\n ): CostReceipt {\n const receipt = buildReceipt(pending, observed, error)\n if (this.records.get(pending.callId)?.status !== 'pending') {\n throw new CostCallConflictError(`CostLedger: call '${pending.callId}' is not pending`)\n }\n this.appendRecord(receipt)\n return cloneReceipt(receipt)\n }\n\n private resolveMaximum(maximum: MaximumCharge | undefined): number | undefined {\n if (!maximum) {\n if (this.costCeilingUsd !== undefined) {\n throw new CostAccountingIncompleteError(\n 'CostLedger: capped paid calls require a hard maximumCharge before execution',\n )\n }\n return undefined\n }\n if ('externallyEnforcedMaximumUsd' in maximum) {\n assertNonNegative(\n maximum.externallyEnforcedMaximumUsd,\n 'maximumCharge.externallyEnforcedMaximumUsd',\n )\n return maximum.externallyEnforcedMaximumUsd\n }\n const priced = costForUsage(maximum.model, maximum)\n if (priced.costUnknown) {\n if (this.costCeilingUsd !== undefined) {\n throw new CostAccountingIncompleteError(\n `CostLedger: cannot reserve unpriced model '${maximum.model}' in a capped run`,\n )\n }\n return undefined\n }\n return priced.costUsd\n }\n\n private hasIncompleteSettledCall(): boolean {\n return [...this.records.values()].some(\n (record) =>\n record.status === 'settled' &&\n (record.costUnknown ||\n record.usageUnknown ||\n (record.maximumCostUsd !== undefined && record.costUsd > record.maximumCostUsd)),\n )\n }\n\n private appendRecord(record: CostLedgerRecord): void {\n const callId = record.callId\n const receipt = record.status === 'settled' ? record : undefined\n validateTransition(this.records, record)\n const event: CostCallEvent = {\n version: 1,\n record: cloneRecord(record),\n }\n this.appendEvent(event, callId, receipt)\n this.records.set(callId, cloneRecord(record))\n }\n\n private ensureCostLimitPersisted(callId?: string): void {\n if (this.costLimitPersisted || this.costCeilingUsd === undefined) return\n this.appendEvent({ version: 1, costCeilingUsd: this.costCeilingUsd }, callId)\n this.costLimitPersisted = true\n }\n\n private appendEvent(event: CostLedgerEvent, callId?: string, receipt?: CostReceipt): void {\n try {\n if (this.persistence) {\n const nextRevision = this.persistence.append(this.revision, `${JSON.stringify(event)}\\n`)\n if (nextRevision === undefined) {\n throw new CostCallConflictError(\n `CostLedger: persisted revision changed while writing call '${callId}'`,\n { callId, receipt },\n )\n }\n assertString(nextRevision, 'persistence revision')\n this.revision = nextRevision\n }\n } catch (cause) {\n if (cause instanceof CostCallConflictError) throw cause\n throw new CostLedgerPersistenceError(cause, callId, receipt)\n }\n }\n}\n\n/** Public callback surface for a shared cost ledger.\n *\n * Declaration bundles may expose this type through multiple package subpaths.\n * Keeping callback contracts structural lets those subpaths compose while the\n * concrete {@link CostLedger} retains its private durable state.\n */\nexport type CostLedgerHandle = Pick<CostLedger, keyof CostLedger>\n\n/** Return the canonical pricing-table key, or null when the model is unpriced. */\nexport function modelPriceKey(model: string): string | null {\n return isModelPriced(model) ? model : null\n}\n\nexport interface CostResult {\n costUsd: number\n costUnknown: boolean\n}\n\nexport function costForUsage(model: string, usage: CostUsage): CostResult {\n assertUsage(usage)\n if (!resolveModelPricing(model)) return { costUsd: 0, costUnknown: true }\n return {\n costUsd: estimateCost(usage.inputTokens + (usage.cachedTokens ?? 0), usage.outputTokens, model),\n costUnknown: false,\n }\n}\n\ntype Settled<T> =\n | { kind: 'value'; value: T }\n | { kind: 'error'; error: Error }\n | { kind: 'aborted' }\n\nasync function settle<T>(promise: Promise<T>, signal: AbortSignal): Promise<Settled<T>> {\n return await new Promise((resolve) => {\n let done = false\n const finish = (value: Settled<T>): void => {\n if (done) return\n done = true\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n }\n const onAbort = () => finish({ kind: 'aborted' })\n signal.addEventListener('abort', onAbort, { once: true })\n if (signal.aborted) onAbort()\n promise.then(\n (value) => finish({ kind: 'value', value }),\n (error) => finish({ kind: 'error', error: toError(error) }),\n )\n })\n}\n\nfunction buildReceipt(\n pending: PendingCostCall,\n observed: CostReceiptInput,\n error?: string,\n): CostReceipt {\n assertUsage(observed)\n assertString(observed.model, 'receipt.model')\n const estimated = costForUsage(observed.model, observed)\n const hasActual = observed.actualCostUsd !== undefined\n if (hasActual && observed.costUnknown === true) {\n throw new ValidationError(\n 'CostLedger: a receipt cannot have both actualCostUsd and costUnknown=true',\n )\n }\n if (hasActual) assertNonNegative(observed.actualCostUsd!, 'actualCostUsd')\n const usageUnknown = observed.usageUnknown === true\n const costUnknown =\n observed.costUnknown === true || (!hasActual && (usageUnknown || estimated.costUnknown))\n const resolvedPricing = !hasActual && !costUnknown ? resolveModelPricing(observed.model) : null\n return parseReceipt(\n {\n status: 'settled',\n callId: pending.callId,\n channel: pending.channel,\n phase: pending.phase,\n actor: pending.actor,\n model: observed.model,\n inputTokens: observed.inputTokens,\n outputTokens: observed.outputTokens,\n ...(observed.cachedTokens === undefined ? {} : { cachedTokens: observed.cachedTokens }),\n costUsd: costUnknown ? 0 : hasActual ? observed.actualCostUsd! : estimated.costUsd,\n costUnknown,\n usageUnknown,\n ...(resolvedPricing\n ? {\n pricing: {\n inputUsdPerThousand: resolvedPricing.input,\n outputUsdPerThousand: resolvedPricing.output,\n },\n }\n : {}),\n ...(hasActual ? { actualCostUsd: observed.actualCostUsd } : {}),\n ...(pending.maximumCostUsd === undefined ? {} : { maximumCostUsd: pending.maximumCostUsd }),\n ...(error ? { error } : {}),\n ...(pending.tags ? { tags: { ...pending.tags } } : {}),\n timestamp: pending.timestamp,\n },\n 'provider receipt',\n )\n}\n\nconst NonEmptyString = z.string().refine((value) => value.trim().length > 0, 'must be non-empty')\nconst TokenCount = z.number().int().nonnegative().finite()\nconst NonNegative = z.number().nonnegative().finite()\nconst Positive = z.number().positive().finite()\nconst Tags = z.record(NonEmptyString, z.string())\nconst CostPricingSchema = z.strictObject({\n inputUsdPerThousand: Positive,\n outputUsdPerThousand: Positive,\n})\nconst CostCallBaseShape = {\n callId: NonEmptyString,\n channel: NonEmptyString,\n phase: NonEmptyString,\n actor: NonEmptyString,\n model: NonEmptyString,\n maximumCostUsd: NonNegative.optional(),\n tags: Tags.optional(),\n timestamp: NonNegative,\n}\nconst PendingCostCallSchema = z.strictObject({\n status: z.literal('pending'),\n ...CostCallBaseShape,\n})\nconst CostReceiptSchema = z\n .strictObject({\n status: z.literal('settled'),\n ...CostCallBaseShape,\n inputTokens: TokenCount,\n outputTokens: TokenCount,\n cachedTokens: TokenCount.optional(),\n costUsd: NonNegative,\n costUnknown: z.boolean(),\n usageUnknown: z.boolean().default(false),\n pricing: CostPricingSchema.optional(),\n actualCostUsd: NonNegative.optional(),\n error: z.string().optional(),\n })\n .superRefine((receipt, ctx) => {\n if (receipt.actualCostUsd !== undefined) {\n if (receipt.costUnknown || receipt.costUsd !== receipt.actualCostUsd) {\n ctx.addIssue({ code: 'custom', message: 'actual cost must be known and equal costUsd' })\n }\n if (receipt.pricing !== undefined) {\n ctx.addIssue({ code: 'custom', message: 'actual cost must not include estimated pricing' })\n }\n return\n }\n if (receipt.costUnknown) {\n if (receipt.costUsd !== 0) {\n ctx.addIssue({ code: 'custom', message: 'unknown cost must have costUsd 0' })\n }\n if (receipt.pricing !== undefined) {\n ctx.addIssue({ code: 'custom', message: 'unknown cost must not include estimated pricing' })\n }\n return\n }\n if (receipt.usageUnknown) {\n ctx.addIssue({ code: 'custom', message: 'known estimated cost requires known usage' })\n }\n if (!receipt.pricing) {\n ctx.addIssue({ code: 'custom', message: 'known estimated cost requires a pricing snapshot' })\n return\n }\n const expected = costFromPricing(receipt, receipt.pricing)\n if (receipt.costUsd !== expected) {\n ctx.addIssue({\n code: 'custom',\n message: `estimated cost ${receipt.costUsd} does not match pricing snapshot ${expected}`,\n })\n }\n })\nconst CostLedgerEventSchema = z.union([\n z.strictObject({\n version: z.literal(1),\n record: z.union([PendingCostCallSchema, CostReceiptSchema]),\n }),\n z.strictObject({\n version: z.literal(1),\n completedTasks: TokenCount,\n }),\n z.strictObject({\n version: z.literal(1),\n costCeilingUsd: NonNegative,\n }),\n])\n\nfunction parseEvents(serialized: string): {\n records: CostLedgerRecord[]\n completedTasks: number\n costCeilingUsd?: number\n} {\n const records = new Map<string, CostLedgerRecord>()\n let completedTasks = 0\n let costCeilingUsd: number | undefined\n let lineNumber = 0\n try {\n for (const line of serialized.split('\\n')) {\n if (!line.trim()) continue\n lineNumber += 1\n const event = CostLedgerEventSchema.parse(JSON.parse(line)) as CostLedgerEvent\n if ('record' in event) {\n validateTransition(records, event.record)\n records.set(event.record.callId, cloneRecord(event.record))\n } else if ('completedTasks' in event) {\n completedTasks += event.completedTasks\n if (!Number.isSafeInteger(completedTasks)) {\n throw new ValidationError('CostLedger: completed task count exceeds safe integer range')\n }\n } else {\n if (costCeilingUsd !== undefined) {\n throw new ValidationError('CostLedger: duplicate persisted cost ceiling')\n }\n costCeilingUsd = event.costCeilingUsd\n }\n }\n return {\n records: [...records.values()],\n completedTasks,\n ...(costCeilingUsd === undefined ? {} : { costCeilingUsd }),\n }\n } catch (cause) {\n throw new ValidationError(\n `CostLedger: invalid persisted event ${lineNumber || 1}: ${validationMessage(cause)}`,\n { cause },\n )\n }\n}\n\nfunction validateTransition(\n records: ReadonlyMap<string, CostLedgerRecord>,\n record: CostLedgerRecord,\n): void {\n const current = records.get(record.callId)\n if (!current) return\n if (record.status === 'pending' || current.status === 'settled') {\n throw new CostCallConflictError(`CostLedger: duplicate callId '${record.callId}'`)\n }\n if (!sameAttribution(current, record)) {\n throw new ValidationError(`CostLedger: receipt attribution changed for call '${record.callId}'`)\n }\n}\n\nfunction sameAttribution(before: CostCallBase, after: CostCallBase): boolean {\n return (\n before.channel === after.channel &&\n before.phase === after.phase &&\n before.actor === after.actor &&\n before.maximumCostUsd === after.maximumCostUsd &&\n before.timestamp === after.timestamp &&\n JSON.stringify(before.tags ?? {}) === JSON.stringify(after.tags ?? {})\n )\n}\n\nfunction parseReceipt(value: unknown, path: string): CostReceipt {\n try {\n return CostReceiptSchema.parse(value) as CostReceipt\n } catch (cause) {\n throw new ValidationError(`CostLedger: invalid ${path}: ${validationMessage(cause)}`, { cause })\n }\n}\n\nfunction parseImportedReceipt(value: unknown, path: string): CostReceipt {\n if (typeof value !== 'object' || value === null) return parseReceipt(value, path)\n const candidate = { ...value } as Record<string, unknown>\n if (\n candidate.status === 'settled' &&\n candidate.actualCostUsd === undefined &&\n candidate.costUnknown === false &&\n candidate.pricing === undefined &&\n typeof candidate.model === 'string'\n ) {\n const pricing = resolveModelPricing(candidate.model)\n if (pricing) {\n candidate.pricing = {\n inputUsdPerThousand: pricing.input,\n outputUsdPerThousand: pricing.output,\n }\n }\n }\n return parseReceipt(candidate, path)\n}\n\nfunction validateAttribution(\n input: Pick<RunPaidCallInput<unknown>, 'channel' | 'phase' | 'actor' | 'model' | 'tags'>,\n): void {\n assertString(input.channel, 'channel')\n assertString(input.phase, 'phase')\n assertString(input.actor, 'actor')\n if (input.model !== undefined) assertString(input.model, 'model')\n if (input.tags !== undefined) {\n const parsed = Tags.safeParse(input.tags)\n if (!parsed.success)\n throw new ValidationError(`CostLedger: invalid tags: ${parsed.error.message}`)\n }\n}\n\nfunction matches(record: CostCallBase, filter: CostLedgerFilter | undefined): boolean {\n if (!filter) return true\n if (filter.channel !== undefined && record.channel !== filter.channel) return false\n if (filter.phase !== undefined && record.phase !== filter.phase) return false\n return Object.entries(filter.tags ?? {}).every(([key, value]) => record.tags?.[key] === value)\n}\n\nfunction cloneRecord(record: CostLedgerRecord): CostLedgerRecord {\n return record.status === 'settled'\n ? cloneReceipt(record)\n : { ...record, tags: record.tags ? { ...record.tags } : undefined }\n}\n\nfunction cloneReceipt(receipt: CostReceipt): CostReceipt {\n return {\n ...receipt,\n tags: receipt.tags ? { ...receipt.tags } : undefined,\n pricing: receipt.pricing ? { ...receipt.pricing } : undefined,\n }\n}\n\nfunction costFromPricing(usage: CostUsage, pricing: NonNullable<CostReceipt['pricing']>): number {\n return (\n ((usage.inputTokens + (usage.cachedTokens ?? 0)) / 1000) * pricing.inputUsdPerThousand +\n (usage.outputTokens / 1000) * pricing.outputUsdPerThousand\n )\n}\n\nfunction emptyRollup(channel: CostChannel): ChannelRollup {\n return {\n channel,\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n costUsd: 0,\n unpricedCalls: 0,\n unknownUsageCalls: 0,\n }\n}\n\nfunction pendingModel(input: RunPaidCallInput<unknown>): string {\n if (input.model) return input.model\n if (input.maximumCharge && 'model' in input.maximumCharge) return input.maximumCharge.model\n return 'unknown'\n}\n\nfunction unknownReceipt(model: string): CostReceiptInput {\n return { model, inputTokens: 0, outputTokens: 0, costUnknown: true, usageUnknown: true }\n}\n\nfunction resolveCallId(input: string | undefined): string {\n if (input !== undefined) {\n assertString(input, 'callId')\n return input\n }\n if (typeof globalThis.crypto?.randomUUID !== 'function') {\n throw new ValidationError('CostLedger: crypto.randomUUID is required when callId is omitted')\n }\n return globalThis.crypto.randomUUID()\n}\n\nfunction abortError(signal: AbortSignal): Error {\n const reason = (signal as { reason?: unknown }).reason\n if (reason instanceof Error) return reason\n const error = new Error('CostLedger: paid call aborted')\n error.name = 'AbortError'\n return error\n}\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\nfunction paidFailure<T>(callId: string, error: Error, receipt?: CostReceipt): PaidCallResult<T> {\n return {\n succeeded: false,\n callId,\n error,\n ...(receipt ? { receipt: cloneReceipt(receipt) } : {}),\n }\n}\n\nfunction validationMessage(cause: unknown): string {\n return cause instanceof z.ZodError ? z.prettifyError(cause) : toError(cause).message\n}\n\nfunction assertUsage(usage: CostUsage): void {\n assertTokenCount(usage.inputTokens, 'inputTokens')\n assertTokenCount(usage.outputTokens, 'outputTokens')\n if (usage.cachedTokens !== undefined) assertTokenCount(usage.cachedTokens, 'cachedTokens')\n}\n\nfunction assertTokenCount(value: unknown, name: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {\n throw new ValidationError(\n `CostLedger: ${name} must be a non-negative integer, got ${String(value)}`,\n )\n }\n}\n\nfunction assertNonNegative(value: unknown, name: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {\n throw new ValidationError(\n `CostLedger: ${name} must be a non-negative finite number, got ${String(value)}`,\n )\n }\n}\n\nfunction assertString(value: unknown, name: string): asserts value is string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new ValidationError(`CostLedger: ${name} must be a non-empty string`)\n }\n}\n"],"mappings":"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","names":[]}