@dzhechkov/harness-cli 0.3.244 → 0.3.246

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.244",
3
+ "version": "0.3.246",
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",
@@ -57,7 +57,7 @@
57
57
  "@dzhechkov/skills-reverse-engineering": "^0.1.0",
58
58
  "@dzhechkov/skills-presentation-storyteller": "^0.1.0",
59
59
  "@dzhechkov/skills-website-cloner": "^0.1.0",
60
- "@dzhechkov/harness-core": "0.3.135"
60
+ "@dzhechkov/harness-core": "0.3.137"
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": "2471dcbdf8588a65410c17557f5ef331c4f8cc77923824728f64ebe7e33d84dc"
28
+ "content": "129ee8a3fc96a1edda2258d02cd6dc4b8df2ab766f3b03ddb38f1559f0c0d9b9"
29
29
  }
30
30
  ]
31
31
  },
@@ -105,7 +105,7 @@
105
105
  "hashes": [
106
106
  {
107
107
  "alg": "SHA-256",
108
- "content": "2bb00d2f42334250ee57b4d0f88d92968cbe3f010ec8d75bb748c0ee6f8de0b8"
108
+ "content": "894d5779615292e57a6b5c204ebd04cef4b065e3fe4d8546c0f3dfbe0fb22529"
109
109
  }
110
110
  ]
111
111
  },
@@ -115,7 +115,7 @@
115
115
  "hashes": [
116
116
  {
117
117
  "alg": "SHA-256",
118
- "content": "d959d7623b68286e440e04f90ee3ae7af0166c1fe506f2cf7e6e9e317439409d"
118
+ "content": "aaaf1d89fb27f39c125c3404b37d57f9251fe62d7993f79df5696944ae8bddcf"
119
119
  }
120
120
  ]
121
121
  },
@@ -125,7 +125,7 @@
125
125
  "hashes": [
126
126
  {
127
127
  "alg": "SHA-256",
128
- "content": "68e0bbf621169f7bae350a5b723f9425969ab12b6f7dd98ce26bb06d32c77c92"
128
+ "content": "dfdfb4feeb07bf037194a1aa7da4f956e88da30ec8c1848fa2e989d82ed34a0b"
129
129
  }
130
130
  ]
131
131
  },
@@ -185,7 +185,7 @@
185
185
  "hashes": [
186
186
  {
187
187
  "alg": "SHA-256",
188
- "content": "ff01608759bb01a9bb83aa45cc4658182765d9fb4b2512f3a096b8ea55370eac"
188
+ "content": "139d06a7617876ef1f9a1c7408f993314f1c3415a7c95a4dc53d89dcf453d866"
189
189
  }
190
190
  ]
191
191
  },
@@ -205,7 +205,7 @@
205
205
  "hashes": [
206
206
  {
207
207
  "alg": "SHA-256",
208
- "content": "14a3db7155fcc858272439a55bc7a43a09c7f6fd7caa302e5a13c153fe1a6d16"
208
+ "content": "967efe0f790775d915f31665e270490794a8ca4bdbecd0844562edda2edf42d9"
209
209
  }
210
210
  ]
211
211
  },
package/src/cli.ts CHANGED
@@ -199,6 +199,10 @@ import {
199
199
  classifyContentProbe,
200
200
  renderContentProbe,
201
201
  findNonRegistrableSkillDirs,
202
+ assembleCompoundingReport,
203
+ renderCompoundingReport,
204
+ readReinforcementState,
205
+ readQuarantineState,
202
206
  registrationExitCode,
203
207
  renderRegistrationReport,
204
208
  } from '@dzhechkov/harness-core';
@@ -232,6 +236,7 @@ Usage:
232
236
  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)
233
237
  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)
234
238
  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)
239
+ 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)
235
240
  dz setup --target <name> [--preset <name>] [--select id,id,...] [--skills-dir <dir>] [--project <dir>] [--memory agentdb] [--no-memory] [--no-hooks] [--install-driver] [--force] [--enrich]
236
241
  dz teach "<pattern>" [--reward <0-1>] [--domain <name>] [--type rule|success-pattern|lesson-learned] [--project <dir>] [--no-mirror] (--project pins the learned store to <dir>/.dz, not the cwd — pin to a canonical brain)
237
242
  dz teach --from-json <file> [--project <dir>] [--no-mirror] (bulk-import a 'dz recall --all --json' export — share a learned store across machines)
