@dzhechkov/harness-core 0.8.35 → 0.8.37
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/.dz-manifest.json +224 -104
- package/README.md +335 -10
- package/dist/agentdb-index.d.ts +87 -7
- package/dist/agentdb-index.d.ts.map +1 -1
- package/dist/agentdb-index.js +416 -57
- package/dist/agentdb-index.js.map +1 -1
- package/dist/apply-leg.d.ts +57 -1
- package/dist/apply-leg.d.ts.map +1 -1
- package/dist/apply-leg.js +450 -52
- package/dist/apply-leg.js.map +1 -1
- package/dist/codex-hooks-assets.d.ts.map +1 -1
- package/dist/codex-hooks-assets.js +67 -5
- package/dist/codex-hooks-assets.js.map +1 -1
- package/dist/codex-hooks.d.ts +13 -1
- package/dist/codex-hooks.d.ts.map +1 -1
- package/dist/codex-hooks.js +13 -1
- package/dist/codex-hooks.js.map +1 -1
- package/dist/codex-rollouts.d.ts +118 -0
- package/dist/codex-rollouts.d.ts.map +1 -0
- package/dist/codex-rollouts.js +297 -0
- package/dist/codex-rollouts.js.map +1 -0
- package/dist/cost-ledger.d.ts +56 -4
- package/dist/cost-ledger.d.ts.map +1 -1
- package/dist/cost-ledger.js +176 -20
- package/dist/cost-ledger.js.map +1 -1
- package/dist/cross-family-control.d.ts +345 -0
- package/dist/cross-family-control.d.ts.map +1 -0
- package/dist/cross-family-control.js +802 -0
- package/dist/cross-family-control.js.map +1 -0
- package/dist/debt-ratchet.d.ts +53 -0
- package/dist/debt-ratchet.d.ts.map +1 -0
- package/dist/debt-ratchet.js +107 -0
- package/dist/debt-ratchet.js.map +1 -0
- package/dist/embedding-config.d.ts +42 -0
- package/dist/embedding-config.d.ts.map +1 -1
- package/dist/embedding-config.js +106 -10
- package/dist/embedding-config.js.map +1 -1
- package/dist/feature-adr-checkpoints.d.ts +6 -0
- package/dist/feature-adr-checkpoints.d.ts.map +1 -1
- package/dist/feature-adr-checkpoints.js +29 -0
- package/dist/feature-adr-checkpoints.js.map +1 -1
- package/dist/feature-adr-decision-recall.d.ts +2 -2
- package/dist/feature-adr-decision-recall.d.ts.map +1 -1
- package/dist/feature-adr-decision-recall.js +5 -3
- package/dist/feature-adr-decision-recall.js.map +1 -1
- package/dist/feature-adr-envelope.d.ts +96 -0
- package/dist/feature-adr-envelope.d.ts.map +1 -0
- package/dist/feature-adr-envelope.js +183 -0
- package/dist/feature-adr-envelope.js.map +1 -0
- package/dist/feature-adr-routing.d.ts +64 -0
- package/dist/feature-adr-routing.d.ts.map +1 -1
- package/dist/feature-adr-routing.js +122 -2
- package/dist/feature-adr-routing.js.map +1 -1
- package/dist/feature-adr-stage-canon.d.ts +79 -0
- package/dist/feature-adr-stage-canon.d.ts.map +1 -0
- package/dist/feature-adr-stage-canon.js +117 -0
- package/dist/feature-adr-stage-canon.js.map +1 -0
- package/dist/index.d.ts +23 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/loop-blobs.generated.js +4 -4
- package/dist/loop-blobs.generated.js.map +1 -1
- package/dist/mutation-gate.d.ts +51 -0
- package/dist/mutation-gate.d.ts.map +1 -1
- package/dist/mutation-gate.js +295 -0
- package/dist/mutation-gate.js.map +1 -1
- package/dist/operations.d.ts +1 -0
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +18 -2
- package/dist/operations.js.map +1 -1
- package/dist/publish.d.ts +59 -7
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +205 -32
- package/dist/publish.js.map +1 -1
- package/dist/qe-bridge.d.ts.map +1 -1
- package/dist/qe-bridge.js +4 -2
- package/dist/qe-bridge.js.map +1 -1
- package/dist/qe-findings.d.ts +107 -0
- package/dist/qe-findings.d.ts.map +1 -0
- package/dist/qe-findings.js +417 -0
- package/dist/qe-findings.js.map +1 -0
- package/dist/recap.d.ts +1 -1
- package/dist/recap.d.ts.map +1 -1
- package/dist/recap.js +4 -2
- package/dist/recap.js.map +1 -1
- package/dist/release-line.d.ts +16 -0
- package/dist/release-line.d.ts.map +1 -1
- package/dist/release-line.js +31 -0
- package/dist/release-line.js.map +1 -1
- package/dist/round.d.ts +74 -1
- package/dist/round.d.ts.map +1 -1
- package/dist/round.js +112 -4
- package/dist/round.js.map +1 -1
- package/dist/run-records.d.ts +60 -0
- package/dist/run-records.d.ts.map +1 -1
- package/dist/run-records.js +244 -2
- package/dist/run-records.js.map +1 -1
- package/dist/score.d.ts +44 -1
- package/dist/score.d.ts.map +1 -1
- package/dist/score.js +78 -5
- package/dist/score.js.map +1 -1
- package/dist/vector-tier.d.ts +34 -3
- package/dist/vector-tier.d.ts.map +1 -1
- package/dist/vector-tier.js +105 -14
- package/dist/vector-tier.js.map +1 -1
- package/package.json +2 -2
- package/sbom.json +403 -103
- package/src/agentdb-index.ts +423 -60
- package/src/apply-leg.ts +469 -50
- package/src/codex-hooks-assets.ts +67 -5
- package/src/codex-hooks.ts +13 -1
- package/src/codex-rollouts.ts +374 -0
- package/src/cost-ledger.ts +232 -24
- package/src/cross-family-control.ts +960 -0
- package/src/debt-ratchet.ts +143 -0
- package/src/embedding-config.ts +131 -10
- package/src/feature-adr-checkpoints.ts +29 -0
- package/src/feature-adr-decision-recall.ts +6 -4
- package/src/feature-adr-envelope.ts +242 -0
- package/src/feature-adr-routing.ts +139 -2
- package/src/feature-adr-stage-canon.ts +141 -0
- package/src/index.ts +66 -7
- package/src/loop-blobs.generated.ts +4 -4
- package/src/mutation-gate.ts +316 -0
- package/src/operations.ts +18 -3
- package/src/publish.ts +247 -30
- package/src/qe-bridge.ts +4 -2
- package/src/qe-findings.ts +463 -0
- package/src/recap.ts +10 -3
- package/src/release-line.ts +32 -0
- package/src/round.ts +165 -6
- package/src/run-records.ts +282 -2
- package/src/score.ts +115 -6
- package/src/vector-tier.ts +127 -14
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A pure reader for Codex CLI rollout logs (feature `measurement-integrity`, ADR-001 D3).
|
|
3
|
+
*
|
|
4
|
+
* A `dz feature-adr-record --kind ledger` row for a Codex coder/reviewer stage carries
|
|
5
|
+
* `tokens: null` in 130 of 156 recorded rows (Step 0, 2026-09-16) even though the spend is sitting
|
|
6
|
+
* right there on disk: Codex writes one JSONL file per session at
|
|
7
|
+
* `~/.codex/sessions/YYYY/MM/DD/rollout-<ts>-<uuid>.jsonl`, and nothing in the pipeline reads it. The
|
|
8
|
+
* pipeline dispatches Codex without an explicit session id (`codex exec -C <repo> -m <id> …`), so the
|
|
9
|
+
* only way to join a ledger row to the rollout that produced it is a WINDOW match: the stage's own
|
|
10
|
+
* start/end time, its `cwd`, and its model.
|
|
11
|
+
*
|
|
12
|
+
* PURE — this module never opens `~/.codex/sessions` itself; the CLI reads the files and hands their
|
|
13
|
+
* TEXT to {@link parseCodexRollout}. It must never gain a `node:fs` import (the `core-boundary`
|
|
14
|
+
* ratchet, `test/core-boundary.test.ts`, pins the current file/import count).
|
|
15
|
+
*
|
|
16
|
+
* ## A measured schema correction (read before touching the parser)
|
|
17
|
+
*
|
|
18
|
+
* Step 0's assessment described the usage record as `type: "token_count"`, keyed
|
|
19
|
+
* `payload.info.total_token_usage`. A live probe of this machine's `~/.codex/sessions` (2026-09-16,
|
|
20
|
+
* `cli_version: "0.154.0"`, every rollout from the last two days) found NO such record — the CURRENT
|
|
21
|
+
* shape is `type: "token_usage_record"`, keyed `payload.usage`, with the same five sub-fields
|
|
22
|
+
* (`input_tokens`, `cached_input_tokens`, `output_tokens`, `reasoning_output_tokens`,
|
|
23
|
+
* `total_tokens`). The model id lives on `type: "turn_context"`'s `payload.model` (not on
|
|
24
|
+
* `session_meta`, as Step 0 assumed), and `cwd` is carried by BOTH `session_meta.payload.cwd` and
|
|
25
|
+
* `turn_context.payload.cwd`. Rather than build against a shape that no longer exists on this
|
|
26
|
+
* machine, {@link parseCodexRollout} accepts BOTH the documented legacy shape and the measured
|
|
27
|
+
* current one — Codex CLI versions drift the schema (C-2: this module depends on no version beyond
|
|
28
|
+
* the fields it reads), and a reader that understands only a shape nothing on disk still emits would
|
|
29
|
+
* fail FR-5 at the exact thing it exists to fix.
|
|
30
|
+
*
|
|
31
|
+
* @packageDocumentation
|
|
32
|
+
*/
|
|
33
|
+
function isRecord(v) {
|
|
34
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
35
|
+
}
|
|
36
|
+
function nonEmptyString(v) {
|
|
37
|
+
return typeof v === 'string' && v.length > 0 ? v : null;
|
|
38
|
+
}
|
|
39
|
+
function finiteNonNegative(v) {
|
|
40
|
+
return typeof v === 'number' && Number.isFinite(v) && v >= 0 ? v : 0;
|
|
41
|
+
}
|
|
42
|
+
/** Epoch ms from a record's own `timestamp` (current schema) or `ts` (legacy/defensive), or `null`. */
|
|
43
|
+
function recordTimeMs(rec) {
|
|
44
|
+
const raw = rec['timestamp'] ?? rec['ts'];
|
|
45
|
+
if (typeof raw === 'number' && Number.isFinite(raw))
|
|
46
|
+
return raw;
|
|
47
|
+
if (typeof raw === 'string') {
|
|
48
|
+
const ms = Date.parse(raw);
|
|
49
|
+
return Number.isFinite(ms) ? ms : null;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function isoOrNull(ms) {
|
|
54
|
+
if (ms === null || !Number.isFinite(ms) || Math.abs(ms) > 8.64e15)
|
|
55
|
+
return null;
|
|
56
|
+
try {
|
|
57
|
+
return new Date(ms).toISOString();
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Pull `{input_tokens, cached_input_tokens, output_tokens, reasoning_output_tokens, total_tokens}`
|
|
64
|
+
* (both schemas use these five field names) out of a usage-bearing sub-object. */
|
|
65
|
+
function totalsFrom(usage) {
|
|
66
|
+
return {
|
|
67
|
+
input: finiteNonNegative(usage['input_tokens']),
|
|
68
|
+
cachedInput: finiteNonNegative(usage['cached_input_tokens']),
|
|
69
|
+
output: finiteNonNegative(usage['output_tokens']),
|
|
70
|
+
reasoning: finiteNonNegative(usage['reasoning_output_tokens']),
|
|
71
|
+
total: finiteNonNegative(usage['total_tokens']),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse ONE rollout file's full text into a {@link CodexRollout}. Pure, never-throws; a corrupt line
|
|
76
|
+
* is skipped exactly the way `extractCostSamples` (`cost-ledger.ts`) skips one.
|
|
77
|
+
*
|
|
78
|
+
* `fileName`, when given, is used ONLY as a last-resort `id` source (the `rollout-<ts>-<uuid>.jsonl`
|
|
79
|
+
* name's own uuid) when no `session_meta` record carried one — never trusted over the file's own
|
|
80
|
+
* content.
|
|
81
|
+
*/
|
|
82
|
+
export function parseCodexRollout(text, fileName) {
|
|
83
|
+
if (typeof text !== 'string' || text.trim().length === 0) {
|
|
84
|
+
return { error: 'empty rollout text' };
|
|
85
|
+
}
|
|
86
|
+
let id = null;
|
|
87
|
+
let cwd = null;
|
|
88
|
+
let sessionMetaModel = null;
|
|
89
|
+
let turnContextModel = null;
|
|
90
|
+
let firstMs = null;
|
|
91
|
+
let lastMs = null;
|
|
92
|
+
let lastTotals = null;
|
|
93
|
+
let sawAnyRecord = false;
|
|
94
|
+
const closedTurns = [];
|
|
95
|
+
let open = null;
|
|
96
|
+
let unmatchableTurns = 0;
|
|
97
|
+
const closeOpenTurn = (endMs) => {
|
|
98
|
+
if (open === null)
|
|
99
|
+
return;
|
|
100
|
+
if (open.startedMs === null || endMs === null)
|
|
101
|
+
unmatchableTurns += 1;
|
|
102
|
+
closedTurns.push({
|
|
103
|
+
model: open.model,
|
|
104
|
+
cwd: open.cwd,
|
|
105
|
+
startedAt: open.startedMs === null ? null : isoOrNull(open.startedMs),
|
|
106
|
+
endedAt: endMs === null ? null : isoOrNull(endMs),
|
|
107
|
+
totals: open.totals,
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
const deltaTotals = (now, base) => {
|
|
111
|
+
if (base === null)
|
|
112
|
+
return now;
|
|
113
|
+
const d = (a, b) => (a - b >= 0 ? a - b : a); // a counter that went DOWN is per-record, not cumulative
|
|
114
|
+
return { input: d(now.input, base.input), cachedInput: d(now.cachedInput, base.cachedInput), output: d(now.output, base.output), reasoning: d(now.reasoning, base.reasoning), total: d(now.total, base.total) };
|
|
115
|
+
};
|
|
116
|
+
for (const line of text.split('\n')) {
|
|
117
|
+
if (line.length === 0)
|
|
118
|
+
continue;
|
|
119
|
+
let rec;
|
|
120
|
+
try {
|
|
121
|
+
rec = JSON.parse(line);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
continue; // corrupt line — skip, never throw
|
|
125
|
+
}
|
|
126
|
+
if (!isRecord(rec))
|
|
127
|
+
continue;
|
|
128
|
+
sawAnyRecord = true;
|
|
129
|
+
const ms = recordTimeMs(rec);
|
|
130
|
+
if (ms !== null) {
|
|
131
|
+
firstMs = firstMs === null ? ms : Math.min(firstMs, ms);
|
|
132
|
+
lastMs = lastMs === null ? ms : Math.max(lastMs, ms);
|
|
133
|
+
}
|
|
134
|
+
const type = rec['type'];
|
|
135
|
+
const payload = isRecord(rec['payload']) ? rec['payload'] : null;
|
|
136
|
+
if (payload === null)
|
|
137
|
+
continue;
|
|
138
|
+
if (type === 'session_meta') {
|
|
139
|
+
if (id === null)
|
|
140
|
+
id = nonEmptyString(payload['session_id']) ?? nonEmptyString(payload['id']);
|
|
141
|
+
if (cwd === null)
|
|
142
|
+
cwd = nonEmptyString(payload['cwd']);
|
|
143
|
+
// Step 0's documented (legacy, not observed live on this machine) shape put `model` directly on
|
|
144
|
+
// `session_meta` — accepted here too, but `turnContextModel` always wins at the end (below)
|
|
145
|
+
// since that is what the measured current schema actually carries.
|
|
146
|
+
if (sessionMetaModel === null)
|
|
147
|
+
sessionMetaModel = nonEmptyString(payload['model']);
|
|
148
|
+
}
|
|
149
|
+
else if (type === 'turn_context') {
|
|
150
|
+
if (turnContextModel === null)
|
|
151
|
+
turnContextModel = nonEmptyString(payload['model']);
|
|
152
|
+
if (cwd === null)
|
|
153
|
+
cwd = nonEmptyString(payload['cwd']);
|
|
154
|
+
// Close the previous open turn AT this boundary (even when the boundary has no timestamp —
|
|
155
|
+
// the previous turn must stop absorbing usage), then open the new one.
|
|
156
|
+
closeOpenTurn(ms);
|
|
157
|
+
open = { model: nonEmptyString(payload['model']), cwd: nonEmptyString(payload['cwd']) ?? cwd, startedMs: ms, baseline: lastTotals, totals: null };
|
|
158
|
+
}
|
|
159
|
+
// Legacy shape (Step 0's documented one, not observed live on this machine 2026-09-16):
|
|
160
|
+
// `type: "token_count"`, `payload.info.total_token_usage`.
|
|
161
|
+
if (type === 'token_count') {
|
|
162
|
+
const info = isRecord(payload['info']) ? payload['info'] : null;
|
|
163
|
+
const usage = info !== null && isRecord(info['total_token_usage']) ? info['total_token_usage'] : null;
|
|
164
|
+
if (usage !== null) {
|
|
165
|
+
const t = totalsFrom(usage);
|
|
166
|
+
if (open !== null)
|
|
167
|
+
open.totals = deltaTotals(t, open.baseline);
|
|
168
|
+
lastTotals = t;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Current shape (measured live, cli_version 0.154.0): `type: "token_usage_record"`,
|
|
172
|
+
// `payload.usage`.
|
|
173
|
+
if (type === 'token_usage_record') {
|
|
174
|
+
const usage = isRecord(payload['usage']) ? payload['usage'] : null;
|
|
175
|
+
if (usage !== null) {
|
|
176
|
+
const t = totalsFrom(usage);
|
|
177
|
+
if (open !== null)
|
|
178
|
+
open.totals = deltaTotals(t, open.baseline);
|
|
179
|
+
lastTotals = t;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (open !== null && lastMs !== null)
|
|
184
|
+
closeOpenTurn(lastMs);
|
|
185
|
+
if (!sawAnyRecord)
|
|
186
|
+
return { error: 'no parseable JSON lines in rollout text' };
|
|
187
|
+
if (id === null) {
|
|
188
|
+
// Last resort: the uuid embedded in `rollout-<ts>-<uuid>.jsonl` — never invented, only read back.
|
|
189
|
+
// A plain "greedy dash" regex would stop at the uuid's OWN internal dashes (its 8-4-4-4-12 hex
|
|
190
|
+
// groups), so this matches the canonical uuid shape explicitly rather than "everything after the
|
|
191
|
+
// last dash".
|
|
192
|
+
const m = typeof fileName === 'string'
|
|
193
|
+
? /([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\.jsonl$/.exec(fileName)
|
|
194
|
+
: null;
|
|
195
|
+
id = m !== null ? (m[1] ?? null) : null;
|
|
196
|
+
}
|
|
197
|
+
if (id === null)
|
|
198
|
+
return { error: 'no session_meta record and no id in fileName — cannot identify this rollout' };
|
|
199
|
+
if (lastTotals === null) {
|
|
200
|
+
return { error: 'no token_count or token_usage_record entry — nothing to attribute' };
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
id,
|
|
204
|
+
cwd,
|
|
205
|
+
model: turnContextModel ?? sessionMetaModel,
|
|
206
|
+
startedAt: isoOrNull(firstMs),
|
|
207
|
+
endedAt: isoOrNull(lastMs),
|
|
208
|
+
totals: lastTotals,
|
|
209
|
+
granularity: closedTurns.length > 0 ? 'turn' : 'session',
|
|
210
|
+
unmatchableTurns,
|
|
211
|
+
turns: closedTurns,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* measurement-integrity fix-round-1/F5 (Codex r1 HIGH #5): every candidate window `matchCodexRollouts`
|
|
216
|
+
* may attribute spend to, at the SHARPEST granularity `parseCodexRollout` could recover from the
|
|
217
|
+
* file. For a `granularity: 'turn'` rollout this is one candidate PER TURN THAT ACTUALLY CARRIES
|
|
218
|
+
* USAGE (a turn nothing was ever attributed to yields no candidate — there is nothing honest to
|
|
219
|
+
* report for it); for `granularity: 'session'` it is exactly one candidate, the whole file, exactly
|
|
220
|
+
* as this reader behaved before this fix.
|
|
221
|
+
*
|
|
222
|
+
* This is the fix for the CRITICAL scenario the Codex review named: the OLD matcher tested the
|
|
223
|
+
* whole session's `[startedAt, endedAt]` against the query window, so ANY brief overlap with that wide
|
|
224
|
+
* interval could attribute an entire multi-turn session's cumulative spend (and, potentially, another
|
|
225
|
+
* turn's DIFFERENT model) to one stage. Scoping candidates to turns means two turns of the SAME
|
|
226
|
+
* session that only one of them overlaps the window can no longer collide — and two turns that BOTH
|
|
227
|
+
* overlap it correctly produce two candidates, which the caller below turns into `ambiguous` rather
|
|
228
|
+
* than an arbitrary pick (this is also where "the model of every usage-bearing turn matching a window
|
|
229
|
+
* must agree" ends up enforced: two turns with different models can only both match by being two
|
|
230
|
+
* SEPARATE candidates, which is ambiguous by construction — there is no path where a mismatch is
|
|
231
|
+
* silently resolved to one of them).
|
|
232
|
+
*/
|
|
233
|
+
function candidateViewsOf(r) {
|
|
234
|
+
if (r.granularity === 'session')
|
|
235
|
+
return [r];
|
|
236
|
+
const out = [];
|
|
237
|
+
for (const turn of r.turns) {
|
|
238
|
+
if (turn.totals === null)
|
|
239
|
+
continue; // nothing was ever attributed to this turn — not a candidate
|
|
240
|
+
out.push({
|
|
241
|
+
id: r.id,
|
|
242
|
+
unmatchableTurns: r.unmatchableTurns,
|
|
243
|
+
cwd: turn.cwd,
|
|
244
|
+
model: turn.model,
|
|
245
|
+
startedAt: turn.startedAt,
|
|
246
|
+
endedAt: turn.endedAt,
|
|
247
|
+
totals: turn.totals,
|
|
248
|
+
granularity: 'turn',
|
|
249
|
+
turns: [turn],
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return out;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Which candidate VIEWS (session-level, or — per {@link candidateViewsOf} — turn-level whenever the
|
|
256
|
+
* schema recovered turn boundaries) have an interval that OVERLAPS the given `[from, to]` window
|
|
257
|
+
* (never nearest-in-time — ADR-001 D3 rejects "closest by clock" because two reviews back to back
|
|
258
|
+
* would attribute one's spend to the other). A candidate with no parseable timestamps never matches —
|
|
259
|
+
* an unattributable interval is not a wildcard.
|
|
260
|
+
*
|
|
261
|
+
* `0` matches → `{status:'none'}`. `1` → `{status:'one', rollout}`. `>1` → `{status:'ambiguous',
|
|
262
|
+
* candidates}` — NEVER an arbitrary pick of "the first" (NFR-3). `>1` also covers the case where two
|
|
263
|
+
* DIFFERENT turns (of the same or different rollouts) overlap the window with different models — that
|
|
264
|
+
* disagreement can never resolve to a lone `'one'`, it always surfaces as `'ambiguous'`.
|
|
265
|
+
*/
|
|
266
|
+
export function matchCodexRollouts(rollouts, window) {
|
|
267
|
+
const fromMs = Date.parse(window.from);
|
|
268
|
+
const toMs = Date.parse(window.to);
|
|
269
|
+
if (!Number.isFinite(fromMs) || !Number.isFinite(toMs) || fromMs > toMs)
|
|
270
|
+
return { status: 'none' };
|
|
271
|
+
const candidates = [];
|
|
272
|
+
for (const r of rollouts) {
|
|
273
|
+
for (const view of candidateViewsOf(r)) {
|
|
274
|
+
if (view.startedAt === null || view.endedAt === null)
|
|
275
|
+
continue;
|
|
276
|
+
const startMs = Date.parse(view.startedAt);
|
|
277
|
+
const endMs = Date.parse(view.endedAt);
|
|
278
|
+
if (!Number.isFinite(startMs) || !Number.isFinite(endMs))
|
|
279
|
+
continue;
|
|
280
|
+
// Lead delta after Codex r2 (#5): the turn must START inside the window — a turn that merely
|
|
281
|
+
// brushes the window's edge (any-overlap) is exactly how a neighbouring dispatch's turn leaks in.
|
|
282
|
+
if (startMs < fromMs || startMs > toMs)
|
|
283
|
+
continue;
|
|
284
|
+
if (window.cwd !== undefined && view.cwd !== window.cwd)
|
|
285
|
+
continue;
|
|
286
|
+
if (window.model !== undefined && view.model !== window.model)
|
|
287
|
+
continue;
|
|
288
|
+
candidates.push(view);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (candidates.length === 0)
|
|
292
|
+
return { status: 'none' };
|
|
293
|
+
if (candidates.length === 1)
|
|
294
|
+
return { status: 'one', rollout: candidates[0] };
|
|
295
|
+
return { status: 'ambiguous', candidates };
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=codex-rollouts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-rollouts.js","sourceRoot":"","sources":["../src/codex-rollouts.ts"],"names":[],"mappings":"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"}
|
package/dist/cost-ledger.d.ts
CHANGED
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
*
|
|
48
48
|
* @packageDocumentation
|
|
49
49
|
*/
|
|
50
|
+
import type { CanonicalStage } from './feature-adr-stage-canon.js';
|
|
50
51
|
/** The one sentence that states what the ledger is and is not. Printed by EVERY surface (ADR-003). */
|
|
51
52
|
export declare const COST_LEDGER_SCOPE: string;
|
|
52
53
|
export type CostLedgerDefectKind =
|
|
@@ -70,10 +71,16 @@ export type CostLedgerDefectKind =
|
|
|
70
71
|
*/
|
|
71
72
|
export declare const COST_LEDGER_DEFECT_KINDS: readonly CostLedgerDefectKind[];
|
|
72
73
|
/**
|
|
73
|
-
*
|
|
74
|
-
* `verdict !== 'DEFECT'` as "reconciled" (ADR-003).
|
|
74
|
+
* Four values, not two (measurement-integrity ADR-001 D2 grew this from three). `INSUFFICIENT_DATA`
|
|
75
|
+
* is NOT success: a caller must not read `verdict !== 'DEFECT'` as "reconciled" (ADR-003).
|
|
76
|
+
* `INCOMPLETE_INVENTORY` is likewise not success — it names the SPECIFIC case where every unaccounted
|
|
77
|
+
* token traces to a named orphan transcript (a directory listing the record's own inventory does not
|
|
78
|
+
* know about), with no OTHER attribution defect present. It outranks `BALANCED` (an orphan transcript
|
|
79
|
+
* can never read as balanced) and is outranked by `DEFECT` (a genuine attribution defect — double
|
|
80
|
+
* counting, a foreign sample, spend unaccounted for reasons OTHER than a named orphan — is a worse
|
|
81
|
+
* finding than "the inventory is incomplete but everything it does have reconciles").
|
|
75
82
|
*/
|
|
76
|
-
export type CostLedgerVerdict = 'BALANCED' | 'DEFECT' | 'INSUFFICIENT_DATA';
|
|
83
|
+
export type CostLedgerVerdict = 'BALANCED' | 'DEFECT' | 'INCOMPLETE_INVENTORY' | 'INSUFFICIENT_DATA';
|
|
77
84
|
export declare const COST_LEDGER_VERDICTS: readonly CostLedgerVerdict[];
|
|
78
85
|
/**
|
|
79
86
|
* Default reconciliation tolerance, as a FRACTION of the run total. Zero, because the arithmetic is
|
|
@@ -128,6 +135,17 @@ export interface CostLedgerRow {
|
|
|
128
135
|
readonly slug: string | null;
|
|
129
136
|
/** `stageLabel()` output, verbatim. */
|
|
130
137
|
readonly stage: string;
|
|
138
|
+
/** measurement-integrity FR-2/ADR-001 D1: the canonical bucket `stage` classifies into, NEXT TO
|
|
139
|
+
* the untouched verbatim `stage` — never a replacement for it. `'unknown'` when no rule matches. */
|
|
140
|
+
readonly stageCanonical: CanonicalStage | 'unknown';
|
|
141
|
+
/** measurement-integrity FR-4: 1-based position of THIS occurrence among stage entries that share
|
|
142
|
+
* `stage`'s exact label, in record order — `attempt: 1, attempts: 1` when the label occurs once. */
|
|
143
|
+
readonly attempt: number;
|
|
144
|
+
/** Total number of stage entries in this run that share `stage`'s exact label. A repeated label no
|
|
145
|
+
* longer merges silently into one row (ADR-001 D... measurement-integrity FR-4): each occurrence
|
|
146
|
+
* is its OWN row, and every one of them carries the same `attempts` count so a reader grouping by
|
|
147
|
+
* `stage` can tell there were several without re-deriving it. */
|
|
148
|
+
readonly attempts: number;
|
|
131
149
|
readonly phase: string | null;
|
|
132
150
|
/** The stage's model id, or `'mixed'` when several agents share a label with different models. */
|
|
133
151
|
readonly model: string;
|
|
@@ -172,6 +190,18 @@ export interface CostLedgerReconciliation {
|
|
|
172
190
|
readonly identityHolds: boolean;
|
|
173
191
|
readonly verdict: CostLedgerVerdict;
|
|
174
192
|
readonly defects: readonly CostLedgerDefect[];
|
|
193
|
+
/** measurement-integrity FR-3/ADR-001 D2: transcripts present in the run's directory that have NO
|
|
194
|
+
* `workflowProgress[]` entry in the record — named explicitly rather than dissolved into a generic
|
|
195
|
+
* `unaccountedTokens` remainder. `method: 'per-transcript'` means `tokens` is an exact sum over
|
|
196
|
+
* each orphan's own extracted samples; `'count-fallback'` means only the COUNT (and, where
|
|
197
|
+
* available, the ids) is known and `tokens` falls back to the reconciliation's own
|
|
198
|
+
* `unaccountedTokens` as the best available estimate — always present, always additive. */
|
|
199
|
+
readonly orphanTranscripts: {
|
|
200
|
+
readonly count: number;
|
|
201
|
+
readonly tokens: number;
|
|
202
|
+
readonly ids: readonly string[];
|
|
203
|
+
readonly method: 'per-transcript' | 'count-fallback';
|
|
204
|
+
};
|
|
175
205
|
}
|
|
176
206
|
export interface CostLedgerReport {
|
|
177
207
|
readonly runId: string;
|
|
@@ -180,6 +210,16 @@ export interface CostLedgerReport {
|
|
|
180
210
|
readonly status: string | null;
|
|
181
211
|
readonly startedTs: string | null;
|
|
182
212
|
readonly rows: readonly CostLedgerRow[];
|
|
213
|
+
/** measurement-integrity FR-2/T1: rows re-aggregated by `stageCanonical`, plus two synthetic
|
|
214
|
+
* buckets — `unknown` (rows whose verbatim label matched no canon rule) and `unattributed` (the
|
|
215
|
+
* orphan-transcript tokens from `reconciliation.orphanTranscripts`, which belong to no stage row
|
|
216
|
+
* at all). Every one of the 12 {@link CanonicalStage} values is always present, even at zero, so a
|
|
217
|
+
* reader can iterate a stable key set. */
|
|
218
|
+
readonly byCanonicalStage: Record<CanonicalStage | 'unknown' | 'unattributed', {
|
|
219
|
+
readonly tokens: number;
|
|
220
|
+
readonly agents: number;
|
|
221
|
+
readonly attempts: number;
|
|
222
|
+
}>;
|
|
183
223
|
readonly reconciliation: CostLedgerReconciliation;
|
|
184
224
|
/** The record's cached raw sum — reported, never the invariant's right-hand side (ADR-002). */
|
|
185
225
|
readonly recordTotalTokens: number | null;
|
|
@@ -232,8 +272,20 @@ export interface BuildCostLedgerInput {
|
|
|
232
272
|
}[];
|
|
233
273
|
/** RIGHT side — the dedup-union over the run's transcript DIRECTORY (ADR-002). */
|
|
234
274
|
readonly runSamples: readonly CostLedgerSample[];
|
|
235
|
-
/** Agent transcripts present in the run directory with no `workflowProgress[]` entry.
|
|
275
|
+
/** Agent transcripts present in the run directory with no `workflowProgress[]` entry — ids only.
|
|
276
|
+
* Kept for the `Unaccounted` defect's `subjects` listing; superseded by `orphanTranscripts` below
|
|
277
|
+
* for the FR-3 `orphanTranscripts.tokens` figure whenever the caller can supply per-orphan samples. */
|
|
236
278
|
readonly orphanAgentIds?: readonly string[];
|
|
279
|
+
/** measurement-integrity FR-3: the SAME orphan transcripts as `orphanAgentIds`, but carrying each
|
|
280
|
+
* one's own extracted samples so `reconciliation.orphanTranscripts.tokens` is an EXACT sum rather
|
|
281
|
+
* than a derived remainder. When omitted, `orphanAgentIds` alone still produces a named
|
|
282
|
+
* `orphanTranscripts` entry (`method: 'count-fallback'`, `tokens` = the reconciliation's own
|
|
283
|
+
* `unaccountedTokens` as the best available estimate) — the count/ids are never lost even without
|
|
284
|
+
* the precise per-transcript figure. */
|
|
285
|
+
readonly orphanTranscripts?: readonly {
|
|
286
|
+
readonly agentId: string;
|
|
287
|
+
readonly samples: readonly CostLedgerSample[];
|
|
288
|
+
}[];
|
|
237
289
|
/** Fraction of the run total tolerated as unaccounted. Default {@link DEFAULT_COST_LEDGER_EPSILON}. */
|
|
238
290
|
readonly epsilon?: number;
|
|
239
291
|
/** True when the transcript listing hit the file cap — the run total is incomplete (Codex QE HIGH). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost-ledger.d.ts","sourceRoot":"","sources":["../src/cost-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;
|
|
1
|
+
{"version":3,"file":"cost-ledger.d.ts","sourceRoot":"","sources":["../src/cost-ledger.ts"],"names":[],"mappings":"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"}
|