@dzhechkov/harness-cli 0.3.257 → 0.3.258

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/harness-cli",
3
- "version": "0.3.257",
3
+ "version": "0.3.258",
4
4
  "description": "The dz CLI — install AI skills for Claude Code, Codex, OpenCode, Hermes, OpenClaude, GitHub Copilot. 35 commands, 13 presets, 6 platform targets.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "sbom.json"
42
42
  ],
43
43
  "dependencies": {
44
- "@dzhechkov/harness-core": "^0.3.146",
44
+ "@dzhechkov/harness-core": "^0.3.147",
45
45
  "@dzhechkov/harness-presets": "^0.5.0",
46
46
  "@dzhechkov/scout": "^0.8.0",
47
47
  "@dzhechkov/skills-devops": "^0.3.0",
package/sbom.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "hashes": [
26
26
  {
27
27
  "alg": "SHA-256",
28
- "content": "7333dd44bcbeb6536e8ee0f0490a57fefca211e706535da7f44cea7012388213"
28
+ "content": "a38e5ef6a741aec138af0de7bd3616d4356d613ba1616bd8b5417194c1ee5f03"
29
29
  }
30
30
  ]
31
31
  },
@@ -105,7 +105,7 @@
105
105
  "hashes": [
106
106
  {
107
107
  "alg": "SHA-256",
108
- "content": "818293a250cdf1bd10b5d69267b714d9a8ab90017c1fa18de29fc24e28ad8a55"
108
+ "content": "f954d1e2e3d9f5941481a2b2ccbf553bab892dfa9ba1e7aefb4bf7d1800e9203"
109
109
  }
110
110
  ]
111
111
  },
@@ -115,7 +115,7 @@
115
115
  "hashes": [
116
116
  {
117
117
  "alg": "SHA-256",
118
- "content": "9c37499ed55b571232b5718c863b83b31f7a79faab46a9dcbe3283b993b1862a"
118
+ "content": "5fb105be335591fb20401a3b23bac9829777e7ba96c2a2480c29970f4ffa2774"
119
119
  }
120
120
  ]
121
121
  },
@@ -125,7 +125,7 @@
125
125
  "hashes": [
126
126
  {
127
127
  "alg": "SHA-256",
128
- "content": "6cf537925ccb4b1ffff84c8fd255b487438b78b56a46f9d91d33b25500ae520d"
128
+ "content": "a4be3aac6dadec03c1fc85fc5354d9a286ac0a21b4983349c4e511cae49dec79"
129
129
  }
130
130
  ]
131
131
  },
@@ -185,7 +185,7 @@
185
185
  "hashes": [
186
186
  {
187
187
  "alg": "SHA-256",
188
- "content": "7abb07cdda09bea2b8e948cecdbaed4579371e8d0e8cee4436e7fcb20f430cdd"
188
+ "content": "b502ba368d29e25413ce35e8853bc5650c06f686202e51f997f67db0fac03224"
189
189
  }
190
190
  ]
191
191
  },
@@ -205,7 +205,7 @@
205
205
  "hashes": [
206
206
  {
207
207
  "alg": "SHA-256",
208
- "content": "d64af623372238bb5f2ead34e733130d7b013c49058a26f4795f09586b2b5dda"
208
+ "content": "a369561502f08d9dd4993a294adcb3a38349f543959fa8de31cd1580778062b0"
209
209
  }
210
210
  ]
211
211
  },
