@dzhechkov/harness-cli 0.7.5 → 0.7.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"known-flags.d.ts","sourceRoot":"","sources":["../src/known-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAuR5C,CAAC"}
1
+ {"version":3,"file":"known-flags.d.ts","sourceRoot":"","sources":["../src/known-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAyR5C,CAAC"}
@@ -23,6 +23,7 @@ export const KNOWN_CLI_FLAGS = [
23
23
  'audit-dev',
24
24
  'author',
25
25
  'auto',
26
+ 'backfill',
26
27
  'base',
27
28
  'baseline',
28
29
  'body',
@@ -135,6 +136,7 @@ export const KNOWN_CLI_FLAGS = [
135
136
  'margin',
136
137
  'mark',
137
138
  'max',
139
+ 'max-per-day',
138
140
  'max-wall-clock',
139
141
  'memory',
140
142
  'mock',
@@ -1 +1 @@
1
- {"version":3,"file":"known-flags.js","sourceRoot":"","sources":["../src/known-flags.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"known-flags.js","sourceRoot":"","sources":["../src/known-flags.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/harness-cli",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
4
4
  "description": "The dz CLI — install AI skills for Claude Code, Codex, OpenCode, Hermes, OpenClaude, GitHub Copilot. 67 commands, 14 presets, 10 platform targets.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -41,23 +41,23 @@
41
41
  "sbom.json"
42
42
  ],
43
43
  "dependencies": {
44
- "@dzhechkov/harness-core": "^0.7.5",
45
- "@dzhechkov/scout": "^0.8.7",
44
+ "@dzhechkov/harness-core": "^0.7.8",
46
45
  "@dzhechkov/harness-presets": "^0.5.14",
47
- "@dzhechkov/skills-mcp": "^0.3.6",
46
+ "@dzhechkov/scout": "^0.8.7",
48
47
  "@dzhechkov/skills-devops": "^0.3.13",
48
+ "@dzhechkov/skills-mcp": "^0.3.6",
49
49
  "@dzhechkov/skills-web3": "^0.2.5",
50
50
  "@dzhechkov/skills-qe": "^0.3.10",
51
- "@dzhechkov/skills-news": "^0.1.12",
51
+ "@dzhechkov/skills-academic": "^0.3.3",
52
+ "@dzhechkov/skills-meta": "^0.9.51",
52
53
  "@dzhechkov/skills-ecc": "^0.1.8",
53
- "@dzhechkov/skills-meta": "^0.9.49",
54
54
  "@dzhechkov/skills-pm": "^0.1.1",
55
- "@dzhechkov/skills-academic": "^0.3.3",
56
55
  "@dzhechkov/skills-taste": "^0.1.1",
56
+ "@dzhechkov/skills-idea2prd": "^0.1.11",
57
57
  "@dzhechkov/skills-reverse-engineering": "^0.1.9",
58
58
  "@dzhechkov/skills-presentation-storyteller": "^0.1.10",
59
- "@dzhechkov/skills-website-cloner": "^0.1.1",
60
- "@dzhechkov/skills-idea2prd": "^0.1.11"
59
+ "@dzhechkov/skills-news": "^0.1.12",
60
+ "@dzhechkov/skills-website-cloner": "^0.1.1"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@types/node": "^25.6.0",
package/sbom.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "hashes": [
26
26
  {
27
27
  "alg": "SHA-256",
28
- "content": "bf6ac920e20f4e9978dbb7b1cca48790d97e44f245dc53088e189776b4a7616e"
28
+ "content": "3d621db3f7811b174ee46b19fa462316ef13679786a910ac64c65fb05bfd5ef7"
29
29
  }
30
30
  ]
31
31
  },
@@ -85,7 +85,7 @@
85
85
  "hashes": [
86
86
  {
87
87
  "alg": "SHA-256",
88
- "content": "a8309c4a78c90a1c9db9518a6d07c5fa800c4d39710941a379635a65012e208d"
88
+ "content": "bf5eadb6ea3ed4761fbc8206167c86119467d7dfd28d7e0eee7cd21d30099da6"
89
89
  }
90
90
  ]
91
91
  },
@@ -95,7 +95,7 @@
95
95
  "hashes": [
96
96
  {
97
97
  "alg": "SHA-256",
98
- "content": "8cf050f1bc0b69be1088e58cc5f88f034d2e847fba9ffc87f3cc01121d7d9d74"
98
+ "content": "2cee996fe21ed692135c98b35bf5e56a89f2dc157f681b36c65020fd062b857b"
99
99
  }
100
100
  ]
101
101
  },
@@ -105,7 +105,7 @@
105
105
  "hashes": [
106
106
  {
107
107
  "alg": "SHA-256",
108
- "content": "442b8bbb2ec9f7701ddc2232fc8662956966097d6f46ee1fce49bd06c20db97f"
108
+ "content": "68a41f08452af263f2a378b54e813567b6ba52376f3d0e13567a7eef7dff09e0"
109
109
  }
110
110
  ]
111
111
  },
@@ -125,7 +125,7 @@
125
125
  "hashes": [
126
126
  {
127
127
  "alg": "SHA-256",
128
- "content": "6fc728a98d8a920a226a4ee2d8b045ee46e27246c7d7e8bdf15e6c7758f3efbc"
128
+ "content": "c7856b79fdf6683fe855268191805ed07b1c68f2ff7ac544d46ac3d93e4c94ef"
129
129
  }
130
130
  ]
131
131
  },
