@dzhechkov/harness-core 0.8.36 → 0.8.38

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 (112) hide show
  1. package/.dz-manifest.json +216 -76
  2. package/README.md +349 -8
  3. package/dist/agentdb-index.d.ts +87 -7
  4. package/dist/agentdb-index.d.ts.map +1 -1
  5. package/dist/agentdb-index.js +416 -57
  6. package/dist/agentdb-index.js.map +1 -1
  7. package/dist/apply-leg.d.ts +19 -1
  8. package/dist/apply-leg.d.ts.map +1 -1
  9. package/dist/apply-leg.js +187 -36
  10. package/dist/apply-leg.js.map +1 -1
  11. package/dist/codex-rollouts.d.ts +118 -0
  12. package/dist/codex-rollouts.d.ts.map +1 -0
  13. package/dist/codex-rollouts.js +297 -0
  14. package/dist/codex-rollouts.js.map +1 -0
  15. package/dist/cost-ledger.d.ts +56 -4
  16. package/dist/cost-ledger.d.ts.map +1 -1
  17. package/dist/cost-ledger.js +176 -20
  18. package/dist/cost-ledger.js.map +1 -1
  19. package/dist/cross-family-control.d.ts +380 -0
  20. package/dist/cross-family-control.d.ts.map +1 -0
  21. package/dist/cross-family-control.js +848 -0
  22. package/dist/cross-family-control.js.map +1 -0
  23. package/dist/debt-ratchet.d.ts +53 -0
  24. package/dist/debt-ratchet.d.ts.map +1 -0
  25. package/dist/debt-ratchet.js +107 -0
  26. package/dist/debt-ratchet.js.map +1 -0
  27. package/dist/embedding-config.d.ts +42 -0
  28. package/dist/embedding-config.d.ts.map +1 -1
  29. package/dist/embedding-config.js +106 -10
  30. package/dist/embedding-config.js.map +1 -1
  31. package/dist/feature-adr-checkpoints.d.ts +6 -0
  32. package/dist/feature-adr-checkpoints.d.ts.map +1 -1
  33. package/dist/feature-adr-checkpoints.js +29 -0
  34. package/dist/feature-adr-checkpoints.js.map +1 -1
  35. package/dist/feature-adr-decision-recall.d.ts +2 -2
  36. package/dist/feature-adr-decision-recall.d.ts.map +1 -1
  37. package/dist/feature-adr-decision-recall.js +5 -3
  38. package/dist/feature-adr-decision-recall.js.map +1 -1
  39. package/dist/feature-adr-envelope.d.ts +96 -0
  40. package/dist/feature-adr-envelope.d.ts.map +1 -0
  41. package/dist/feature-adr-envelope.js +183 -0
  42. package/dist/feature-adr-envelope.js.map +1 -0
  43. package/dist/feature-adr-routing.d.ts +64 -0
  44. package/dist/feature-adr-routing.d.ts.map +1 -1
  45. package/dist/feature-adr-routing.js +133 -3
  46. package/dist/feature-adr-routing.js.map +1 -1
  47. package/dist/feature-adr-stage-canon.d.ts +79 -0
  48. package/dist/feature-adr-stage-canon.d.ts.map +1 -0
  49. package/dist/feature-adr-stage-canon.js +117 -0
  50. package/dist/feature-adr-stage-canon.js.map +1 -0
  51. package/dist/index.d.ts +21 -9
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +15 -5
  54. package/dist/index.js.map +1 -1
  55. package/dist/loop-blobs.generated.js +4 -4
  56. package/dist/loop-blobs.generated.js.map +1 -1
  57. package/dist/mutation-gate.d.ts +51 -0
  58. package/dist/mutation-gate.d.ts.map +1 -1
  59. package/dist/mutation-gate.js +295 -0
  60. package/dist/mutation-gate.js.map +1 -1
  61. package/dist/qe-bridge.d.ts +8 -0
  62. package/dist/qe-bridge.d.ts.map +1 -1
  63. package/dist/qe-bridge.js +4 -2
  64. package/dist/qe-bridge.js.map +1 -1
  65. package/dist/qe-findings.d.ts +107 -0
  66. package/dist/qe-findings.d.ts.map +1 -0
  67. package/dist/qe-findings.js +417 -0
  68. package/dist/qe-findings.js.map +1 -0
  69. package/dist/recap.d.ts +1 -1
  70. package/dist/recap.d.ts.map +1 -1
  71. package/dist/recap.js +4 -2
  72. package/dist/recap.js.map +1 -1
  73. package/dist/review-cost.d.ts +51 -0
  74. package/dist/review-cost.d.ts.map +1 -0
  75. package/dist/review-cost.js +110 -0
  76. package/dist/review-cost.js.map +1 -0
  77. package/dist/round.d.ts +207 -1
  78. package/dist/round.d.ts.map +1 -1
  79. package/dist/round.js +321 -4
  80. package/dist/round.js.map +1 -1
  81. package/dist/run-records.d.ts +97 -0
  82. package/dist/run-records.d.ts.map +1 -1
  83. package/dist/run-records.js +336 -2
  84. package/dist/run-records.js.map +1 -1
  85. package/dist/score.d.ts +44 -1
  86. package/dist/score.d.ts.map +1 -1
  87. package/dist/score.js +78 -5
  88. package/dist/score.js.map +1 -1
  89. package/package.json +1 -1
  90. package/sbom.json +425 -75
  91. package/src/agentdb-index.ts +423 -60
  92. package/src/apply-leg.ts +187 -36
  93. package/src/codex-rollouts.ts +374 -0
  94. package/src/cost-ledger.ts +232 -24
  95. package/src/cross-family-control.ts +1038 -0
  96. package/src/debt-ratchet.ts +143 -0
  97. package/src/embedding-config.ts +131 -10
  98. package/src/feature-adr-checkpoints.ts +29 -0
  99. package/src/feature-adr-decision-recall.ts +6 -4
  100. package/src/feature-adr-envelope.ts +242 -0
  101. package/src/feature-adr-routing.ts +150 -3
  102. package/src/feature-adr-stage-canon.ts +141 -0
  103. package/src/index.ts +65 -6
  104. package/src/loop-blobs.generated.ts +4 -4
  105. package/src/mutation-gate.ts +316 -0
  106. package/src/qe-bridge.ts +12 -2
  107. package/src/qe-findings.ts +463 -0
  108. package/src/recap.ts +10 -3
  109. package/src/review-cost.ts +139 -0
  110. package/src/round.ts +481 -6
  111. package/src/run-records.ts +388 -2
  112. package/src/score.ts +115 -6