package/src/cli.ts CHANGED
@@ -80,6 +80,11 @@ import {
80
80
  statuslineData,
81
81
  writeFeatureAdrState,
82
82
  computeUsage,
83
+ deriveCostLedger,
84
+ renderCostLedger,
85
+ verifyCostLedgerReport,
86
+ writeCostLedgerJsonl,
87
+ COST_LEDGER_SCOPE,
83
88
  deriveUsageCalibration,
84
89
  normalizeClaudeUsageModelKey,
85
90
  readUsageLimits,
@@ -340,6 +345,7 @@ Usage:
340
345
  dz statusline [--json] [--install] [--project <dir>] (live self-learning panel for Claude Code's status bar; reads the CC JSON payload from STDIN)
341
346
  dz statusline --fa-record --slug <s> --step "<label>" [--recalled <n>] [--stored <n>] [--mode <m>] (feature-adr: record live per-run learning state → 📐 panel segment)
342
347
  dz usage [--json] [--project <dir>] | dz usage --calibrate --session <pct> --weekly <pct> [--model fable=<pct>] [--project <dir>] (ESTIMATE Claude usage from fixed reset windows; optional per-model weekly binding; exit 0 ALWAYS; pct=null when limits unconfigured)
348
+ dz usage --by-stage [--run <runId> | --slug <slug>] [--epsilon <0..1>] [--write <file.jsonl>] [--json] (per-stage cost ledger for ONE feature-adr run + the reconciliation invariant: accounted + unaccounted = run total; verdict BALANCED | DEFECT | INSUFFICIENT_DATA; local transcript ESTIMATES — catches ATTRIBUTION errors, not pricing errors)
343
349
  dz claim-check [paths...] [--json] [--fail-on high|medium|none] [--project <dir>] (enforce the Integrity Rule: flag untagged/overstated accuracy claims; default scan = root README.md + every discovered package's README.md + features/*/08_qe_report.md + docs/**/*.md (historical feature artifacts are NOT scanned — pass paths explicitly); exit 1 only at/above --fail-on, default high)
344
350
  dz pretrain [--project <dir>]
345
351
  dz recommend "<task description>"
@@ -1509,6 +1515,64 @@ function cmdUsageCalibrate(
1509
1515
  }
1510
1516
  }
1511
1517
 
1518
+ /**
1519
+ * `dz usage --by-stage` — the per-stage cost ledger for one feature-adr run (feature `cost-ledger`).
1520
+ *
1521
+ * A run reports ONE number; this turns it into an itemized receipt keyed by the workflow's OWN
1522
+ * `stageLabel()` strings, plus the reconciliation line that guards the bookkeeping itself. Derived
1523
+ * post-hoc from the transcripts already on disk — no workflow edit, killed runs included.
1524
+ *
1525
+ * Exit code is 0 ALWAYS, matching the rest of `dz usage`; the VERDICT (`BALANCED` / `DEFECT` /
1526
+ * `INSUFFICIENT_DATA`) is the signal, and `INSUFFICIENT_DATA` is not success.
1527
+ */
1528
+ function cmdUsageByStage(
1529
+ options: Map<string, string>,
1530
+ flags: Set<string>,
1531
+ write: Write,
1532
+ ): number {
1533
+ const runId = options.get('run');
1534
+ const slug = options.get('slug');
1535
+ const epsilonRaw = options.get('epsilon');
1536
+ const epsilon = epsilonRaw === undefined ? undefined : Number(epsilonRaw);
1537
+ const report = deriveCostLedger({
1538
+ ...(runId !== undefined ? { runId } : {}),
1539
+ ...(slug !== undefined ? { slug } : {}),
1540
+ ...(epsilon !== undefined && Number.isFinite(epsilon) ? { epsilon } : {}),
1541
+ });
1542
+
1543
+ if (report === null) {
1544
+ // An ABSENT run is never a balanced empty report (ADR-003).
1545
+ const detail = runId !== undefined ? `run ${runId}` : slug !== undefined ? `slug ${slug}` : 'any workflow run';
1546
+ if (flags.has('json')) {
1547
+ write(JSON.stringify({ verdict: 'INSUFFICIENT_DATA', reason: `no workflow run record found for ${detail}`, rows: [], estimated: true, scope: COST_LEDGER_SCOPE }));
1548
+ } else {
1549
+ write(`usage --by-stage: INSUFFICIENT_DATA — no workflow run record found for ${detail}`);
1550
+ write(`usage --by-stage: scope: ${COST_LEDGER_SCOPE}`);
1551
+ }
1552
+ return 0;
1553
+ }
1554
+
1555
+ // The verifier re-derives the identities from the EMITTED report — a builder bug must surface as
1556
+ // a finding, not as a plausible table.
1557
+ const verifyDefects = verifyCostLedgerReport(report);
1558
+
1559
+ const outPath = options.get('write');
1560
+ let wrote: boolean | null = null;
1561
+ if (outPath !== undefined && outPath.length > 0) wrote = writeCostLedgerJsonl(resolve(outPath), report);
1562
+
1563
+ if (flags.has('json')) {
1564
+ write(JSON.stringify({ ...report, verifyDefects, ...(wrote === null ? {} : { wrote, writePath: resolve(outPath ?? '') }) }));
1565
+ return 0;
1566
+ }
1567
+
1568
+ write(renderCostLedger(report));
1569
+ for (const d of verifyDefects) write(` verifier: ${d.kind}: ${d.detail}`);
1570
+ if (wrote !== null) {
1571
+ write(` ${wrote ? 'wrote' : 'FAILED to write'} ${resolve(outPath ?? '')} (derived report — regenerable, never read back)`);
1572
+ }
1573
+ return 0;
1574
+ }
1575
+
1512
1576
  /**
1513
1577
  * `dz usage` — print an ESTIMATE of Claude session + weekly usage from fixed reset windows,
1514
1578
  * aggregated READONLY from the local transcript store (see {@link computeUsage}). `--json` emits
@@ -1540,6 +1604,7 @@ function cmdUsage(
1540
1604
  });
1541
1605
  try {
1542
1606
  if (flags.has('calibrate')) return cmdUsageCalibrate(options, optionLists, cwd, write);
1607
+ if (flags.has('by-stage')) return cmdUsageByStage(options, flags, write);
1543
1608
 
1544
1609
  const u = computeUsage(projectRoot);
1545
1610
  const lim = readUsageLimits(projectRoot);