@ai-dossier/core 1.4.2 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -205,6 +205,38 @@ const verifier = registry.get('ed25519');
205
205
  const result = await verifier.verify(content, signature);
206
206
  ```
207
207
 
208
+ ### Agent Usage & Run Log
209
+
210
+ Shared with `packages/sched` so both the `ai-dossier run` headless path and the
211
+ scheduler's detached dispatch path agree on which block of an agent's result is the
212
+ source of record.
213
+
214
+ ```typescript
215
+ import {
216
+ parseAgentUsage, // claude: one --output-format json object, OR a stream-json event stream
217
+ parseOpenCodeUsage, // opencode: a `run --format json` JSONL event stream
218
+ usageParserFor, // pick the parser from the spawned binary's basename
219
+ runsLogPath, // ~/.dossier/runs.jsonl
220
+ SCHED_DISPATCH_EVENT, // the sched dispatch-log preamble `type`, skipped by both parsers
221
+ type AgentRunUsage,
222
+ type RunLogEntry,
223
+ } from '@ai-dossier/core';
224
+
225
+ const usage = parseAgentUsage(stdout);
226
+ // → { model, input_tokens, output_tokens, cache_creation_tokens,
227
+ // cache_read_tokens, total_cost_usd, result_text } — every field null
228
+ // when the agent did not report it; values are never fabricated.
229
+ ```
230
+
231
+ `parseAgentUsage` treats the agent's per-model **`modelUsage` map as the source of
232
+ record** whenever it carries at least one object-shaped entry, summed across models. The
233
+ top-level `usage` block is used only when `modelUsage` has no such entry — the two are
234
+ never blended field-by-field, because they have been observed to disagree enough to
235
+ fabricate a ~43% "saving" when mixed (ai-dossier#524). Cost is read from `costUSD` (the
236
+ key claude writes), falling back to the top-level total when `modelUsage` reports no cost
237
+ at all. For a `stream-json` log the final `type:"result"` event wins; with no such event
238
+ (an agent killed mid-run) per-turn `assistant` usage is summed instead.
239
+
208
240
  ## Types
209
241
 
210
242
  All TypeScript types are exported from the package root:
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Parsers for headless-agent JSON result output — the token/cost/model data
3
+ * an `ai-dossier run` or `packages/sched` dispatch needs to record in
4
+ * `runs.jsonl` (#458, #524).
5
+ *
6
+ * Shared between `cli` (the `ai-dossier run` headless path) and `sched` (the
7
+ * scheduler's detached-agent dispatch path) so both consumers agree on which
8
+ * block of a claude/opencode result is the source of record — the divergence
9
+ * between them (one reading `usage`, the other `modelUsage`, and disagreeing
10
+ * enough to fabricate a ~43% "saving" when mixed, ai-dossier#524) is exactly
11
+ * the bug this module exists to close off. Lives in `core`, not `cli`,
12
+ * because `sched` cannot depend on `cli` (the dependency runs the other way:
13
+ * `cli` already depends on both `core` and `sched`).
14
+ */
15
+ /**
16
+ * Usage data extracted from an agent CLI's JSON result output.
17
+ * Every field is null when the CLI did not report it — values are never
18
+ * fabricated or estimated.
19
+ */
20
+ export interface AgentRunUsage {
21
+ /** Model id the agent reported; comma-joined when several models ran (token/cost fields are totals across all). */
22
+ model: string | null;
23
+ input_tokens: number | null;
24
+ output_tokens: number | null;
25
+ /** Cache-creation (write) input tokens, summed across models when several ran. */
26
+ cache_creation_tokens: number | null;
27
+ /** Cache-read input tokens, summed across models when several ran. */
28
+ cache_read_tokens: number | null;
29
+ total_cost_usd: number | null;
30
+ /** The final result text (claude's `result` field), for re-emitting to stdout. */
31
+ result_text: string | null;
32
+ }
33
+ /**
34
+ * `type` of the preamble line `packages/sched` writes to a dispatch log at
35
+ * spawn time (ai-dossier#524). It exists so a log is never 0 bytes for a unit
36
+ * that ran; every parser here skips it rather than counting it as agent
37
+ * output. Shared from `core` so the writer (`sched`'s `createSpawnDeps`) and
38
+ * the readers (below) can never drift apart on the sentinel's spelling.
39
+ */
40
+ export declare const SCHED_DISPATCH_EVENT = "sched-dispatch";
41
+ /**
42
+ * Parse a claude headless result into usage data — both output formats.
43
+ *
44
+ * Accepts either shape, because the two consumers spawn claude differently:
45
+ *
46
+ * - **A single JSON object** (`--output-format json`, what `ai-dossier run`
47
+ * uses): parsed whole.
48
+ * - **A JSONL event stream** (`--output-format stream-json`, what the
49
+ * scheduler dispatches with since ai-dossier#524): the LAST `type:"result"`
50
+ * event wins — a per-unit log is append-mode, so a prior dispatch's result
51
+ * may precede this one in the same slice. With no `result` event at all (an
52
+ * agent killed mid-run), per-turn `assistant` usage is summed instead, so an
53
+ * interrupted dispatch still reports the tokens it really spent.
54
+ *
55
+ * Lines that do not parse as JSON objects are skipped rather than
56
+ * disqualifying the stream: the sched dispatch preamble
57
+ * ({@link SCHED_DISPATCH_EVENT}) sits at the head of every dispatch slice, and
58
+ * an agent killed mid-write leaves a truncated final line.
59
+ *
60
+ * Returns null when the output parses as neither shape (and for a stream
61
+ * holding no usage-bearing event). A result object that simply reported no
62
+ * usage yields an entry whose fields are all null, not `null` itself —
63
+ * "the agent reported nothing" and "there was no agent output" stay distinct.
64
+ */
65
+ export declare function parseAgentUsage(stdout: string | null | undefined): AgentRunUsage | null;
66
+ /**
67
+ * Parse an `opencode run --format json` result stream into usage data (#459).
68
+ *
69
+ * opencode emits one JSON event per line: the assistant's text arrives in
70
+ * `type:"text"` parts, and per-step token/cost totals in `type:"step_finish"`
71
+ * parts (a multi-step run emits several — tokens and cost are summed), with
72
+ * cache counts nested as `tokens.cache: { write, read }`. The model id is not
73
+ * present in the events, so `model` is null and callers fall back to the
74
+ * requested --model alias — that field, and only that field, is genuinely
75
+ * unavailable here rather than merely absent. Returns null when the output
76
+ * holds no opencode event at all; individual non-JSON lines (stderr warnings
77
+ * interleaved by the scheduler's merged stdout/stderr fd) are skipped, not
78
+ * treated as disqualifying.
79
+ *
80
+ * **Cross-agent caveat.** opencode reports `tokens.reasoning` SEPARATELY from
81
+ * `tokens.output` (a step's `total` is input + output + reasoning +
82
+ * cache.read), whereas claude folds thinking tokens into `output_tokens`.
83
+ * Reasoning is 45-75% of generated tokens in real logs, so an opencode
84
+ * `output_tokens` is NOT directly comparable to a claude one — do not put the
85
+ * two in the same column of a cost comparison without saying so. It is left
86
+ * out rather than summed in because this module never derives a value the
87
+ * agent did not report; capturing it needs a field of its own on
88
+ * {@link AgentRunUsage} and `RunLogEntry`, which is a schema change beyond
89
+ * ai-dossier#524's scope.
90
+ */
91
+ export declare function parseOpenCodeUsage(stdout: string | null | undefined): AgentRunUsage | null;
92
+ /**
93
+ * Pick the usage parser for a dispatched agent, keyed off the spawned
94
+ * binary's basename — `opencode` (any path) routes to
95
+ * {@link parseOpenCodeUsage}; everything else, including an
96
+ * operator-configured command this build doesn't specifically recognize,
97
+ * falls back to {@link parseAgentUsage} (the claude shape). A command this
98
+ * build doesn't recognize is not guessed at further than that fallback —
99
+ * its output either parses as a claude-shaped JSON result or the parser
100
+ * returns null, never a fabricated guess.
101
+ */
102
+ export declare function usageParserFor(cmd0: string): (stdout: string | null | undefined) => AgentRunUsage | null;
103
+ //# sourceMappingURL=agent-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-usage.d.ts","sourceRoot":"","sources":["../src/agent-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,mHAAmH;IACnH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kFAAkF;IAClF,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kFAAkF;IAClF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAsFD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AAoLrD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,GAAG,IAAI,CA6BvF;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,GAAG,IAAI,CA6F1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,GACX,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,aAAa,GAAG,IAAI,CAE7D"}
@@ -0,0 +1,493 @@
1
+ "use strict";
2
+ /**
3
+ * Parsers for headless-agent JSON result output — the token/cost/model data
4
+ * an `ai-dossier run` or `packages/sched` dispatch needs to record in
5
+ * `runs.jsonl` (#458, #524).
6
+ *
7
+ * Shared between `cli` (the `ai-dossier run` headless path) and `sched` (the
8
+ * scheduler's detached-agent dispatch path) so both consumers agree on which
9
+ * block of a claude/opencode result is the source of record — the divergence
10
+ * between them (one reading `usage`, the other `modelUsage`, and disagreeing
11
+ * enough to fabricate a ~43% "saving" when mixed, ai-dossier#524) is exactly
12
+ * the bug this module exists to close off. Lives in `core`, not `cli`,
13
+ * because `sched` cannot depend on `cli` (the dependency runs the other way:
14
+ * `cli` already depends on both `core` and `sched`).
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.SCHED_DISPATCH_EVENT = void 0;
51
+ exports.parseAgentUsage = parseAgentUsage;
52
+ exports.parseOpenCodeUsage = parseOpenCodeUsage;
53
+ exports.usageParserFor = usageParserFor;
54
+ const path = __importStar(require("node:path"));
55
+ /**
56
+ * Largest token count accepted from an agent (#524). Well above any real run
57
+ * (a 1M-token context ×1000 turns), and low enough that summing a cohort of
58
+ * them in `sched stats` cannot reach Infinity.
59
+ */
60
+ const MAX_REPORTED_TOKENS = 1e15;
61
+ /** Largest cost in USD accepted from an agent (#524) — no real dispatch approaches it. */
62
+ const MAX_REPORTED_COST_USD = 1e6;
63
+ /**
64
+ * Narrow untrusted agent output to a finite, non-negative number within a
65
+ * sane ceiling (#524). Used for token counts AND for costs — hence the
66
+ * explicit `max`, since the two have very different plausible ranges.
67
+ *
68
+ * The ceiling is not paranoia: `sched stats` sums these across a cohort, and
69
+ * a single `1e308` entry would carry the whole TOTAL row to Infinity, which
70
+ * the formatter renders as `-` — silently blanking every legitimate run
71
+ * alongside it. Out-of-range values are rejected (null = "not reported")
72
+ * rather than clamped, so a bogus number is never presented as a real one.
73
+ */
74
+ function toBounded(value, max) {
75
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= max
76
+ ? value
77
+ : null;
78
+ }
79
+ /** Token-count flavour of {@link toBounded}. */
80
+ function toCount(value) {
81
+ return toBounded(value, MAX_REPORTED_TOKENS);
82
+ }
83
+ /** Cost flavour of {@link toBounded} — a USD amount, not a count. */
84
+ function toCost(value) {
85
+ return toBounded(value, MAX_REPORTED_COST_USD);
86
+ }
87
+ /** Longest `model` value written to `runs.jsonl` before truncation (#524). */
88
+ const MAX_MODEL_LENGTH = 200;
89
+ /**
90
+ * Most model names joined into one `model` value (#524). The map/stream those
91
+ * names come from is agent-controlled and unbounded, so the join is capped
92
+ * before {@link sanitizeModel} ever sees it — 16 distinct models in one run
93
+ * is already far beyond anything real.
94
+ */
95
+ const MAX_MODELS_JOINED = 16;
96
+ /** Join model names for the `model` field, bounded by {@link MAX_MODELS_JOINED}. */
97
+ function joinModels(names) {
98
+ if (names.length === 0)
99
+ return null;
100
+ if (names.length === 1)
101
+ return names[0];
102
+ return names.slice(0, MAX_MODELS_JOINED).join(',');
103
+ }
104
+ /**
105
+ * `model` is copied verbatim from untrusted agent JSON into a `runs.jsonl`
106
+ * entry a later command (`ai-dossier history`, `sched stats`) may render.
107
+ * Strip control characters (the terminal-escape/log-injection risk) and cap
108
+ * the length, rather than trusting an agent-controlled string unbounded.
109
+ */
110
+ function sanitizeModel(value) {
111
+ if (value === null)
112
+ return null;
113
+ let clean = '';
114
+ // Bound the WORK, not just the result: `value` is agent-controlled and can
115
+ // be arbitrarily long, so stop as soon as the cap is reached rather than
116
+ // materializing a sanitized copy of the whole string first.
117
+ for (const char of value) {
118
+ if (clean.length >= MAX_MODEL_LENGTH)
119
+ break;
120
+ const code = char.codePointAt(0) ?? 0;
121
+ // C0 (< 0x20), DEL (0x7f) and C1 (0x80-0x9f) alike: U+009B is the 8-bit
122
+ // CSI, which a terminal in a non-UTF-8 locale acts on exactly like ESC[.
123
+ if (code >= 0x20 && code !== 0x7f && !(code >= 0x80 && code <= 0x9f))
124
+ clean += char;
125
+ }
126
+ return clean;
127
+ }
128
+ /** Narrow an unknown value to a plain-object record; null for anything else. */
129
+ function asRecord(value) {
130
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
131
+ ? value
132
+ : null;
133
+ }
134
+ /**
135
+ * `type` of the preamble line `packages/sched` writes to a dispatch log at
136
+ * spawn time (ai-dossier#524). It exists so a log is never 0 bytes for a unit
137
+ * that ran; every parser here skips it rather than counting it as agent
138
+ * output. Shared from `core` so the writer (`sched`'s `createSpawnDeps`) and
139
+ * the readers (below) can never drift apart on the sentinel's spelling.
140
+ */
141
+ exports.SCHED_DISPATCH_EVENT = 'sched-dispatch';
142
+ /**
143
+ * Event `type`s that only ever appear INSIDE a stream, never as a whole
144
+ * `--output-format json` payload. A single such line must be parsed as a
145
+ * one-line stream, not mistaken for a result object (#524 review).
146
+ */
147
+ const STREAM_EVENT_TYPES = new Set([
148
+ 'assistant',
149
+ 'user',
150
+ 'system',
151
+ exports.SCHED_DISPATCH_EVENT,
152
+ ]);
153
+ /** Parse one string as a JSON object; null for anything else (array, scalar, malformed). */
154
+ function parseJsonObject(text) {
155
+ try {
156
+ return asRecord(JSON.parse(text));
157
+ }
158
+ catch {
159
+ return null;
160
+ }
161
+ }
162
+ /**
163
+ * Extract usage from a claude `result`-shaped object — the payload of
164
+ * `--output-format json`, and of the final `type:"result"` event of
165
+ * `--output-format stream-json`. Both carry the same fields.
166
+ *
167
+ * `modelUsage` (summed across every model entry) is the source of record for
168
+ * token counts and cost — it is the only block that reflects a multi-model
169
+ * run accurately. The top-level `usage` / `total_cost_usd` (older: `cost_usd`)
170
+ * fields are used ONLY when `modelUsage` has no object-shaped entry at all:
171
+ * they are never blended field-by-field with it, because the two blocks have been
172
+ * observed to disagree (ai-dossier#524) — picking one field from each would
173
+ * silently produce a number neither block actually reported.
174
+ */
175
+ function extractResultUsage(parsed) {
176
+ const usage = asRecord(parsed.usage) ?? {};
177
+ const modelUsage = asRecord(parsed.modelUsage);
178
+ // Keep only object-shaped entries; a scalar entry is malformed, not a model.
179
+ const modelEntries = modelUsage
180
+ ? Object.entries(modelUsage).filter((entry) => !!asRecord(entry[1]))
181
+ : [];
182
+ const hasModelUsage = modelEntries.length > 0;
183
+ /** Sum one field across every model entry, trying each spelling in turn. */
184
+ const sumFromModelUsage = (keys, narrow = toCount) => {
185
+ let sum = 0;
186
+ let seen = false;
187
+ for (const [, entry] of modelEntries) {
188
+ let value = null;
189
+ for (const key of keys) {
190
+ value = narrow(entry[key]);
191
+ if (value !== null)
192
+ break;
193
+ }
194
+ if (value !== null) {
195
+ sum += value;
196
+ seen = true;
197
+ }
198
+ }
199
+ return seen ? sum : null;
200
+ };
201
+ // modelUsage wins whenever it carries at least one object-shaped entry —
202
+ // even if that entry only answers some of the fields — so a run's numbers
203
+ // always come from a single, consistent block rather than a per-field blend
204
+ // with `usage`. (`modelUsage: {}`, or a map whose every entry is a scalar,
205
+ // is malformed rather than present: `usage` is used in that case.)
206
+ const input_tokens = hasModelUsage
207
+ ? sumFromModelUsage(['inputTokens', 'input_tokens'])
208
+ : toCount(usage.input_tokens);
209
+ const output_tokens = hasModelUsage
210
+ ? sumFromModelUsage(['outputTokens', 'output_tokens'])
211
+ : toCount(usage.output_tokens);
212
+ const cache_creation_tokens = hasModelUsage
213
+ ? sumFromModelUsage(['cacheCreationInputTokens', 'cache_creation_input_tokens'])
214
+ : toCount(usage.cache_creation_input_tokens);
215
+ const cache_read_tokens = hasModelUsage
216
+ ? sumFromModelUsage(['cacheReadInputTokens', 'cache_read_input_tokens'])
217
+ : toCount(usage.cache_read_input_tokens);
218
+ // `costUSD` FIRST: that is the key claude actually writes inside a
219
+ // `modelUsage` entry (verified against a live claude stats artifact, #524
220
+ // review). `totalCostUsd`/`total_cost_usd` are kept as tolerated spellings.
221
+ // When modelUsage reports no cost key at all, fall back to the top-level
222
+ // total rather than reporting null — the whole-run cost is not a per-field
223
+ // blend of two token blocks, it is the one number both shapes agree on, and
224
+ // dropping it silently regressed `ai-dossier run`'s existing cost recording.
225
+ const costFromModelUsage = hasModelUsage
226
+ ? sumFromModelUsage(['costUSD', 'totalCostUsd', 'total_cost_usd'], toCost)
227
+ : null;
228
+ const total_cost_usd = costFromModelUsage ?? toCost(parsed.total_cost_usd) ?? toCost(parsed.cost_usd);
229
+ const modelFromUsage = joinModels(modelEntries.map(([key]) => key));
230
+ const rawModel = typeof parsed.model === 'string' && parsed.model ? parsed.model : modelFromUsage;
231
+ const model = sanitizeModel(rawModel);
232
+ const result_text = typeof parsed.result === 'string' ? parsed.result : null;
233
+ return {
234
+ model,
235
+ input_tokens,
236
+ output_tokens,
237
+ cache_creation_tokens,
238
+ cache_read_tokens,
239
+ total_cost_usd,
240
+ result_text,
241
+ };
242
+ }
243
+ /**
244
+ * Sum per-turn usage from `type:"assistant"` stream events — the fallback for
245
+ * a run that produced NO final `result` event (ai-dossier#524).
246
+ *
247
+ * The scheduler kills an agent that is still alive when ground truth says its
248
+ * unit is already done (`reconcileRunning`'s external-advance branch), and a
249
+ * killed agent never emits its `result` event. Before stream-json that meant
250
+ * zero recoverable tokens for those dispatches — six of the eleven pilot units.
251
+ * Each `assistant` event carries the usage of the request that produced it, so
252
+ * summing them recovers what the run actually spent up to the kill.
253
+ *
254
+ * `total_cost_usd` stays null: per-turn events do not report cost, and this
255
+ * path must not fabricate one from token counts.
256
+ */
257
+ function sumAssistantUsage(events) {
258
+ let input = 0;
259
+ let output = 0;
260
+ let cacheCreation = 0;
261
+ let cacheRead = 0;
262
+ let sawInput = false;
263
+ let sawOutput = false;
264
+ let sawCacheCreation = false;
265
+ let sawCacheRead = false;
266
+ const models = new Set();
267
+ for (const event of events) {
268
+ const message = asRecord(event.message);
269
+ if (!message)
270
+ continue;
271
+ if (typeof message.model === 'string' && message.model)
272
+ models.add(message.model);
273
+ const usage = asRecord(message.usage);
274
+ if (!usage)
275
+ continue;
276
+ const inputTokens = toCount(usage.input_tokens);
277
+ if (inputTokens !== null) {
278
+ input += inputTokens;
279
+ sawInput = true;
280
+ }
281
+ const outputTokens = toCount(usage.output_tokens);
282
+ if (outputTokens !== null) {
283
+ output += outputTokens;
284
+ sawOutput = true;
285
+ }
286
+ const cacheCreationTokens = toCount(usage.cache_creation_input_tokens);
287
+ if (cacheCreationTokens !== null) {
288
+ cacheCreation += cacheCreationTokens;
289
+ sawCacheCreation = true;
290
+ }
291
+ const cacheReadTokens = toCount(usage.cache_read_input_tokens);
292
+ if (cacheReadTokens !== null) {
293
+ cacheRead += cacheReadTokens;
294
+ sawCacheRead = true;
295
+ }
296
+ }
297
+ return {
298
+ model: sanitizeModel(joinModels([...models])),
299
+ input_tokens: sawInput ? input : null,
300
+ output_tokens: sawOutput ? output : null,
301
+ cache_creation_tokens: sawCacheCreation ? cacheCreation : null,
302
+ cache_read_tokens: sawCacheRead ? cacheRead : null,
303
+ total_cost_usd: null,
304
+ result_text: null,
305
+ };
306
+ }
307
+ /**
308
+ * Parse a claude headless result into usage data — both output formats.
309
+ *
310
+ * Accepts either shape, because the two consumers spawn claude differently:
311
+ *
312
+ * - **A single JSON object** (`--output-format json`, what `ai-dossier run`
313
+ * uses): parsed whole.
314
+ * - **A JSONL event stream** (`--output-format stream-json`, what the
315
+ * scheduler dispatches with since ai-dossier#524): the LAST `type:"result"`
316
+ * event wins — a per-unit log is append-mode, so a prior dispatch's result
317
+ * may precede this one in the same slice. With no `result` event at all (an
318
+ * agent killed mid-run), per-turn `assistant` usage is summed instead, so an
319
+ * interrupted dispatch still reports the tokens it really spent.
320
+ *
321
+ * Lines that do not parse as JSON objects are skipped rather than
322
+ * disqualifying the stream: the sched dispatch preamble
323
+ * ({@link SCHED_DISPATCH_EVENT}) sits at the head of every dispatch slice, and
324
+ * an agent killed mid-write leaves a truncated final line.
325
+ *
326
+ * Returns null when the output parses as neither shape (and for a stream
327
+ * holding no usage-bearing event). A result object that simply reported no
328
+ * usage yields an entry whose fields are all null, not `null` itself —
329
+ * "the agent reported nothing" and "there was no agent output" stay distinct.
330
+ */
331
+ function parseAgentUsage(stdout) {
332
+ if (typeof stdout !== 'string' || stdout.trim() === '')
333
+ return null;
334
+ // `--output-format json`: the whole payload is one object. Checked first so
335
+ // a pretty-printed (multi-line) result is not mistaken for an event stream.
336
+ // Stream event types are excluded, or a stream that happens to hold exactly
337
+ // ONE line (an agent killed after a single turn, or whose preamble write
338
+ // failed) would take this path and report all-null instead of falling
339
+ // through to the per-turn sum below.
340
+ const single = parseJsonObject(stdout);
341
+ if (single && !STREAM_EVENT_TYPES.has(single.type))
342
+ return extractResultUsage(single);
343
+ let lastResult = null;
344
+ const assistants = [];
345
+ for (const line of stdout.split('\n')) {
346
+ const trimmed = line.trim();
347
+ if (!trimmed)
348
+ continue;
349
+ const event = parseJsonObject(trimmed);
350
+ if (!event || event.type === exports.SCHED_DISPATCH_EVENT)
351
+ continue;
352
+ if (event.type === 'result')
353
+ lastResult = event;
354
+ else if (event.type === 'assistant')
355
+ assistants.push(event);
356
+ }
357
+ if (lastResult)
358
+ return extractResultUsage(lastResult);
359
+ if (assistants.length > 0)
360
+ return sumAssistantUsage(assistants);
361
+ return null;
362
+ }
363
+ /**
364
+ * Parse an `opencode run --format json` result stream into usage data (#459).
365
+ *
366
+ * opencode emits one JSON event per line: the assistant's text arrives in
367
+ * `type:"text"` parts, and per-step token/cost totals in `type:"step_finish"`
368
+ * parts (a multi-step run emits several — tokens and cost are summed), with
369
+ * cache counts nested as `tokens.cache: { write, read }`. The model id is not
370
+ * present in the events, so `model` is null and callers fall back to the
371
+ * requested --model alias — that field, and only that field, is genuinely
372
+ * unavailable here rather than merely absent. Returns null when the output
373
+ * holds no opencode event at all; individual non-JSON lines (stderr warnings
374
+ * interleaved by the scheduler's merged stdout/stderr fd) are skipped, not
375
+ * treated as disqualifying.
376
+ *
377
+ * **Cross-agent caveat.** opencode reports `tokens.reasoning` SEPARATELY from
378
+ * `tokens.output` (a step's `total` is input + output + reasoning +
379
+ * cache.read), whereas claude folds thinking tokens into `output_tokens`.
380
+ * Reasoning is 45-75% of generated tokens in real logs, so an opencode
381
+ * `output_tokens` is NOT directly comparable to a claude one — do not put the
382
+ * two in the same column of a cost comparison without saying so. It is left
383
+ * out rather than summed in because this module never derives a value the
384
+ * agent did not report; capturing it needs a field of its own on
385
+ * {@link AgentRunUsage} and `RunLogEntry`, which is a schema change beyond
386
+ * ai-dossier#524's scope.
387
+ */
388
+ function parseOpenCodeUsage(stdout) {
389
+ if (typeof stdout !== 'string' || stdout.trim() === '')
390
+ return null;
391
+ let sawEvent = false;
392
+ const texts = [];
393
+ let inputTokens = 0;
394
+ let outputTokens = 0;
395
+ let cacheCreationTokens = 0;
396
+ let cacheReadTokens = 0;
397
+ let costUsd = 0;
398
+ let sawUsage = false;
399
+ let sawCacheCreation = false;
400
+ let sawCacheRead = false;
401
+ for (const line of stdout.split('\n')) {
402
+ const trimmed = line.trim();
403
+ if (!trimmed)
404
+ continue;
405
+ const event = parseJsonObject(trimmed);
406
+ // Skip an unparseable line rather than discarding the whole stream
407
+ // (#524 review). `createSpawnDeps` merges stderr into the SAME fd as
408
+ // stdout, and opencode writes ANSI-coloured warnings there ("permission
409
+ // requested: ... auto-rejecting"), so ONE such line in a 1,600-line log
410
+ // used to null out the entire run — ~$28 and ~97M cache-read tokens
411
+ // across two real logs on a six-run cohort, recorded as indistinguishable
412
+ // nulls. Format-mismatch detection is preserved by `sawEvent` below: a
413
+ // stream with no valid opencode event at all still returns null.
414
+ if (!event)
415
+ continue;
416
+ // The sched dispatch preamble (#524) is written by the scheduler, not by
417
+ // opencode: skip it WITHOUT setting `sawEvent`, so a log holding only a
418
+ // preamble still reads as "the agent wrote nothing" (null) rather than an
419
+ // all-null usage object implying opencode reported no tokens.
420
+ if (event.type === exports.SCHED_DISPATCH_EVENT)
421
+ continue;
422
+ sawEvent = true;
423
+ const part = asRecord(event.part);
424
+ if (event.type === 'text' && part && typeof part.text === 'string') {
425
+ texts.push(part.text);
426
+ }
427
+ if (event.type === 'step_finish' && part) {
428
+ const tokens = asRecord(part.tokens);
429
+ if (tokens) {
430
+ const input = toCount(tokens.input);
431
+ if (input !== null) {
432
+ inputTokens += input;
433
+ sawUsage = true;
434
+ }
435
+ const output = toCount(tokens.output);
436
+ if (output !== null) {
437
+ outputTokens += output;
438
+ sawUsage = true;
439
+ }
440
+ // opencode nests cache counts one level down, as
441
+ // `tokens.cache: { write, read }` — verified against a real 310-event
442
+ // dispatch log (#524 review). They were previously hardcoded null on
443
+ // the mistaken belief opencode did not report them, silently dropping
444
+ // tens of millions of cache-read tokens per run.
445
+ const cache = asRecord(tokens.cache);
446
+ if (cache) {
447
+ const write = toCount(cache.write);
448
+ if (write !== null) {
449
+ cacheCreationTokens += write;
450
+ sawCacheCreation = true;
451
+ sawUsage = true;
452
+ }
453
+ const read = toCount(cache.read);
454
+ if (read !== null) {
455
+ cacheReadTokens += read;
456
+ sawCacheRead = true;
457
+ sawUsage = true;
458
+ }
459
+ }
460
+ }
461
+ const cost = toCost(part.cost);
462
+ if (cost !== null) {
463
+ costUsd += cost;
464
+ sawUsage = true;
465
+ }
466
+ }
467
+ }
468
+ if (!sawEvent)
469
+ return null;
470
+ return {
471
+ model: null,
472
+ input_tokens: sawUsage ? inputTokens : null,
473
+ output_tokens: sawUsage ? outputTokens : null,
474
+ cache_creation_tokens: sawCacheCreation ? cacheCreationTokens : null,
475
+ cache_read_tokens: sawCacheRead ? cacheReadTokens : null,
476
+ total_cost_usd: sawUsage ? costUsd : null,
477
+ result_text: texts.length > 0 ? texts.join('') : null,
478
+ };
479
+ }
480
+ /**
481
+ * Pick the usage parser for a dispatched agent, keyed off the spawned
482
+ * binary's basename — `opencode` (any path) routes to
483
+ * {@link parseOpenCodeUsage}; everything else, including an
484
+ * operator-configured command this build doesn't specifically recognize,
485
+ * falls back to {@link parseAgentUsage} (the claude shape). A command this
486
+ * build doesn't recognize is not guessed at further than that fallback —
487
+ * its output either parses as a claude-shaped JSON result or the parser
488
+ * returns null, never a fabricated guess.
489
+ */
490
+ function usageParserFor(cmd0) {
491
+ return path.basename(cmd0) === 'opencode' ? parseOpenCodeUsage : parseAgentUsage;
492
+ }
493
+ //# sourceMappingURL=agent-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-usage.js","sourceRoot":"","sources":["../src/agent-usage.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -6,8 +6,12 @@
6
6
  * - Checksum verification (SHA256 integrity checks)
7
7
  * - Signature verification (Minisign and AWS KMS)
8
8
  * - Output coherence validation
9
+ * - Headless-agent usage parsing (token/cost from claude/opencode JSON results)
10
+ * - runs.jsonl entry schema and path (shared by cli + sched)
9
11
  * - TypeScript type definitions
10
12
  */
13
+ export type { AgentRunUsage } from './agent-usage';
14
+ export { parseAgentUsage, parseOpenCodeUsage, SCHED_DISPATCH_EVENT, usageParserFor, } from './agent-usage';
11
15
  export { calculateChecksum, verifyIntegrity } from './checksum';
12
16
  export type { CoherenceContext, CoherenceDiagnostic, CoherenceResult, CoherenceSeverity, DeclaredOutputSchema, StepOutput, } from './coherence';
13
17
  export { validateCoherence, validateStepCoherence } from './coherence';
@@ -18,6 +22,8 @@ export { defaultRules, LintRuleRegistry, lintDossier, lintDossierFile, loadLintC
18
22
  export { parseDossierContent, parseDossierFile, RECOMMENDED_FIELDS, REQUIRED_FIELDS, VALID_RISK_LEVELS, VALID_STATUSES, validateFrontmatter, } from './parser';
19
23
  export type { ChecksumStatus, ContentRiskResult, SignatureStatus, VerificationRiskLevel, VerificationRiskResult, } from './risk-assessment';
20
24
  export { assessContentRisk, assessVerificationRisk } from './risk-assessment';
25
+ export type { RunLogEntry } from './run-log-entry';
26
+ export { runsLogPath } from './run-log-entry';
21
27
  export type { SecurityCategory, SecurityFinding, SecurityReport, SecurityRule, SecurityRuleContext, SecurityRuleSeverityOverride, SecurityScanConfig, SecuritySeverity, } from './security-scanner';
22
28
  export { buildReport, defaultSecurityRules, SecurityRuleRegistry, scanDossier, scanDossierFile, scanMarkdown, } from './security-scanner';
23
29
  export type { TrustedKeyEntry, TrustedKeyProblem } from './signature';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -7,6 +7,8 @@
7
7
  * - Checksum verification (SHA256 integrity checks)
8
8
  * - Signature verification (Minisign and AWS KMS)
9
9
  * - Output coherence validation
10
+ * - Headless-agent usage parsing (token/cost from claude/opencode JSON results)
11
+ * - runs.jsonl entry schema and path (shared by cli + sched)
10
12
  * - TypeScript type definitions
11
13
  */
12
14
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
@@ -24,8 +26,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
24
26
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
25
27
  };
26
28
  Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.createTraceRecorder = exports.resolveTraceConfig = exports.toSpkiPem = exports.signatureCoverage = exports.publicKeysMatch = exports.normalizePublicKey = exports.isSupportedPublicKey = exports.canonicalizeFrontmatter = exports.buildSignedPayload = exports.VerifierRegistry = exports.KmsVerifier = exports.KmsSigner = exports.getVerifierRegistry = exports.Ed25519Verifier = exports.Ed25519Signer = exports.verifyWithKms = exports.verifyWithEd25519 = exports.verifySignature = exports.trustedKeysFromContent = exports.reportTrustedKeyProblems = exports.parseTrustedKeys = exports.loadTrustedKeys = exports.isKmsKeyIdentifier = exports.findTrustedIdentifier = exports.scanMarkdown = exports.scanDossierFile = exports.scanDossier = exports.SecurityRuleRegistry = exports.defaultSecurityRules = exports.buildReport = exports.assessVerificationRisk = exports.assessContentRisk = exports.validateFrontmatter = exports.VALID_STATUSES = exports.VALID_RISK_LEVELS = exports.REQUIRED_FIELDS = exports.RECOMMENDED_FIELDS = exports.parseDossierFile = exports.parseDossierContent = exports.loadLintConfig = exports.lintDossierFile = exports.lintDossier = exports.LintRuleRegistry = exports.defaultRules = exports.formatDossierFile = exports.formatDossierContent = exports.validateStepCoherence = exports.validateCoherence = exports.verifyIntegrity = exports.calculateChecksum = void 0;
28
- exports.createDefaultVerificationResult = exports.scanBodyForUrls = exports.isUrlCoveredByDeclared = exports.isPlaceholderUrl = exports.findUndeclaredUrls = exports.findStaleReferences = exports.collectDeclaredUrls = exports.readFileIfExists = exports.getErrorStack = exports.getErrorMessage = exports.sha256Hex = exports.sha256Hash = exports.VALID_TRACE_STATUSES = void 0;
29
+ exports.normalizePublicKey = exports.isSupportedPublicKey = exports.canonicalizeFrontmatter = exports.buildSignedPayload = exports.VerifierRegistry = exports.KmsVerifier = exports.KmsSigner = exports.getVerifierRegistry = exports.Ed25519Verifier = exports.Ed25519Signer = exports.verifyWithKms = exports.verifyWithEd25519 = exports.verifySignature = exports.trustedKeysFromContent = exports.reportTrustedKeyProblems = exports.parseTrustedKeys = exports.loadTrustedKeys = exports.isKmsKeyIdentifier = exports.findTrustedIdentifier = exports.scanMarkdown = exports.scanDossierFile = exports.scanDossier = exports.SecurityRuleRegistry = exports.defaultSecurityRules = exports.buildReport = exports.runsLogPath = exports.assessVerificationRisk = exports.assessContentRisk = exports.validateFrontmatter = exports.VALID_STATUSES = exports.VALID_RISK_LEVELS = exports.REQUIRED_FIELDS = exports.RECOMMENDED_FIELDS = exports.parseDossierFile = exports.parseDossierContent = exports.loadLintConfig = exports.lintDossierFile = exports.lintDossier = exports.LintRuleRegistry = exports.defaultRules = exports.formatDossierFile = exports.formatDossierContent = exports.validateStepCoherence = exports.validateCoherence = exports.verifyIntegrity = exports.calculateChecksum = exports.usageParserFor = exports.SCHED_DISPATCH_EVENT = exports.parseOpenCodeUsage = exports.parseAgentUsage = void 0;
30
+ exports.createDefaultVerificationResult = exports.scanBodyForUrls = exports.isUrlCoveredByDeclared = exports.isPlaceholderUrl = exports.findUndeclaredUrls = exports.findStaleReferences = exports.collectDeclaredUrls = exports.readFileIfExists = exports.getErrorStack = exports.getErrorMessage = exports.sha256Hex = exports.sha256Hash = exports.VALID_TRACE_STATUSES = exports.createTraceRecorder = exports.resolveTraceConfig = exports.toSpkiPem = exports.signatureCoverage = exports.publicKeysMatch = void 0;
31
+ var agent_usage_1 = require("./agent-usage");
32
+ Object.defineProperty(exports, "parseAgentUsage", { enumerable: true, get: function () { return agent_usage_1.parseAgentUsage; } });
33
+ Object.defineProperty(exports, "parseOpenCodeUsage", { enumerable: true, get: function () { return agent_usage_1.parseOpenCodeUsage; } });
34
+ Object.defineProperty(exports, "SCHED_DISPATCH_EVENT", { enumerable: true, get: function () { return agent_usage_1.SCHED_DISPATCH_EVENT; } });
35
+ Object.defineProperty(exports, "usageParserFor", { enumerable: true, get: function () { return agent_usage_1.usageParserFor; } });
29
36
  // Checksum exports
30
37
  var checksum_1 = require("./checksum");
31
38
  Object.defineProperty(exports, "calculateChecksum", { enumerable: true, get: function () { return checksum_1.calculateChecksum; } });
@@ -57,6 +64,8 @@ Object.defineProperty(exports, "validateFrontmatter", { enumerable: true, get: f
57
64
  var risk_assessment_1 = require("./risk-assessment");
58
65
  Object.defineProperty(exports, "assessContentRisk", { enumerable: true, get: function () { return risk_assessment_1.assessContentRisk; } });
59
66
  Object.defineProperty(exports, "assessVerificationRisk", { enumerable: true, get: function () { return risk_assessment_1.assessVerificationRisk; } });
67
+ var run_log_entry_1 = require("./run-log-entry");
68
+ Object.defineProperty(exports, "runsLogPath", { enumerable: true, get: function () { return run_log_entry_1.runsLogPath; } });
60
69
  var security_scanner_1 = require("./security-scanner");
61
70
  Object.defineProperty(exports, "buildReport", { enumerable: true, get: function () { return security_scanner_1.buildReport; } });
62
71
  Object.defineProperty(exports, "defaultSecurityRules", { enumerable: true, get: function () { return security_scanner_1.defaultSecurityRules; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;;;;;;;;;;;;;;;AAEH,mBAAmB;AACnB,uCAAgE;AAAvD,6GAAA,iBAAiB,OAAA;AAAE,2GAAA,eAAe,OAAA;AAU3C,yCAAuE;AAA9D,8GAAA,iBAAiB,OAAA;AAAE,kHAAA,qBAAqB,OAAA;AAEjD,oBAAoB;AACpB,yCAAsE;AAA7D,iHAAA,oBAAoB,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAUhD,iBAAiB;AACjB,mCAMkB;AALhB,sGAAA,YAAY,OAAA;AACZ,0GAAA,gBAAgB,OAAA;AAChB,qGAAA,WAAW,OAAA;AACX,yGAAA,eAAe,OAAA;AACf,wGAAA,cAAc,OAAA;AAEhB,iBAAiB;AACjB,mCAQkB;AAPhB,6GAAA,mBAAmB,OAAA;AACnB,0GAAA,gBAAgB,OAAA;AAChB,4GAAA,kBAAkB,OAAA;AAClB,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,wGAAA,cAAc,OAAA;AACd,6GAAA,mBAAmB,OAAA;AASrB,0BAA0B;AAC1B,qDAA8E;AAArE,oHAAA,iBAAiB,OAAA;AAAE,yHAAA,sBAAsB,OAAA;AAYlD,uDAO4B;AAN1B,+GAAA,WAAW,OAAA;AACX,wHAAA,oBAAoB,OAAA;AACpB,wHAAA,oBAAoB,OAAA;AACpB,+GAAA,WAAW,OAAA;AACX,mHAAA,eAAe,OAAA;AACf,gHAAA,YAAY,OAAA;AAId,yCAUqB;AATnB,kHAAA,qBAAqB,OAAA;AACrB,+GAAA,kBAAkB,OAAA;AAClB,4GAAA,eAAe,OAAA;AACf,6GAAA,gBAAgB,OAAA;AAChB,qHAAA,wBAAwB,OAAA;AACxB,mHAAA,sBAAsB,OAAA;AACtB,4GAAA,eAAe,OAAA;AACf,8GAAA,iBAAiB,OAAA;AACjB,0GAAA,aAAa,OAAA;AAEf,iDAAiD;AACjD,qCAWmB;AAVjB,wGAAA,aAAa,OAAA;AACb,0GAAA,eAAe,OAAA;AACf,8GAAA,mBAAmB,OAAA;AACnB,oGAAA,SAAS,OAAA;AACT,sGAAA,WAAW,OAAA;AAIX,2GAAA,gBAAgB,OAAA;AAKlB,qDAQ2B;AAPzB,qHAAA,kBAAkB,OAAA;AAClB,0HAAA,uBAAuB,OAAA;AACvB,uHAAA,oBAAoB,OAAA;AACpB,qHAAA,kBAAkB,OAAA;AAClB,kHAAA,eAAe,OAAA;AACf,oHAAA,iBAAiB,OAAA;AACjB,4GAAA,SAAS,OAAA;AASX,+CAAoD;AAA3C,kHAAA,kBAAkB,OAAA;AAW3B,mDAA6E;AAApE,qHAAA,mBAAmB,OAAA;AAAE,sHAAA,oBAAoB,OAAA;AAClD,eAAe;AACf,0CAAwB;AACxB,mBAAmB;AACnB,yCAAuD;AAA9C,oGAAA,UAAU,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC9B,kBAAkB;AAClB,yCAAgE;AAAvD,yGAAA,eAAe,OAAA;AAAE,uGAAA,aAAa,OAAA;AACvC,wBAAwB;AACxB,iCAA8C;AAArC,sGAAA,gBAAgB,OAAA;AACzB,yBAAyB;AACzB,mDAO6B;AAN3B,kHAAA,mBAAmB,OAAA;AACnB,kHAAA,mBAAmB,OAAA;AACnB,iHAAA,kBAAkB,OAAA;AAClB,+GAAA,gBAAgB,OAAA;AAChB,qHAAA,sBAAsB,OAAA;AACtB,8GAAA,eAAe,OAAA;AAEjB,yBAAyB;AACzB,qDAAuE;AAA9D,+HAAA,+BAA+B,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;;;;;;;;;;;;;;;;AAIH,6CAKuB;AAJrB,8GAAA,eAAe,OAAA;AACf,iHAAA,kBAAkB,OAAA;AAClB,mHAAA,oBAAoB,OAAA;AACpB,6GAAA,cAAc,OAAA;AAEhB,mBAAmB;AACnB,uCAAgE;AAAvD,6GAAA,iBAAiB,OAAA;AAAE,2GAAA,eAAe,OAAA;AAU3C,yCAAuE;AAA9D,8GAAA,iBAAiB,OAAA;AAAE,kHAAA,qBAAqB,OAAA;AAEjD,oBAAoB;AACpB,yCAAsE;AAA7D,iHAAA,oBAAoB,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAUhD,iBAAiB;AACjB,mCAMkB;AALhB,sGAAA,YAAY,OAAA;AACZ,0GAAA,gBAAgB,OAAA;AAChB,qGAAA,WAAW,OAAA;AACX,yGAAA,eAAe,OAAA;AACf,wGAAA,cAAc,OAAA;AAEhB,iBAAiB;AACjB,mCAQkB;AAPhB,6GAAA,mBAAmB,OAAA;AACnB,0GAAA,gBAAgB,OAAA;AAChB,4GAAA,kBAAkB,OAAA;AAClB,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,wGAAA,cAAc,OAAA;AACd,6GAAA,mBAAmB,OAAA;AASrB,0BAA0B;AAC1B,qDAA8E;AAArE,oHAAA,iBAAiB,OAAA;AAAE,yHAAA,sBAAsB,OAAA;AAGlD,iDAA8C;AAArC,4GAAA,WAAW,OAAA;AAYpB,uDAO4B;AAN1B,+GAAA,WAAW,OAAA;AACX,wHAAA,oBAAoB,OAAA;AACpB,wHAAA,oBAAoB,OAAA;AACpB,+GAAA,WAAW,OAAA;AACX,mHAAA,eAAe,OAAA;AACf,gHAAA,YAAY,OAAA;AAId,yCAUqB;AATnB,kHAAA,qBAAqB,OAAA;AACrB,+GAAA,kBAAkB,OAAA;AAClB,4GAAA,eAAe,OAAA;AACf,6GAAA,gBAAgB,OAAA;AAChB,qHAAA,wBAAwB,OAAA;AACxB,mHAAA,sBAAsB,OAAA;AACtB,4GAAA,eAAe,OAAA;AACf,8GAAA,iBAAiB,OAAA;AACjB,0GAAA,aAAa,OAAA;AAEf,iDAAiD;AACjD,qCAWmB;AAVjB,wGAAA,aAAa,OAAA;AACb,0GAAA,eAAe,OAAA;AACf,8GAAA,mBAAmB,OAAA;AACnB,oGAAA,SAAS,OAAA;AACT,sGAAA,WAAW,OAAA;AAIX,2GAAA,gBAAgB,OAAA;AAKlB,qDAQ2B;AAPzB,qHAAA,kBAAkB,OAAA;AAClB,0HAAA,uBAAuB,OAAA;AACvB,uHAAA,oBAAoB,OAAA;AACpB,qHAAA,kBAAkB,OAAA;AAClB,kHAAA,eAAe,OAAA;AACf,oHAAA,iBAAiB,OAAA;AACjB,4GAAA,SAAS,OAAA;AASX,+CAAoD;AAA3C,kHAAA,kBAAkB,OAAA;AAW3B,mDAA6E;AAApE,qHAAA,mBAAmB,OAAA;AAAE,sHAAA,oBAAoB,OAAA;AAClD,eAAe;AACf,0CAAwB;AACxB,mBAAmB;AACnB,yCAAuD;AAA9C,oGAAA,UAAU,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC9B,kBAAkB;AAClB,yCAAgE;AAAvD,yGAAA,eAAe,OAAA;AAAE,uGAAA,aAAa,OAAA;AACvC,wBAAwB;AACxB,iCAA8C;AAArC,sGAAA,gBAAgB,OAAA;AACzB,yBAAyB;AACzB,mDAO6B;AAN3B,kHAAA,mBAAmB,OAAA;AACnB,kHAAA,mBAAmB,OAAA;AACnB,iHAAA,kBAAkB,OAAA;AAClB,+GAAA,gBAAgB,OAAA;AAChB,qHAAA,sBAAsB,OAAA;AACtB,8GAAA,eAAe,OAAA;AAEjB,yBAAyB;AACzB,qDAAuE;AAA9D,+HAAA,+BAA+B,OAAA"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The `~/.dossier/runs.jsonl` entry schema (#458, #524).
3
+ *
4
+ * Lives in `core`, not `cli`, so `packages/sched`'s dispatch path can write
5
+ * entries in the same shape `cli`'s `ai-dossier run` and `ai-dossier history`
6
+ * already read — one schema, two writers — without `sched` depending on
7
+ * `cli` (the dependency runs the other way). `cli/src/run-log.ts` re-exports
8
+ * this type and owns the actual file I/O (respecting the `auditLog` config
9
+ * flag); `sched` writes its own entries independently — see
10
+ * `packages/sched/src/run-log.ts`.
11
+ */
12
+ export interface RunLogEntry {
13
+ timestamp: string;
14
+ dossier: string;
15
+ resolved_version: string;
16
+ source: 'cache' | 'registry' | 'local' | 'url';
17
+ registry?: string;
18
+ /**
19
+ * How the version was resolved (only meaningful for registry sources):
20
+ * - 'pinned' — caller passed name@version explicitly
21
+ * - 'registry' — resolver called the registry and got a fresh version
22
+ * - 'cache' — resolver served from TTL'd resolution cache (no registry call)
23
+ * - 'stale-cache' — registry was unreachable; fell back to highest cached semver
24
+ * Useful for postmortems answering "did this run hit a stale resolution that
25
+ * masked a registry outage?". Absent for local files and URLs.
26
+ */
27
+ resolution_source?: 'pinned' | 'registry' | 'cache' | 'stale-cache';
28
+ verification: 'passed' | 'failed' | 'skipped' | 'nested-skip';
29
+ llm: string;
30
+ user: string;
31
+ cwd: string;
32
+ nested: boolean;
33
+ /**
34
+ * Deprecated: written by the pre-#401 update-check machinery. Retained on the
35
+ * interface so `dossier history` can still display this field when reading
36
+ * older runs.jsonl entries. Not written by new runs.
37
+ */
38
+ update_available?: string;
39
+ /**
40
+ * Cost/observability fields (#458). All optional and nullable so old-schema
41
+ * entries still parse; written by new runs with explicit nulls when a value
42
+ * is unavailable — never fabricated.
43
+ */
44
+ /** Wall-clock duration of the run in milliseconds (action start → entry write). */
45
+ duration_ms?: number | null;
46
+ /**
47
+ * The exact agent command spawned (binary + args). Prompt content is excluded
48
+ * (headless prompts travel over stdin). Null when nothing was spawned
49
+ * (nested-skip, failed verification, dry-run, no LLM detected, unknown LLM).
50
+ */
51
+ spawned_command?: string | null;
52
+ /** Model id as reported by the agent CLI, else the requested --model alias. Null when unknown. */
53
+ model?: string | null;
54
+ /** Exit code of the spawned agent process, or of the CLI action for early exits. Null when killed by a signal or failed to spawn. */
55
+ exit_code?: number | null;
56
+ /** Why the spawned process produced no exit code: spawn error (e.g. ENOENT) or signal. Null when the process exited normally. */
57
+ spawn_error?: string | null;
58
+ /** Input tokens reported by the agent CLI. Null when unavailable. */
59
+ input_tokens?: number | null;
60
+ /** Output tokens reported by the agent CLI. Null when unavailable. */
61
+ output_tokens?: number | null;
62
+ /**
63
+ * Cache-creation (write) and cache-read input tokens reported by the agent
64
+ * CLI (#524). Sourced from `modelUsage`, the same as `input_tokens`/
65
+ * `output_tokens` — see `parseAgentUsage` in `./agent-usage`. Null when
66
+ * unavailable.
67
+ */
68
+ cache_creation_tokens?: number | null;
69
+ cache_read_tokens?: number | null;
70
+ /** Total cost in USD reported by the agent CLI. Null when unavailable. */
71
+ total_cost_usd?: number | null;
72
+ /**
73
+ * The scheduler unit this run belongs to (#524), e.g. `issue:524` or
74
+ * `batch:b1` — set by `packages/sched` dispatch entries, null/absent for
75
+ * an ordinary `ai-dossier run` invocation (which has no unit).
76
+ */
77
+ unit?: string | null;
78
+ }
79
+ /**
80
+ * `~/.dossier/runs.jsonl` — the single location both writers (`cli`'s
81
+ * `ai-dossier run` and `packages/sched`'s dispatch path) append to, and both
82
+ * readers (`ai-dossier history`, `ai-dossier sched stats`) read from (#524).
83
+ * Hoisted here so the path is computed in exactly one place; before this,
84
+ * `cli/src/run-log.ts` and `packages/sched/src/run-log.ts` each built it
85
+ * independently and agreed only by coincidence. Testable via `home`.
86
+ */
87
+ export declare function runsLogPath(home?: string): string;
88
+ //# sourceMappingURL=run-log-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-log-entry.d.ts","sourceRoot":"","sources":["../src/run-log-entry.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;IACpE,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kGAAkG;IAClG,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,qIAAqI;IACrI,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iIAAiI;IACjI,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAqB,GAAG,MAAM,CAE/D"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runsLogPath = runsLogPath;
37
+ const os = __importStar(require("node:os"));
38
+ const path = __importStar(require("node:path"));
39
+ /**
40
+ * `~/.dossier/runs.jsonl` — the single location both writers (`cli`'s
41
+ * `ai-dossier run` and `packages/sched`'s dispatch path) append to, and both
42
+ * readers (`ai-dossier history`, `ai-dossier sched stats`) read from (#524).
43
+ * Hoisted here so the path is computed in exactly one place; before this,
44
+ * `cli/src/run-log.ts` and `packages/sched/src/run-log.ts` each built it
45
+ * independently and agreed only by coincidence. Testable via `home`.
46
+ */
47
+ function runsLogPath(home = os.homedir()) {
48
+ return path.join(home, '.dossier', 'runs.jsonl');
49
+ }
50
+ //# sourceMappingURL=run-log-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-log-entry.js","sourceRoot":"","sources":["../src/run-log-entry.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0FA,kCAEC;AA5FD,4CAA8B;AAC9B,gDAAkC;AAiFlC;;;;;;;GAOG;AACH,SAAgB,WAAW,CAAC,OAAe,EAAE,CAAC,OAAO,EAAE;IACrD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AACnD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-dossier/core",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Parsing, verification, and signing for dossiers — portable, signed, versioned skills for any LLM tool.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",