package/dist/round.js CHANGED
@@ -3,20 +3,54 @@
3
3
  * lesson ids, ledger writing/reading and pid liveness. In particular, this file never imports a
4
4
  * filesystem or process API; the CLI owns `.dz/rounds/` and the witnessed ledger writer.
5
5
  */
6
+ import { validateExperimentEnvelope } from './feature-adr-envelope.js';
6
7
  const ROUND_OUTCOMES = ['shipped', 'refuted', 'blocked', 'abandoned'];
7
8
  function nonEmpty(value) {
8
9
  return typeof value === 'string' && value.trim() !== '';
9
10
  }
11
+ /** review-cost-ledger fix-round-1 #1/#2 (ADR-001 п.2 amended): does an explicit `--reviewer` AGREE
12
+ * with the qe-bridge sidecar's own `gradedBy` (already normalized by the caller to `family:model`,
13
+ * e.g. `claude:sonnet`)? Case-insensitive. An exact `family:model` match agrees; a FAMILY-ONLY flag
14
+ * (no `:` in it at all, e.g. `claude`) agrees with ANY `family:*` gradedBy of that same family —
15
+ * the lead naming only the family (not a specific model) is still confirming the sidecar's identity.
16
+ * Anything else (a different family, or a full `family:model` that does not match exactly) does NOT
17
+ * agree — `closeRound` refuses that case outright rather than guessing which one is right. */
18
+ function reviewerAgreesWithSidecar(reviewerFlag, gradedBy) {
19
+ const flag = reviewerFlag.trim().toLowerCase();
20
+ const graded = gradedBy.trim().toLowerCase();
21
+ if (flag === '' || graded === '')
22
+ return false;
23
+ if (flag === graded)
24
+ return true;
25
+ if (!flag.includes(':')) {
26
+ const gradedFamily = graded.split(':')[0] ?? '';
27
+ return flag === gradedFamily;
28
+ }
29
+ return false;
30
+ }
10
31
  function validSlug(value) {
11
32
  return /^[a-z0-9][a-z0-9._-]*$/i.test(value);
12
33
  }
13
34
  function validCount(value) {
14
35
  return value === undefined || (Number.isInteger(value) && value >= 0);
15
36
  }