@@ -135,7 +135,7 @@
135
135
  "hashes": [
136
136
  {
137
137
  "alg": "SHA-256",
138
- "content": "4bc5e7cb6563fd672fd7e2c38eac4ba55d54de46940c194b3d2cd5ea4519732a"
138
+ "content": "27741d68ac996a060df7161b49e372f68e31b990a406f0792c79c474ff17eeca"
139
139
  }
140
140
  ]
141
141
  },
@@ -145,7 +145,7 @@
145
145
  "hashes": [
146
146
  {
147
147
  "alg": "SHA-256",
148
- "content": "560d103ce98af8095eb7ee86537aa80de7a914fffa693dc23fdf2440a4f76183"
148
+ "content": "bea844c256e8d947464a4690d2224e4f28d61f433d6e50e5fe26bed3b415ae26"
149
149
  }
150
150
  ]
151
151
  },
@@ -285,7 +285,7 @@
285
285
  "hashes": [
286
286
  {
287
287
  "alg": "SHA-256",
288
- "content": "23fa9b92489e2f39d99397a57f99a4c7566d41b75682d1bbde3f113c480acdcd"
288
+ "content": "1e6f9fd92734216f3cc392fba9e2ec7899492a6892e5891197bc582c886a38fc"
289
289
  }
290
290
  ]
291
291
  },
@@ -295,7 +295,7 @@
295
295
  "hashes": [
296
296
  {
297
297
  "alg": "SHA-256",
298
- "content": "f4ed9bddb45629484baf117a3b92eb4097932abda6e5a48227acbc7b5f23f561"
298
+ "content": "fea029550cb557c73eea2d53d94ef09ec99ba353126a5090a658dc219e8ae5df"
299
299
  }
300
300
  ]
301
301
  },
@@ -305,7 +305,7 @@
305
305
  "hashes": [
306
306
  {
307
307
  "alg": "SHA-256",
308
- "content": "41bce9592c8192431f7f023271eaf3f548398e5c15441ea69a59e78633915cd9"
308
+ "content": "1b46a6093d0ff5713c870b5b7566623c98a33bb212c7f1ba0c56f336620961a3"
309
309
  }
310
310
  ]
311
311
  },
@@ -335,7 +335,7 @@
335
335
  "hashes": [
336
336
  {
337
337
  "alg": "SHA-256",
338
- "content": "423120966d33fb4515177a7613f0ace5b392a576098987d0d9ca22aedea96716"
338
+ "content": "b7c47af8811ca86ee8dd5d4d98cab76c4cceddaafbe09676141bacae92b69b9d"
339
339
  }
340
340
  ]