@@ -5620,6 +5625,97 @@ function nameFor(t: { file: string; name?: string }, outcome: 'pass' | 'fail' |
5620
5625
  * --author <model> cosmetic: the reviewer to dispatch, printed alongside the brief
5621
5626
  * --json machine contract { planesChecked, planesSkipped, findings, handoff, artifact }
5622
5627
  */
5628
+ /**
5629
+ * `dz compounding` — does the learning loop actually PAY? (feature compounding, scout C2.)
5630
+ * Gathers the facts (store rows, apply-leg usage log, guard audit) and hands them to the PURE
5631
+ * report assembler. Gates without enough data say INSUFFICIENT_DATA — never a fake verdict.
5632
+ */
5633
+ function cmdCompounding(options: Map<string, string>, flags: Set<string>, cwd: string, write: Write): number {
5634
+ const json = flags.has('json');
5635
+ if (flags.has('help')) {
5636
+ write('dz compounding [--project <dir>] [--json] — honest learning-loop payoff report');
5637
+ write(' pool payoff (write-only ratio) · guard repeat-violation trajectory · cold-vs-warm replay readiness · instrumentation health');
5638
+ return 0;
5639
+ }
5640
+ for (const flag of flags) {
5641
+ if (!new Set(['json', 'help']).has(flag)) {
5642
+ write(json ? JSON.stringify({ error: `unknown option --${flag}`, exitCode: 1 }) : `dz compounding: unknown option --${flag}\n allowed: --project <dir>, --json`);
5643
+ return 1;
5644
+ }
5645
+ }
5646
+ for (const key of options.keys()) {
5647
+ if (key.startsWith('_positional_')) {
5648
+ write(json ? JSON.stringify({ error: `unexpected argument "${options.get(key)}"`, exitCode: 1 }) : `dz compounding: unexpected argument "${options.get(key)}"\n allowed: --project <dir>, --json`);
5649
+ return 1;
5650
+ }
5651
+ if (key !== 'project') {
5652
+ write(json ? JSON.stringify({ error: `unknown option --${key}`, exitCode: 1 }) : `dz compounding: unknown option --${key}\n allowed: --project <dir>, --json`);
5653
+ return 1;
5654
+ }
5655
+ }
5656
+ const root = resolve(cwd, options.get('project') ?? '.');
5657
+
5658
+ // lessons — the store, with reinforcement + quarantine metadata
5659
+ const lessons = loadStoreRecords(root).map((r) => ({
5660
+ dzId: r.id,
5661
+ uses: readReinforcementState(r).uses,
5662
+ quarantined: readQuarantineState(r).quarantined,
5663
+ reward: typeof r.score === 'number' ? r.score : null,
5664
+ }));
5665
+
5666
+ // apply-leg usage events (read records only; aggregate rows carry no query by construction)
5667
+ const usage: { dzId: string; ts: string; query?: string; runId?: string }[] = [];
5668
+ try {
5669
+ const text = readFileSync(join(root, '.dz', 'recall-usage.jsonl'), 'utf-8');
5670
+ for (const line of text.split('\n')) {
5671
+ if (line.trim() === '') continue;
5672
+ try {
5673
+ const o = JSON.parse(line) as Record<string, unknown>;
5674
+ if (typeof o.dzId === 'string' && typeof o.ts === 'string' && o.kind !== 'aggregate') {
5675
+ usage.push({
5676
+ dzId: o.dzId,
5677
+ ts: o.ts,
5678
+ ...(typeof o.query === 'string' ? { query: o.query } : {}),
5679
+ ...(typeof o.runId === 'string' ? { runId: o.runId } : {}),
5680
+ });
5681
+ }
5682
+ } catch {
5683
+ /* one bad line must not kill the report */
5684
+ }
5685
+ }
5686
+ } catch {
5687
+ /* no log yet — the report says so */
5688
+ }
5689
+
5690
+ // guard audit events
5691
+ const guard: { ts: string; verdict: string; rules: string[] }[] = [];
5692
+ try {
5693
+ const text = readFileSync(join(root, '.dz', 'guard-audit.jsonl'), 'utf-8');
5694
+ for (const line of text.split('\n')) {
5695
+ if (line.trim() === '') continue;
5696
+ try {
5697
+ const o = JSON.parse(line) as { ts?: unknown; verdict?: unknown; violations?: { rule?: unknown }[] };
5698
+ if (typeof o.ts === 'string' && typeof o.verdict === 'string') {
5699
+ guard.push({
5700
+ ts: o.ts,
5701
+ verdict: o.verdict,
5702
+ rules: Array.isArray(o.violations) ? o.violations.map((v) => (typeof v?.rule === 'string' ? v.rule : '')).filter(Boolean) : [],
5703
+ });
5704
+ }
5705
+ } catch {
5706
+ /* skip */
5707
+ }
5708
+ }
5709
+ } catch {
5710
+ /* no audit yet */
5711
+ }
5712
+
5713
+ const report = assembleCompoundingReport({ lessons, usage, guard, nowTs: new Date().toISOString() });
5714
+ if (json) write(JSON.stringify({ ...report, exitCode: 0 }, null, 2));
5715
+ else write(renderCompoundingReport(report));
5716
+ return 0;
5717
+ }
5718
+
5623
5719
  /**
5624
5720
  * Env vars an INHERITED Claude session leaks into a child. Left in place, the probe can silently
5625
5721
  * read the parent's project instead of the target — the exact confound that made a hand-rolled
@@ -6397,6 +6493,8 @@ export async function runCli(argv: string[], io: CliIo = {}): Promise<number> {
6397
6493
  return cmdDeliveryCheck(options, flags, cwd, write);
6398
6494
  case 'skills-verify':
6399
6495
  return cmdSkillsVerify(options, flags, cwd, write);
6496
+ case 'compounding':
6497
+ return cmdCompounding(options, flags, cwd, write);
6400
6498
  case 'routing':
6401
6499
  return cmdRouting(options, flags, cwd, write);
6402
6500
  case 'bto-optimize':