37
+ /** experiment-instrument A1: a `--task` value is a non-empty string, at most 120 characters, with no
38
+ * control characters (C0 or DEL) — long/garbled input refuses rather than being silently minted. */
39
+ function validTaskId(value) {
40
+ return value.trim() !== '' && value.length <= 120 && !/[\u0000-\u001f\u007f]/.test(value);
41
+ }
16
42
  export function openRound(input) {
17
43
  if (!validSlug(input.slug) || !Number.isInteger(input.round) || input.round < 1 || !nonEmpty(input.topic)) {
18
44
  return { ok: false, exit: 2, reason: 'нужны безопасный --slug, положительный --round и непустой --topic' };
19
45
  }
46
+ if (input.envelope !== undefined) {
47
+ const v = validateExperimentEnvelope(input.envelope);
48
+ if (!v.ok)
49
+ return { ok: false, exit: 2, reason: `--envelope invalid — ${v.reason}` };
50
+ }
51
+ if (input.task !== undefined && !validTaskId(input.task)) {
52
+ return { ok: false, exit: 2, reason: '--task должен быть непустой строкой ≤120 символов без управляющих символов' };
53
+ }
20
54
  const runOwner = input.ownerKind === 'run';
21
55
  if (!Number.isFinite(Date.parse(input.startedAt)) || !Number.isInteger(input.ownerPid)
22
56
  || (runOwner ? input.ownerPid !== 0 || !nonEmpty(input.ownerRun) : input.ownerPid < 1)
@@ -33,6 +67,8 @@ export function openRound(input) {
33
67
  ...(runOwner ? { ownerRun: input.ownerRun.trim() } : {}),
34
68
  ...(nonEmpty(input.run) ? { run: input.run.trim() } : {}),
35
69
  recalled: [...input.recalled],
70
+ ...(input.envelope !== undefined ? { envelope: input.envelope } : {}),
71
+ taskId: input.task !== undefined ? input.task.trim() : `${input.slug}@${input.startedAt}`,
36
72
  };
37
73
  let existingOwnerAlive = input.existingOwnerAlive;
38
74
  if (input.existing?.ownerKind === 'run' && input.force) {
@@ -63,6 +99,15 @@ export function closeRound(input, io) {
63
99
  if (!ROUND_OUTCOMES.includes(input.outcome)) {
64
100
  return { ok: false, exit: 2, reason: '--outcome: shipped | refuted | blocked | abandoned' };
65
101
  }
102
+ // fix-round-1/F6: `openRound` validated the envelope once, at open time, then trusted it verbatim
103
+ // out of the state FILE from then on. A state file is mutable disk state between open and close —
104
+ // corrupted or hand-edited in that window, it would ride an invalid/tampered envelope straight
105
+ // into the ledger row. Re-validating here, right before the row is built, closes that window.
106
+ if (input.state.envelope !== undefined) {
107
+ const v = validateExperimentEnvelope(input.state.envelope);
108
+ if (!v.ok)
109
+ return { ok: false, exit: 2, reason: `envelope in round state invalid — ${v.reason}` };
110
+ }
66
111
  if (!validCount(input.tokens) || !validCount(input.agents)) {
67
112
  return { ok: false, exit: 2, reason: '--tokens и --agents должны быть целыми числами не меньше нуля' };
68
113
  }
@@ -78,6 +123,160 @@ export function closeRound(input, io) {
78
123
  const missing = lessons.find((id) => !/^teach:[a-z0-9]+$/i.test(id) || !known.has(id));
79
124
  if (missing !== undefined)
80
125
  return { ok: false, exit: 1, reason: `урок не найден: ${missing}` };
126
+ // measurement-integrity FR-7 (ADR-001 D5): grade is mandatory for a FINISHED review
127
+ // (shipped|refuted), a warned-and-dropped no-op for one that never finished (blocked|abandoned —
128
+ // "Отвергнуто: --grade всегда обязателен — заблокированный круг оценки не имеет"). Placed AFTER
129
+ // the outcome/envelope/tokens/lesson checks above (unchanged ordering, unchanged refusal reasons
130
+ // for those) and BEFORE the duration/row-build below.
131
+ const outcome = input.outcome;
132
+ const finishedOutcome = outcome === 'shipped' || outcome === 'refuted';
133
+ const gradeFlagRaw = nonEmpty(input.grade) ? input.grade.trim() : null;
134
+ if (gradeFlagRaw !== null && !/^[A-F][+-]?$/.test(gradeFlagRaw)) {
135
+ return { ok: false, exit: 2, reason: `--grade "${gradeFlagRaw}" не распознан — ожидается вид A|A-|B+|C…F` };
136
+ }
137
+ const warnings = [];
138
+ // measurement-integrity fix-round-1/F10 (Codex r1 MEDIUM #10): for an UNFINISHED outcome, --grade
139
+ // is dropped-with-warning HERE, BEFORE it is ever compared against the sidecar. The OLD ordering
140
+ // ran the conflict check first — so `--outcome blocked --grade B` against a STALE sidecar grade
141
+ // `A` refused outright instead of the promised warning-and-drop, because a value that was about to
142
+ // be discarded still had to survive a conflict check on its way to being discarded. `gradeFlag` is
143
+ // `null` for an unfinished outcome from this point on, exactly as if `--grade` had never been
144
+ // passed — the conflict check below therefore never sees it.
145
+ const gradeFlag = finishedOutcome ? gradeFlagRaw : null;
146
+ if (!finishedOutcome && gradeFlagRaw !== null) {
147
+ warnings.push(`--grade "${gradeFlagRaw}" проигнорирован: outcome=${outcome} не является завершённым ревью, оценка не пишется`);
148
+ }
149
+ const sidecarGrade = input.reviewSidecar !== undefined && nonEmpty(input.reviewSidecar.grade ?? undefined)
150
+ ? input.reviewSidecar.grade.trim()
151
+ : null;
152
+ if (gradeFlag !== null && sidecarGrade !== null && gradeFlag !== sidecarGrade) {
153
+ return {
154
+ ok: false,
155
+ exit: 2,
156
+ reason: `--grade "${gradeFlag}" конфликтует с оценкой сайдкара qe-bridge "${sidecarGrade}" для slug ${input.state.slug}`,
157
+ };
158
+ }
159
+ if (finishedOutcome && gradeFlag === null) {
160
+ return { ok: false, exit: 2, reason: `grade required for a finished review: outcome=${outcome} требует --grade <A|A-|B+|…>` };
161
+ }
162
+ const gradeForRow = gradeFlag;
163
+ // reviewer/reviewMinutes/reviewSource: reviewer is TIED to the sidecar (ADR-001 п.2, amended by
164
+ // fix-round-1 #1/#2 after the Codex r1 BLOCKER/CRITICAL pair) either (a) it is FILLED from the
165
+ // sidecar (no explicit --reviewer), or (b) it is an explicit --reviewer that AGREES with the
166
+ // sidecar's own gradedBy. Case (b) exists because the pipeline's normal path ALWAYS passes
167
+ // --reviewer (feature-adr.js) — under the old "flag always wins, sidecar never trusted for cost"
168
+ // rule, the price this feature exists to record would NEVER be written on that path (BLOCKER #1).
169
+ // A DISAGREEING explicit --reviewer is refused outright, below — never silently ignored, and never
170
+ // silently misattributed (CRITICAL #2).
171
+ let reviewer = nonEmpty(input.reviewer) ? input.reviewer.trim() : null;
172
+ let reviewMinutes = null;
173
+ let reviewSource = null;
174
+ const sidecarGradedBy = input.reviewSidecar !== undefined && nonEmpty(input.reviewSidecar.gradedBy)
175
+ ? input.reviewSidecar.gradedBy.trim()
176
+ : null;
177
+ if (reviewer === null && sidecarGradedBy !== null) {
178
+ reviewer = sidecarGradedBy;
179
+ const elapsedMs = input.reviewSidecar.elapsedMs;
180
+ reviewMinutes = Number.isFinite(elapsedMs) && elapsedMs >= 0 ? Math.round((elapsedMs / 60_000) * 10) / 10 : null;
181
+ reviewSource = 'qe-bridge';
182
+ }
183
+ else if (reviewer !== null && sidecarGradedBy !== null) {
184
+ if (reviewerAgreesWithSidecar(reviewer, sidecarGradedBy)) {
185
+ const elapsedMs = input.reviewSidecar.elapsedMs;
186
+ reviewMinutes = Number.isFinite(elapsedMs) && elapsedMs >= 0 ? Math.round((elapsedMs / 60_000) * 10) / 10 : null;
187
+ reviewSource = 'flag+qe-bridge';
188
+ }
189
+ else {
190
+ // fix-round-1 #1/#2 (ADR-001 п.2 amended): the same discipline a --grade disagreeing with the
191
+ // sidecar's own grade already follows (FR-7) — an explicit reviewer naming someone ELSE than
192
+ // the sidecar's own reviewer must never silently receive (or silently omit) that reviewer's
193
+ // price; it refuses, naming both values, before any row is built.
194
+ return {
195
+ ok: false,
196
+ exit: 2,
197
+ reason: `--reviewer "${reviewer}" conflicts with the qe-bridge sidecar's reviewer "${sidecarGradedBy}" for slug ${input.state.slug}`,
198
+ };
199
+ }
200
+ }
201
+ // review-cost-ledger FR-3/A4 (ADR-001 п.4): a FINISHED review (shipped|refuted) with NEITHER an
202
+ // explicit --reviewer NOR one filled from the sidecar is unmeasurable by definition — the audit
203
+ // this feature exists to close (ADR-001 Q5). blocked|abandoned carry no such requirement, same as
204
+ // they carry no grade requirement above: a review that never finished has no reviewer to name yet.
205
+ if (finishedOutcome && reviewer === null) {
206
+ return {
207
+ ok: false,
208
+ exit: 2,
209
+ reason: `finished review requires a reviewer: outcome=${outcome} needs --reviewer <model> (no --reviewer flag and no qe-bridge signoff to fill it from)`,
210
+ };
211
+ }
212
+ // review-cost-ledger FR-2/A2/A3 (ADR-001 п.1-3, amended by fix-round-1 #2/#3/#5): the reviewer's
213
+ // price is written ONLY when the row's reviewer is TIED to the sidecar — reviewSource is
214
+ // 'qe-bridge' or 'flag+qe-bridge' (the two cases computed above). fix-round-1 #2 (Codex r1
215
+ // CRITICAL #2): the old "or it carries no gradedBy at all" hack is REMOVED — an untrusted sidecar
216
+ // (empty gradedBy, e.g. T3's Codex-no-signoff synthesis) can still explain an ABSENT/UNPARSEABLE
217
+ // price (that is a structural fact about the instrument, not an attribution), but it can NEVER
218
+ // yield an 'ok' price for a reviewer it was not written for — an adversarial ok-cost sidecar with
219
+ // an empty gradedBy is exactly the CRITICAL #2 failing input, and it must never buy a price here.
220
+ let reviewerCostFields = null;
221
+ const sidecarCost = input.reviewSidecar?.cost;
222
+ const reviewerTiedToSidecar = reviewSource === 'qe-bridge' || reviewSource === 'flag+qe-bridge';
223
+ if (reviewerTiedToSidecar) {
224
+ // fix-round-1 #3 (Codex r1 HIGH #3): a sidecar that filled/confirmed the reviewer but carries NO
225
+ // cost record at all (cost undefined) used to leave every price field silently absent — the same
226
+ // "never a bare unexplained gap" discipline as `shipShaReason` now applies here too.
227
+ if (sidecarCost === undefined) {
228
+ reviewerCostFields = { reviewerCostUsd: null, reviewerCostSource: 'unavailable', reviewerCostReason: 'sidecar carried no cost record' };
229
+ }
230
+ else if (sidecarCost.status === 'ok') {
231
+ // fix-round-1 #5 (Codex r1 HIGH #5): tokensPartial on the sidecar means the sum is NOT a real
232
+ // count (at least one component was missing) — reviewerTokens goes null rather than a silently
233
+ // zeroed/short sum, while the still-valid price and the partial breakdown are kept.
234
+ const partial = sidecarCost.tokens.tokensPartial === true;
235
+ reviewerCostFields = {
236
+ reviewerCostUsd: sidecarCost.costUsd,
237
+ reviewerTokens: partial ? null : sidecarCost.tokens.total,
238
+ reviewerTokensBreakdown: {
239
+ input: sidecarCost.tokens.input,
240
+ output: sidecarCost.tokens.output,
241
+ cacheCreation: sidecarCost.tokens.cacheCreation,
242
+ cacheRead: sidecarCost.tokens.cacheRead,
243
+ ...(partial ? { partial: true } : {}),
244
+ },
245
+ reviewerCostSource: 'qe-bridge-stdout',
246
+ };
247
+ }
248
+ else {
249
+ const reason = nonEmpty(sidecarCost.reason)
250
+ ? sidecarCost.reason.trim()
251
+ : 'qe-bridge stdout sidecar carried no parseable cost line';
252
+ reviewerCostFields = { reviewerCostUsd: null, reviewerCostSource: 'unavailable', reviewerCostReason: reason };
253
+ }
254
+ }
255
+ else if (sidecarCost !== undefined) {
256
+ // The reviewer is NOT tied to this sidecar (an untrusted/untied sidecar — e.g. T3's
257
+ // Codex-no-signoff synthesis, empty gradedBy). It may still explain a NAMED limit
258
+ // (status !== 'ok') — that is honest instrument metadata, not an attribution. fix-round-1 #2: an
259
+ // 'ok' status here is NEVER trusted for a price, whatever the number — the sidecar was not
260
+ // written for this reviewer, full stop.
261
+ if (sidecarCost.status !== 'ok') {
262
+ // Lead delta after Codex r2 (#2 partial): an untied sidecar's OWN reason (the cli's Codex
263
+ // "tokens not visible" synthesis) was copied onto ANY explicit reviewer's row — a Claude
264
+ // reviewer got a Codex-specific limit as its explanation. The sidecar's reason travels only
265
+ // to a reviewer of the codex family; every other untied reviewer gets the neutral fact.
266
+ const reviewerIsCodex = /^codex\b/i.test(reviewer ?? '');
267
+ const reason = reviewerIsCodex && nonEmpty(sidecarCost.reason)
268
+ ? sidecarCost.reason.trim()
269
+ : 'explicit --reviewer is not tied to a qe-bridge sidecar (no signoff names this reviewer)';
270
+ reviewerCostFields = { reviewerCostUsd: null, reviewerCostSource: 'unavailable', reviewerCostReason: reason };
271
+ }
272
+ else {
273
+ reviewerCostFields = {
274
+ reviewerCostUsd: null,
275
+ reviewerCostSource: 'unavailable',
276
+ reviewerCostReason: 'qe-bridge sidecar carried a price but is not tied to this row\'s reviewer',
277
+ };
278
+ }
279
+ }
81
280
  const startedMs = Date.parse(input.state.startedAt);
82
281
  const closedMs = Date.parse(input.closedAt);
83
282
  if (!Number.isFinite(startedMs) || !Number.isFinite(closedMs) || closedMs < startedMs) {
@@ -86,18 +285,46 @@ export function closeRound(input, io) {
86
285
  const compactTs = new Date(closedMs).toISOString().replace(/[-:.]/g, '');
87
286
  const marker = `round-${input.state.slug}-${input.state.round}-${compactTs}`;
88
287
  const note = input.note?.trim() ?? '';
288
+ // experiment-instrument FR-1/A4/A5: the state ALWAYS carries a taskId for a round opened after this
289
+ // feature; a state written before it lacks the key on disk, so the same default `openRound` mints
290
+ // is derived here and the derivation is named (`taskIdSource`) — never silently blended with a
291
+ // fresh-mint taskId, which is what `taskIdSource` absent means.
292
+ const taskIdFromState = input.state.taskId;
293
+ const taskId = nonEmpty(taskIdFromState) ? taskIdFromState.trim() : `${input.state.slug}@${input.state.startedAt}`;
294
+ const taskIdSource = nonEmpty(taskIdFromState) ? null : 'derived-legacy';
295
+ // experiment-instrument FR-3/A2: only a FINISHED outcome carries a ship anchor — `blocked|abandoned`
296
+ // never shipped anything, so a sha there would misleadingly imply a release. A null sha REQUIRES its
297
+ // reason to be recorded next to it (never a bare, unexplained null on a finished row) — r1-6 (Codex
298
+ // r1 MEDIUM #6): a caller that supplies no reason at all no longer leaves the row silently
299
+ // unexplained; a stable default fills the gap instead of an absent key.
300
+ const finishedForShip = outcome === 'shipped' || outcome === 'refuted';
301
+ const shipSha = finishedForShip ? (input.shipSha ?? null) : null;
302
+ const shipShaReason = finishedForShip && shipSha === null
303
+ ? (nonEmpty(input.shipShaReason) ? input.shipShaReason.trim() : 'not provided')
304
+ : null;
305
+ // experiment-instrument r1-5 (Codex r1 HIGH #5, ADR-001 amended): `shipTreeDirty` is present only
306
+ // when the caller (the cli) actually resolved it; `shipTreeDirtyReason` fills the gap when it could
307
+ // not be. Neither is ever guessed here — the core never shells out to compute either.
308
+ const shipTreeDirtyValue = finishedForShip && typeof input.shipTreeDirty === 'boolean'
309
+ ? input.shipTreeDirty
310
+ : undefined;
311
+ // r2-2 (Codex r2 MEDIUM N2, lead delta): a finished row with NEITHER field used to omit both —
312
+ // the same bare-gap shape r1-6 closed for the sha. The rule is symmetric: boolean, or a reason.
313
+ const shipTreeDirtyReason = finishedForShip && shipTreeDirtyValue === undefined
314
+ ? (nonEmpty(input.shipTreeDirtyReason) ? input.shipTreeDirtyReason.trim() : 'not provided')
315
+ : undefined;
89
316
  const row = {
90
317
  slug: input.state.slug,
91
318
  stage: 'round',
92
319
  tier: null,
93
320
  coder: nonEmpty(input.coder) ? input.coder.trim() : null,
94
- reviewer: nonEmpty(input.reviewer) ? input.reviewer.trim() : null,
321
+ reviewer,
95
322
  lead: null,
96
323
  minutes: input.noCost === true ? null : Math.floor((closedMs - startedMs) / 60_000),
97
324
  agents: input.noCost === true ? null : input.agents ?? null,
98
325
  tokens: input.noCost === true ? null : input.tokens ?? null,
99
- grade: null,
100
- outcome: input.outcome,
326
+ grade: gradeForRow,
327
+ outcome,
101
328
  reason: nonEmpty(input.reason) ? input.reason.trim() : null,
102
329
  round: input.state.round,
103
330
  lessons,
@@ -106,6 +333,16 @@ export function closeRound(input, io) {
106
333
  date: null,
107
334
  ...(input.noCost === true ? { costIn: 'stages' } : {}),
108
335
  ...(nonEmpty(input.stateId) ? { stateId: input.stateId } : {}),
336
+ ...(input.state.envelope !== undefined ? { envelope: input.state.envelope } : {}),
337
+ ...(reviewSource !== null ? { reviewSource } : {}),
338
+ ...(reviewMinutes !== null ? { reviewMinutes } : {}),
339
+ taskId,
340
+ ...(taskIdSource !== null ? { taskIdSource } : {}),
341
+ ...(finishedForShip ? { shipSha, shippedAt: input.closedAt } : {}),
342
+ ...(shipShaReason !== null ? { shipShaReason } : {}),
343
+ ...(shipTreeDirtyValue !== undefined ? { shipTreeDirty: shipTreeDirtyValue } : {}),
344
+ ...(shipTreeDirtyReason !== undefined ? { shipTreeDirtyReason } : {}),
345
+ ...(reviewerCostFields !== null ? reviewerCostFields : {}),
109
346
  };
110
347
  try {
111
348
  io.writeLedger(row);
@@ -121,7 +358,87 @@ export function closeRound(input, io) {
121
358
  if (!tail.includes(marker)) {
122
359
  return { ok: false, exit: 1, reason: 'строка не найдена — круг НЕ закрыт' };
123
360
  }
124
- return { ok: true, row, marker };
361
+ return { ok: true, row, marker, warnings };
362
+ }
363
+ /**
364
+ * measurement-integrity fix-round-1/F8 (Codex r1 CRITICAL #8): validate an ALREADY-WRITTEN ledger
365
+ * row against the CURRENT schema's `shipped|refuted require a grade` rule (ADR-001 D5 / FR-7).
366
+ *
367
+ * This exists for exactly one caller: `dz round close`'s idempotent-retry path. When the predicted
368
+ * marker (or `stateId`) is already found in the ledger tail, the CLI used to skip `closeRound`
369
+ * ENTIRELY and delete the round's state file — so an OLD row written before FR-7 shipped (`shipped`
370
+ * with `grade: null`, the exact defect this feature exists to close) could be "recognised as already
371
+ * closed" and the state removed without ever being checked against the rule that is supposed to be
372
+ * mandatory. This function is that missing check, run on the ALREADY-FOUND row before the CLI is
373
+ * allowed to treat the retry as a success.
374
+ *
375
+ * Deliberately NARROW: it re-checks only the ONE FR-7 invariant (a schema rule with a proving test),
376
+ * not every field `closeRound` validates on the FIRST write (grade format, envelope shape, …) — those
377
+ * were already enforced when the row was ORIGINALLY written; re-validating them here would either
378
+ * duplicate that logic or silently drift from it. Pure, never throws.
379
+ */
380
+ export function validateClosedRoundLedgerRow(row) {
381
+ if (typeof row !== 'object' || row === null || Array.isArray(row)) {
382
+ return { ok: false, reason: 'найденная строка леджера не JSON-объект — не удаётся проверить оценку' };
383
+ }
384
+ const r = row;
385
+ const outcome = r['outcome'];
386
+ if (typeof outcome !== 'string' || !ROUND_OUTCOMES.includes(outcome)) {
387
+ return { ok: false, reason: `найденная строка леджера несёт неизвестный outcome ${JSON.stringify(outcome)}` };
388
+ }
389
+ const finishedOutcome = outcome === 'shipped' || outcome === 'refuted';
390
+ if (!finishedOutcome)
391
+ return { ok: true }; // blocked|abandoned carry no grade requirement (FR-7)
392
+ const grade = r['grade'];
393
+ if (typeof grade !== 'string' || !/^[A-F][+-]?$/.test(grade)) {
394
+ return {
395
+ ok: false,
396
+ reason: `найденная строка леджера — outcome=${outcome} без валидной оценки (grade=${JSON.stringify(grade)}); ` +
397
+ 'закрытие отказано (measurement-integrity ADR-001 D5 / FR-7 требует непустую оценку для завершённого ревью)',
398
+ };
399
+ }
400
+ return { ok: true };
401
+ }
402
+ /**
403
+ * experiment-instrument FR-1/FR-3 (ADR-001 D-A): the single source every OTHER writer (an auto ledger
404
+ * row, a qe-bridge signoff, a control-review row) consults to find this slug's task identity —
405
+ * never guessed, never minted here. `states` is whatever the CALLER already read as "currently open
406
+ * round state files for this slug" (the cli walks `.dz/rounds/<slug>-*.json`); this function does not
407
+ * touch a filesystem and does not assume the caller pre-filtered by slug, so it filters again itself.
408
+ *
409
+ * `unreadableStateCount` (r1-2, Codex r1 HIGH #2) is how many FILENAMES the caller found matching this
410
+ * slug's pattern that it could NOT parse into a `RoundState` — a corrupt or half-written state file is
411
+ * never silent absence; it means the true open-round count for this slug is UNKNOWN, not zero.
412
+ *
413
+ * - Any unreadable candidate exists AND no readable one does ⇒ `{taskId: null, source: 'unavailable'}`
414
+ * — a round MAY be open here, but its state cannot be read (r1-2).
415
+ * - Any unreadable candidate exists ALONGSIDE at least one readable one ⇒ `{taskId: null, source:
416
+ * 'ambiguous'}` — the readable one might not be the only genuinely open round (r1-2).
417
+ * - Zero candidates at all (readable or not) ⇒ `{taskId: null, source: 'no-open-round'}` — no open
418
+ * round, nothing to fill from (A4).
419
+ * - Two or more readable matches, no unreadable ones ⇒ `{taskId: null, source: 'ambiguous'}` — which
420
+ * one is authoritative is not decidable here; a NULL is the honest answer, never "the latest wins" (A5).
421
+ * - Exactly one readable match, no unreadable ones ⇒ its `taskId` when the state carries one
422
+ * (`source: 'open-round'`), or the SAME `slug@startedAt` default `openRound`/`closeRound` would
423
+ * derive for a legacy state missing the field on disk — labelled `source: 'derived-legacy'` (r1-1,
424
+ * Codex r1 CRITICAL #1: this used to report `'open-round'` for an invented value, indistinguishable
425
+ * from a value the round itself actually minted).
426
+ */
427
+ export function readOpenRoundTaskId(states, slug, unreadableStateCount = 0) {
428
+ const matches = states.filter((s) => s.slug === slug);
429
+ const unreadable = Number.isFinite(unreadableStateCount) && unreadableStateCount > 0 ? Math.floor(unreadableStateCount) : 0;
430
+ if (unreadable > 0 && matches.length === 0)
431
+ return { taskId: null, source: 'unavailable' };
432
+ if (unreadable > 0)
433
+ return { taskId: null, source: 'ambiguous' };
434
+ if (matches.length === 0)
435
+ return { taskId: null, source: 'no-open-round' };
436
+ if (matches.length > 1)
437
+ return { taskId: null, source: 'ambiguous' };
438
+ const state = matches[0];
439
+ const taskId = nonEmpty(state.taskId) ? state.taskId.trim() : `${state.slug}@${state.startedAt}`;
440
+ const source = nonEmpty(state.taskId) ? 'open-round' : 'derived-legacy';
441
+ return { taskId, source };
125
442
  }
126
443
  export function listRounds(states, input) {
127
444
  if (!Number.isFinite(input.now) || !Number.isFinite(input.olderThanMinutes) || input.olderThanMinutes < 0)
package/dist/round.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"round.js","sourceRoot":"","sources":["../src/round.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,CAAU,CAAC;AAmD/E,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,UAAU,CAAC,KAAyB;IAC3C,OAAO,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAczB;IACC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1G,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,mEAAmE,EAAE,CAAC;IAC7G,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC;IAC3C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;WACjF,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;WACnF,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,KAAK,UAAU,IAAI,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,EAAE,CAAC;QACnF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC;IAClF,CAAC;IACD,MAAM,KAAK,GAAe;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;QACzB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,EAAE,KAAK,CAAC,QAAQ;QACnB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,QAAQ,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;KAC9B,CAAC;IACF,IAAI,kBAAkB,GAAG,KAAK,CAAC,kBAAkB,CAAC;IAClD,IAAI,KAAK,CAAC,QAAQ,EAAE,SAAS,KAAK,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QACvD,IAAI,CAAC;YAAC,kBAAkB,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAAC,CAAC;QAClH,MAAM,CAAC;YAAC,kBAAkB,GAAG,IAAI,CAAC;QAAC,CAAC;IACtC,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,kBAAkB,KAAK,KAAK,EAAE,CAAC;QAC3E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACpD,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,KAAK,KAAK;gBACxC,CAAC,CAAC,8BAA8B,KAAK,CAAC,QAAQ,CAAC,QAAQ,IAAI,SAAS,wCAAwC;gBAC5G,CAAC,CAAC,+BAA+B,KAAK,CAAC,QAAQ,CAAC,GAAG,wCAAwC;SAC9F,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACtF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAe1B,EAAE,EAGF;IACC,IAAI,CAAE,cAAoC,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACnE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,oDAAoD,EAAE,CAAC;IAC9F,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,+DAA+D,EAAE,CAAC;IACzG,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC1D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,cAAc,KAAK,EAAE,EAAE,CAAC;QAClD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,iFAAiF,EAAE,CAAC;IAC3H,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,KAAK,EAAE,EAAE,CAAC;QAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,iDAAiD,EAAE,CAAC;IAC3F,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACvF,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,mBAAmB,OAAO,EAAE,EAAE,CAAC;IAE/F,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,SAAS,EAAE,CAAC;QACtF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,gEAAgE,EAAE,CAAC;IAC1G,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,SAAS,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACtC,MAAM,GAAG,GAAmB;QAC1B,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;QACtB,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;QACxD,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;QACjE,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC;QACnF,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI;QAC3D,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI;QAC3D,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,KAAK,CAAC,OAAuB;QACtC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;QAC3D,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK;QACxB,OAAO;QACP,cAAc,EAAE,cAAc,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc;QAC7D,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,IAAI,EAAE;QAClD,IAAI,EAAE,IAAI;QACV,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/D,CAAC;IAEF,IAAI,CAAC;QACH,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,uDAAuD,EAAE,CAAC;IACjG,CAAC;IACD,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,CAAC;QAAC,IAAI,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,wCAAwC,CAAC,CAAC;IACtF,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAA6B,EAAE,KAKzD;IACC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACrH,MAAM,IAAI,GAA+E,EAAE,CAAC;IAC5F,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,SAAS;QAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;QAC7E,IAAI,UAAU,IAAI,KAAK,CAAC,gBAAgB;YAAE,SAAS;QACnD,IAAI,QAAQ,GAAmB,IAAI,CAAC;QACpC,IAAI,CAAC;YACH,QAAQ,GAAG,KAAK,CAAC,SAAS,KAAK,KAAK;gBAClC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;gBACxC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC,CAAC,qCAAqC,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACvI,CAAC"}
1
+ {"version":3,"file":"round.js","sourceRoot":"","sources":["../src/round.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,61 @@
12
12
  *
13
13
  * Pure: payload in, verdict out. The CLI owns paths, the append, the read-back and the exit code.
14
14
  */
15
+ import type { CodexRollout } from './codex-rollouts.js';
16
+ /** Structural — a caller passes `cost-scoring.ts`'s `ModelPricing`; kept local so `run-records.ts`
17
+ * does not have to import `cost-scoring.ts` just to name a type.
18
+ *
19
+ * measurement-integrity fix-round-1/F6 (Codex r1 HIGH #6): `cacheCreation` used to be dropped here —
20
+ * the snapshot silently lacked the ONE rate a cache-WRITE-heavy row needs to reproduce its own cost
21
+ * later, even though the caller's own `ModelPricing` carries it. Now carried through verbatim. */
22
+ export interface LedgerPriceEntry {
23
+ readonly prompt: number;
24
+ readonly completion: number;
25
+ readonly cachedInput: number;
26
+ readonly cacheCreation: number;
27
+ }
28
+ /** measurement-integrity fix-round-1/F4 (Codex r1 HIGH #4): a resolvable executor spec, split into
29
+ * its three parts. Never invents a model: {@link parseModelSpec} returns `null` for anything it
30
+ * cannot resolve to exactly one model, rather than guessing. */
31
+ export interface ParsedModelSpec {
32
+ readonly family: 'claude' | 'codex';
33
+ readonly model: string;
34
+ readonly effort: string | null;
35
+ }
36
+ /**
37
+ * Parse an executor spec — the shapes actually recorded in `coder`/`reviewer` fields
38
+ * (`codex:gpt-5.6-sol:high`, `claude:sonnet`, bare `sonnet`/`opus`, bare `codex`, bare `claude`) —
39
+ * into `{family, model, effort}`. Pure, never throws.
40
+ *
41
+ * Returns `null` (never a guess) for anything that cannot be resolved to exactly ONE model:
42
+ * - a bare `'codex'` or `'claude'` (family named, no model at all);
43
+ * - an annotated/aggregate field such as `'claude:sonnet x2'` or `'qe-bridge:claude x2 + lead'` (real
44
+ * values this ledger carries for a MULTI-reviewer round) — any embedded whitespace means the field
45
+ * names more than one resolvable spec, and picking one would misattribute to the others;
46
+ * - a bare model id with no family marker that is not one of the known bare Claude names (e.g. a full
47
+ * `'claude-sonnet-5'` — that shape is handled by the OLDER vendor-prefix path in {@link priceLookup}
48
+ * for backward compatibility, not by this parser).
49
+ */
50
+ export declare function parseModelSpec(spec: unknown): ParsedModelSpec | null;
51
+ /** measurement-integrity FR-5/FR-6: enrichment the WRITER supplies at write time — the rollout logs
52
+ * it already read (I/O lives in the CLI; this stays pure) and the price table snapshot. Absent
53
+ * entirely ⇒ zero behavior change from before this feature (NFR-1). */
54
+ export interface LedgerEnrichInput {
55
+ /** Parsed Codex rollout logs for the window the CLI read — usually every rollout from the days the
56
+ * window spans. Pure data; the CLI is the one that walked `~/.codex/sessions`. */
57
+ readonly rollouts?: readonly CodexRollout[];
58
+ /** The stage's own time window — usually [the previous ledger row's `ts`, this write's `ts`], or
59
+ * an explicit `--window-from/--window-to`. Omitted ⇒ no rollout match is even attempted. */
60
+ readonly window?: {
61
+ readonly from: string;
62
+ readonly to: string;
63
+ };
64
+ /** Narrows an otherwise-ambiguous match — usually the repo root the stage ran in. */
65
+ readonly cwd?: string;
66
+ /** A model-pricing table SNAPSHOT (FR-6) — the CALLER's table, captured at write time, never the
67
+ * ledger's own idea of "current" pricing (ADR-001 D4 rejects re-pricing after the fact). */
68
+ readonly prices?: Readonly<Record<string, LedgerPriceEntry>>;
69
+ }
15
70
  export type RecordKind = 'ledger' | 'training-pair';
16
71
  export type RecordVerdict =
17
72
  /** the line was appended AND read back equal */
@@ -68,10 +123,52 @@ export declare function decideRecordWrite(input: {
68
123
  /** Who ran it. Supplied by the CALLER, which lives outside the workflow sandbox and can see the
69
124
  * host; absent stays absent (see the stamping comment below). */
70
125
  runnerId?: string | null;
126
+ /** fix-round-1/F2: the CLI's own trusted `--auto` flag — see the comment inside `shapeMismatch`. */
127
+ auto?: boolean;
71
128
  maxChars?: number;
129
+ /** measurement-integrity FR-5/FR-6: rollout-log + price enrichment for a ledger row. Absent ⇒ zero
130
+ * behavior change (NFR-1). */
131
+ enrich?: LedgerEnrichInput;
132
+ /** experiment-instrument FR-2/A3 (ADR-001): when `true`, an AUTO ledger row that would be written
133
+ * `complete:false` is refused instead (exit 2, before any write) — a круг-B default candidate, opt-
134
+ * in today so nothing that already writes incomplete auto rows starts failing underfoot (NFR-1). */
135
+ strict?: boolean;
72
136
  }): RecordDecision;
73
137
  /** The read-back verdict (ADR-002): equal bytes or NOT written. Never inferred from the absence of an error. */
74
138
  export declare function decideReadBack(appended: string, lastLineOnDisk: string | null): RecordDecision;
75
139
  /** The one line every caller reads last, in the shape the other gates use. */
76
140
  export declare function recordVerdictLine(kind: RecordKind, stage: string, d: RecordDecision): string;
141
+ /** experiment-instrument FR-1/FR-3 (ADR-001): what `round.ts`'s `readOpenRoundTaskId` returns — the
142
+ * single source `applyTaskId` fills from. Duplicated here rather than imported so this pure module
143
+ * never depends on `round.ts`'s own shape; the CLI is the one holding both and wiring them together.
144
+ * r1-1/r1-2 (Codex r1 #1/#2): extended with `'derived-legacy'` and `'unavailable'` to stay in
145
+ * lockstep with `round.ts`'s own `readOpenRoundTaskId` return type. */
146
+ export interface TaskIdLookup {
147
+ readonly taskId: string | null;
148
+ readonly source: 'open-round' | 'derived-legacy' | 'no-open-round' | 'ambiguous' | 'unavailable';
149
+ }
150
+ /**
151
+ * experiment-instrument FR-1/FR-3/A8 (ADR-001): propagate `taskId` onto a ledger/training-pair payload
152
+ * BEFORE it reaches {@link decideRecordWrite} — fill-only-null, never overwritten.
153
+ *
154
+ * - The payload already names a non-empty `taskId` string ⇒ it is authoritative. When it DISAGREES
155
+ * with the round's own current taskId, that disagreement is a real fact worth keeping — recorded as
156
+ * `taskIdConflict: {payload, round}` — never silently resolved either way (A8).
157
+ * - The payload's `taskId` key is absent, or explicitly `null`/`undefined` ⇒ filled from `lookup`,
158
+ * INCLUDING the honest `null` case: no open round (A4) or two of them (A5) still stamps `taskId:
159
+ * null` + `taskIdSource` naming why, rather than leaving the field silently absent — absence with a
160
+ * named reason beats absence with none.
161
+ * - r1-3 (Codex r1 HIGH #3): the payload's `taskId` key is PRESENT with a value that is neither a
162
+ * non-empty string nor null/undefined (a number, a boolean, an object, or a blank/whitespace-only
163
+ * string) ⇒ that is a present-but-INVALID value, a THIRD case distinct from both of the above. It
164
+ * used to be treated exactly like "absent" (`typeof !== 'string'` fell through to the fill branch),
165
+ * silently replacing the caller's own (malformed) value with the round's — violating both
166
+ * fill-only-null and "a present payload value always wins". Now: the row's own value is preserved
167
+ * UNTOUCHED (never replaced with a guess about what the caller meant), and the problem is named in
168
+ * `taskIdInvalid` so a reader can see the row was neither filled nor trusted blindly.
169
+ *
170
+ * Pure: no filesystem, no clock. The CALLER (the cli) is the one that read `.dz/rounds/` to build
171
+ * `lookup` in the first place.
172
+ */
173
+ export declare function applyTaskId(row: Record<string, unknown>, lookup: TaskIdLookup): Record<string, unknown>;
77
174
  //# sourceMappingURL=run-records.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-records.d.ts","sourceRoot":"","sources":["../src/run-records.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,eAAe,CAAC;AAEpD,MAAM,MAAM,aAAa;AACvB,gDAAgD;AAC9C,SAAS;AACX,+EAA+E;GAC7E,WAAW;AACb,yEAAyE;GACvE,SAAS;AACX,yEAAyE;GACvE,SAAS;AACX,kGAAkG;GAChG,cAAc,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,wFAAwF;IACxF,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,2FAA2F;AAC3F,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAoD5C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,kGAAkG;IAClG,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gGAAgG;IAChG,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mGAAmG;IACnG,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;sEACkE;IAClE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,cAAc,CAyKjB;AAED,gHAAgH;AAChH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAoB9F;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CAE5F"}
1
+ {"version":3,"file":"run-records.d.ts","sourceRoot":"","sources":["../src/run-records.ts"],"names":[],"mappings":"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"}