341
341
  },
@@ -355,7 +355,7 @@
355
355
  "hashes": [
356
356
  {
357
357
  "alg": "SHA-256",
358
- "content": "c3ef929a729f53ca612ac67b1571d2e8da3681ac5060a1cd16e453e0bb1d4e00"
358
+ "content": "3ea2dd881198881f94675ce14e465ce007e5d987e25b7786f67d9af13e880e22"
359
359
  }
360
360
  ]
361
361
  },
@@ -365,7 +365,7 @@
365
365
  "hashes": [
366
366
  {
367
367
  "alg": "SHA-256",
368
- "content": "cae511b9b892c43e874ee06b439306290cd2c0a9e6b75cd0cd931d47adaef3f5"
368
+ "content": "d8288240b5420ddca2cabdb7b358c7c18ba59724defda951d0dbc61439b6fc4c"
369
369
  }
370
370
  ]
371
371
  },
@@ -405,7 +405,7 @@
405
405
  "hashes": [
406
406
  {
407
407
  "alg": "SHA-256",
408
- "content": "aed996e8a3741b595eba31ef694ec5b2999dc0a73933a4289325cf6b9944e254"
408
+ "content": "d123f4f88f51a6b6d283a4fe6d2502bb297ad0de4eb1ef6f99f01b86a7da98a0"
409
409
  }
410
410
  ]
411
411
  }
@@ -20,6 +20,7 @@
20
20
  */
21
21
  export const BOOLEAN_CLI_FLAGS: ReadonlySet<string> = new Set([
22
22
  'affected',
23
+ 'backfill',
23
24
  'all',
24
25
  'allow-same-family',
25
26
  'allow-same-family-qe',
package/src/cli.ts CHANGED
@@ -142,6 +142,12 @@ import {
142
142
  writeFeatureAdrState,
143
143
  computeUsage,
144
144
  deriveCostLedger,
145
+ planLedgerBackfill,
146
+ listCostLedgerRuns,
147
+ resolveLedgerRunId,
148
+ AMBIGUOUS,
149
+ stampCheckpointLine,
150
+ LEDGER_FILL_SOURCE,
145
151
  renderCostLedger,
146
152
  verifyCostLedgerReport,
147
153
  writeCostLedgerJsonl,
@@ -452,6 +458,7 @@ import {
452
458
  decideReadBack,
453
459
  recordVerdictLine,
454
460
  buildCadenceReport,
461
+ tgVisibleSha256,
455
462
  CADENCE_WINDOW_DAYS,
456
463
  } from '@dzhechkov/harness-core';
457
464
  import type { RecordKind, RecordDecision } from '@dzhechkov/harness-core';
@@ -498,6 +505,7 @@ Usage:
498
505
  dz release [--filter <name>] [--tag] [--publish] [--json] [--dry-run] [--no-issue] (VERIFIED release: 4 HARD gates in FRONT of dz publish — full package test suites, audit >=high, node --check of every dist/bin file, bin smoke-boot via "node <bin> --help" — any red gate STOPS the release (exit 1) + best-effort gh issue; all green ⇒ re-sign reminder, then prints the ready dz publish command (or chains with --publish); never duplicates publish's own gates)
499
506
  dz parity [--target <name>] [--json] (the honest feature×target map, COMPUTED from the capability model — which harness feature is full / manual / absent on each of the ${TARGET_NAMES.length} targets, and via which form)
500
507
  dz delivery-check --slug <slug> [--context-only] [--findings <f.json>] [--strict] [--author <model>] [--json] (portable Step-10 Delivery Gate: prints the 4-plane review brief + artifact probes; --findings classifies a fed-back review into a fail-closed ready|blocked hand-off and writes features/<slug>/10_delivery_review.md; --strict exits 1 on blocked)
508
+ dz challenge --plan <plan.md> [--author <model>] (the deterministic cartridge behind the challenge-panel adversarial plan-gate (R6): assembles the wide brief — plan + architecture/vision.md + testing.md + map.json + degradations.md — and prints the C1-C8 adversary prompt naming the cross-family reviewer to dispatch. exit 0 brief printed / 1 plan missing or empty)
501
509
  dz skills-verify [--dir <project>] [--expect a,b] [--static] [--strict] [--json] (does .claude/skills/ actually REGISTER? --static = instant layout scan for CI; default reads the authoritative system/init listing from a real session. exit 0 pass / 1 fail / 2 inconclusive — never a false pass)
502
510
  dz compounding [--project <dir>] [--json] (honest learning-loop payoff report: pool write-only ratio, guard repeat-violation trajectory, cold-vs-warm replay readiness, instrumentation health — a gate without enough data says INSUFFICIENT_DATA, never a fake verdict)
503
511
  dz epoch-replay --mock [--n <N>] [--effect <-1..1>] [--tie-rate <0..1>] [--seed <N>] [--slice <name>] [--json] ($0 synthetic run — exercises the verdict math, NOT evidence)
@@ -7229,7 +7237,7 @@ function gatherGuardFacts(op: string, root: string, text: string | undefined, st
7229
7237
  }
7230
7238
  facts['licenceHold'] = holds;
7231
7239
  } catch { /* unreadable tree — the rule reports nothing rather than inventing a violation */ }
7232
- try { facts['drift'] = sweepSkillDrift(root, { scope: 'packages', allowlist: readDriftAllowlist(root) }).drifted.map((d) => d.name); } catch { /* skip */ }
7240
+ try { facts['drift'] = sweepSkillDrift(root, { scope: 'installs', allowlist: readDriftAllowlist(root) }).drifted.map((d) => d.name); } catch { /* skip */ }
7233
7241
  facts['counts'] = gatherReadmeCounts(root);
7234
7242
  // readme-first: from the WORKING-TREE diff (publishes happen pre-commit here), per package: does the
7235
7243
  // change set contain its package.json (the version-bump signal) without its README.md?
@@ -7393,7 +7401,7 @@ function gatherGuardFacts(op: string, root: string, text: string | undefined, st
7393
7401
  if (Array.isArray(stubWaivers)) facts['stubWaivers'] = stubWaivers;
7394
7402
  }
7395
7403
  if (op === 'consolidate') {
7396
- try { facts['drift'] = sweepSkillDrift(root, { scope: 'packages', allowlist: readDriftAllowlist(root) }).drifted.map((d) => d.name); } catch { /* skip */ }
7404
+ try { facts['drift'] = sweepSkillDrift(root, { scope: 'installs', allowlist: readDriftAllowlist(root) }).drifted.map((d) => d.name); } catch { /* skip */ }
7397
7405
  }
7398
7406
  if (op === 'teach' || op === 'consolidate') {
7399
7407
  if (op === 'teach' && text) facts['secretTargets'] = [{ label: 'lesson', text }];
@@ -10396,12 +10404,39 @@ async function cmdTgPost(options: Map<string, string>, flags: Set<string>, cwd:
10396
10404
  if (!json) for (const line of renderSourceProvenance(decision)) write(line);
10397
10405
  }
10398
10406
 
10407
+ // ADR-005 autopublish guards: read the stop-cord and the send journal as FACTS, then let the pure
10408
+ // decideTgSend judge. An UNREADABLE journal stays undefined ⇒ decideTgSend fails closed on G4/G5.
10409
+ const tgDir = join(repoRoot, '.dz', 'tg-post');
10410
+ const halted = existsSync(join(tgDir, 'HALT'));
10411
+ const sha256 = tgVisibleSha256(draft);
10412
+ let sentLog: { sha256: string; ts: string; status?: 'pending' | 'sent' }[] | undefined;
10413
+ const sentLogPath = join(tgDir, 'sent-log.jsonl');
10414
+ if (!existsSync(sentLogPath)) {
10415
+ sentLog = []; // no journal yet is an EMPTY journal, not an unreadable one — a fresh channel sends
10416
+ } else {
10417
+ try {
10418
+ sentLog = [];
10419
+ for (const line of readFileSync(sentLogPath, 'utf-8').split('\n')) {
10420
+ if (line.trim() === '') continue;
10421
+ const r = JSON.parse(line) as { sha256?: unknown; ts?: unknown; status?: unknown };
10422
+ if (typeof r.sha256 === 'string' && typeof r.ts === 'string') {
10423
+ sentLog.push({ sha256: r.sha256, ts: r.ts, ...(r.status === 'pending' || r.status === 'sent' ? { status: r.status } : {}) });
10424
+ }
10425
+ }
10426
+ } catch {
10427
+ sentLog = undefined; // genuinely unreadable ⇒ fail-closed
10428
+ }
10429
+ }
10399
10430
  const decision = decideTgSend({
10400
10431
  issues,
10401
10432
  provenanceOutcome,
10402
10433
  confirmed: flags.has('send') && flags.has('yes'),
10403
10434
  nowUtcIso: new Date().toISOString(),
10404
10435
  nightOverride: flags.has('night'),
10436
+ halted,
10437
+ sha256,
10438
+ sentLog,
10439
+ maxPostsPerDay: (() => { const n = Number(options.get('max-per-day')); return Number.isFinite(n) && n > 0 ? n : 10; })(),
10405
10440
  });
10406
10441
 
10407
10442
  const visible = tgVisibleLength(draft);
@@ -10422,6 +10457,13 @@ async function cmdTgPost(options: Map<string, string>, flags: Set<string>, cwd:
10422
10457
  const channel = (options.get('channel') ?? '').trim();
10423
10458
  if (channel === '') { write('dz tg-post: --channel @name (or a chat id) is required to send'); return 2; }
10424
10459
 
10460
+ // Two-phase journal (Codex A-): write a PENDING row BEFORE the network call. If the process dies
10461
+ // between send and the sent-row, G5 dedup sees this pending row on the next run and refuses to
10462
+ // double-publish. Best-effort — a pending-write failure is warned, not fatal (better to risk one
10463
+ // duplicate than to block a legitimate send on a full disk).
10464
+ try { mkdirSync(tgDir, { recursive: true }); appendFileSync(sentLogPath, JSON.stringify({ sha256, ts: new Date().toISOString(), channel, status: 'pending' }) + '\n'); }
10465
+ catch (e) { write(`dz tg-post: WARNING — could not write the PENDING journal row (${(e as Error).message}); the crash-window dedup guard is degraded for this send`); }
10466
+
10425
10467
  const sent = await tgApi(token, 'sendMessage', {
10426
10468
  chat_id: channel,
10427
10469
  text: draft,
@@ -10434,6 +10476,15 @@ async function cmdTgPost(options: Map<string, string>, flags: Set<string>, cwd:
10434
10476
  if (json) write(JSON.stringify({ ok: false, action: 'send', reason: sent.description ?? 'refused', visible }));
10435
10477
  return 1;
10436
10478
  }
10479
+ // Record the send AFTER Telegram accepted it (never before — a failed send must not eat the daily
10480
+ // limit or block a retry via dedup). Best-effort append; a journal write failure is logged, not
10481
+ // fatal — the post already went out.
10482
+ try {
10483
+ mkdirSync(tgDir, { recursive: true });
10484
+ appendFileSync(sentLogPath, JSON.stringify({ sha256, ts: new Date().toISOString(), channel, messageId: sent.messageId ?? null, status: 'sent' }) + '\n');
10485
+ } catch (e) {
10486
+ write(`dz tg-post: WARNING — sent, but could not record it in ${sentLogPath} (${(e as Error).message}) — the daily limit and dedup may under-count until fixed`);
10487
+ }
10437
10488
  write(`dz tg-post: sent to ${channel}${sent.messageId !== undefined ? ` (message ${sent.messageId})` : ''}`);
10438
10489
  if (json) write(JSON.stringify({ ok: true, action: 'send', channel, messageId: sent.messageId ?? null, visible }));
10439
10490
  return 0;
@@ -10502,8 +10553,106 @@ async function cmdRecap(options: Map<string, string>, flags: Set<string>, cwd: s
10502
10553
  return 0;
10503
10554
  }
10504
10555
 
10556
+ /**
10557
+ * `dz feature-adr-record --backfill` — fill the run-cost ledger from the host workflow records.
10558
+ *
10559
+ * MEASURED 2026-08-25: of 87 ledger rows, all 20 written automatically carried
10560
+ * `tokens:null, minutes:null, agents:null`, so cost-per-feature was answerable only for the 66 rows
10561
+ * a human retyped. The numbers exist in the host record; the sandboxed workflow simply cannot reach
10562
+ * them. This is that join, run afterwards, on the dz side.
10563
+ */
10564
+ function cmdLedgerBackfill(options: Map<string, string>, flags: Set<string>, cwd: string, write: Write): number {
10565
+ const json = flags.has('json');
10566
+ const apply = flags.has('yes');
10567
+ const ledgerPath = resolve(options.get('project') ?? cwd, '.dz', 'feature-adr', 'run-cost-ledger.jsonl');
10568
+ if (!existsSync(ledgerPath)) {
10569
+ const msg = `dz feature-adr-record --backfill: no ledger at ${ledgerPath}`;
10570
+ write(json ? JSON.stringify({ ok: false, reason: 'no-ledger', path: ledgerPath }) : msg);
10571
+ return 1;
10572
+ }
10573
+ const raw = readFileSync(ledgerPath, 'utf-8');
10574
+ const lines = raw.split('\n').filter((l) => l !== '');
10575
+
10576
+ // One host-record lookup per runId, cached: deriveCostLedger walks the transcript tree.
10577
+ type Facts = { tokens: number | null; minutes: number | null; agents: number | null };
10578
+ const cache = new Map<string, Facts | typeof AMBIGUOUS | null>();
10579
+
10580
+ // Only `tokens` is derived, and the scope is narrow on purpose:
10581
+ // • minutes — CostLedgerReport exposes startedTs but no run duration; there is nothing to divide.
10582
+ // • agents — the ledger column means TOTAL agent invocations including infra agents, while the
10583
+ // union of row.agentIds counts only agents that SPENT. Writing the second into the first would
10584
+ // quietly redefine the column, which that column's own writer explicitly warns against.
10585
+ const factsFor = (runId: string): Facts | null => {
10586
+ try {
10587
+ const report = deriveCostLedger({ runId });
10588
+ if (report === null) return null;
10589
+ const tokens = typeof report.recordTotalTokens === 'number' && Number.isFinite(report.recordTotalTokens)
10590
+ ? report.recordTotalTokens
10591
+ : null;
10592
+ return { tokens, minutes: null, agents: null };
10593
+ } catch { return null; }
10594
+ };
10595
+
10596
+ const facts = (key: 'runId' | 'slug', value: string): Facts | typeof AMBIGUOUS | null => {
10597
+ const ck = key + ':' + value;
10598
+ const hit = cache.get(ck);
10599
+ if (hit !== undefined) return hit;
10600
+ let out: Facts | typeof AMBIGUOUS | null = null;
10601
+ if (key === 'runId') {
10602
+ out = factsFor(value);
10603
+ } else {
10604
+ // The slug is the fallback because the sandboxed workflow cannot know its own run id. It is
10605
+ // only usable when it names exactly ONE host run: deriveCostLedger resolves a slug with
10606
+ // `runs.find(...)`, which takes the FIRST match SILENTLY, so a feature run twice would have
10607
+ // one run's spend written into the other run's row and called measured. Count first, refuse
10608
+ // on more than one.
10609
+ try {
10610
+ const matches = listCostLedgerRuns().filter((r) => r.slug === value);
10611
+ if (matches.length > 1) out = AMBIGUOUS;
10612
+ else if (matches.length === 1 && matches[0] !== undefined) out = factsFor(matches[0].runId);
10613
+ } catch { out = null; }
10614
+ }
10615
+ cache.set(ck, out);
10616
+ return out;
10617
+ };
10618
+
10619
+ const plan = planLedgerBackfill({ lines, facts });
10620
+ const unfilled = plan.rows.filter((r) => r.skipped !== null && r.skipped !== 'already-complete');
10621
+
10622
+ if (apply && plan.filledRows > 0) {
10623
+ // Atomic replace: a torn ledger is worse than an unfilled one.
10624
+ const tmp = ledgerPath + '.backfill-tmp';
10625
+ writeFileSync(tmp, plan.lines.join('\n') + '\n', 'utf-8');
10626
+ renameSync(tmp, ledgerPath);
10627
+ }
10628
+
10629
+ if (json) {
10630
+ write(JSON.stringify({
10631
+ ok: true, applied: apply && plan.filledRows > 0, filledRows: plan.filledRows,
10632
+ totalRows: lines.length, disagreements: plan.disagreements,
10633
+ unfilled: unfilled.map((r) => ({ index: r.index, runId: r.runId, reason: r.skipped })),
10634
+ source: LEDGER_FILL_SOURCE, path: ledgerPath,
10635
+ }));
10636
+ return 0;
10637
+ }
10638
+ write('dz feature-adr-record --backfill: SCOPE — only tokens is derived; minutes and agents stay null (the run record exposes no duration, and the agents column means a different quantity than the spend-bearing agent ids). A row without a runId is matched by SLUG, and only when the slug names exactly one run.');
10639
+ write(`dz feature-adr-record --backfill: ${plan.filledRows} of ${lines.length} row(s) fillable from the host record${apply ? ' — WRITTEN' : ' (dry run; pass --yes to write)'}`);
10640
+ for (const d of plan.disagreements) {
10641
+ write(` DISAGREEMENT row ${d.index} ${d.field}: ledger says ${d.existing}, host record says ${d.derived} — the typed number stands, look at this`);
10642
+ }
10643
+ const byReason = new Map<string, number>();
10644
+ for (const r of unfilled) byReason.set(String(r.skipped), (byReason.get(String(r.skipped)) ?? 0) + 1);
10645
+ for (const [reason, n] of byReason) write(` not filled: ${n} row(s) — ${reason}`);
10646
+ return 0;
10647
+ }
10648
+
10505
10649
  function cmdFeatureAdrRecord(options: Map<string, string>, flags: Set<string>, cwd: string, write: Write): number {
10506
10650
  const json = flags.has('json');
10651
+ // `--backfill` is a different verb on the same store: it fills the ledger's null cost fields from
10652
+ // the host's own workflow record. DRY-RUN BY DEFAULT — this rewrites an append-only log, so the
10653
+ // writing form must be asked for (`--yes`), the same contract `dz publish` and `sync-canonical`
10654
+ // already use. See ledger-backfill.ts for the four rules the plan obeys.
10655
+ if (flags.has('backfill')) return cmdLedgerBackfill(options, flags, cwd, write);
10507
10656
  const kind = (options.get('kind') ?? '').trim() as RecordKind;
10508
10657
  const stage = (options.get('stage') ?? '').trim();
10509
10658
  const slug = (options.get('slug') ?? '').trim();
@@ -10547,6 +10696,11 @@ function cmdFeatureAdrRecord(options: Map<string, string>, flags: Set<string>, c
10547
10696
  });
10548
10697
  if (decision.line === null) return emit(decision);
10549
10698
 
10699
+ // Declared out here because the READ-BACK below must verify what was ACTUALLY written, not what
10700
+ // the decision proposed — the ledger path enriches the line with a resolved runId before the
10701
+ // append, and comparing against the pre-enrichment text made every ledger write report
10702
+ // "not-verified" (caught by running it, not by reading it).
10703
+ let lineToWrite = decision.line;
10550
10704
  // MEASURE, never assume: an unwritable target is a LOUD refusal, because a swallowed mkdir failure
10551
10705
  // is exactly how a write becomes a silent no-op (acid case A4).
10552
10706
  try {
@@ -10568,7 +10722,27 @@ function cmdFeatureAdrRecord(options: Map<string, string>, flags: Set<string>, c
10568
10722
  }
10569
10723
 
10570
10724
  try {
10571
- appendFileSync(target, `${decision.line}\n`, 'utf-8');
10725
+ // WRITE-TIME RUN-ID RESOLUTION. The sandboxed workflow cannot know its own run id — it is not in
10726
+ // `args` and not a sandbox global — so 16 of 20 automatic ledger rows carried no join key at all
10727
+ // and nothing could ever be joined to them (MEASURED 2026-08-25). This command runs on the host,
10728
+ // where the records live, so it answers the question the sandbox cannot. Resolving HERE beats
10729
+ // resolving later: right now the run is in flight and is simply the newest for this slug; an hour
10730
+ // from now the same slug may have several and the choice becomes a guess. Refuses on any tie.
10731
+ lineToWrite = decision.line;
10732
+ if (kind === 'ledger') {
10733
+ try {
10734
+ const parsed: unknown = JSON.parse(decision.line);
10735
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
10736
+ const rowObj = parsed as Record<string, unknown>;
10737
+ const resolved = resolveLedgerRunId(rowObj, listCostLedgerRuns());
10738
+ if (resolved !== null) {
10739
+ // Marked, because a resolved run id is our inference, not something the pipeline knew.
10740
+ lineToWrite = JSON.stringify({ ...rowObj, runId: resolved, runIdSource: 'resolved-at-write' });
10741
+ }
10742
+ }
10743
+ } catch { /* resolution is an ENRICHMENT; a failure must never cost the row itself */ }
10744
+ }
10745
+ appendFileSync(target, `${lineToWrite}\n`, 'utf-8');
10572
10746
  } catch (err) {
10573
10747
  return emit({ verdict: 'refused', exit: 2, reason: `the append failed: ${(err as Error).message}`, blocking: false, line: null });
10574
10748
  }
@@ -10582,7 +10756,7 @@ function cmdFeatureAdrRecord(options: Map<string, string>, flags: Set<string>, c
10582
10756
  } catch {
10583
10757
  lastLine = null;
10584
10758
  }
10585
- return emit(decideReadBack(decision.line, lastLine), { target });
10759
+ return emit(decideReadBack(lineToWrite, lastLine), { target });
10586
10760
  }
10587
10761
 
10588
10762
  function cmdAmendmentCheck(options: Map<string, string>, flags: Set<string>, cwd: string, write: Write): number {
@@ -10739,7 +10913,9 @@ function cmdFeatureAdrCheckpoint(options: Map<string, string>, flags: Set<string
10739
10913
  const stateDir = join(featureDir, '.fa-state');
10740
10914
  try {
10741
10915
  mkdirSync(stateDir, { recursive: true });
10742
- appendFileSync(join(stateDir, 'checkpoints.jsonl'), verdict.line + '\n', 'utf-8');
10916
+ // The CLI is the only participant with a clock — the sandboxed workflow has no `Date` — so the
10917
+ // write instant is stamped here, at the append, and nowhere inside the blob-mirrored serializer.
10918
+ appendFileSync(join(stateDir, 'checkpoints.jsonl'), stampCheckpointLine(verdict.line, new Date().toISOString()) + '\n', 'utf-8');
10743
10919
  } catch (err) {
10744
10920
  const reason = err instanceof Error ? err.message : String(err);
10745
10921
  return emit({ ok: false, stage, reason }, 'dz feature-adr checkpoint: write failed — ' + reason, 1);
@@ -23,6 +23,7 @@ export const KNOWN_CLI_FLAGS: readonly string[] = [
23
23
  'audit-dev',
24
24
  'author',
25
25
  'auto',
26
+ 'backfill',
26
27
  'base',
27
28
  'baseline',
28
29
  'body',
@@ -135,6 +136,7 @@ export const KNOWN_CLI_FLAGS: readonly string[] = [
135
136
  'margin',
136
137
  'mark',
137
138
  'max',
139
+ 'max-per-day',
138
140
  'max-wall-clock',
139
141
  'memory',
140
142
  'mock',