@dzhechkov/harness-cli 0.8.15 → 0.8.16

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.8.15",
3
+ "version": "0.8.16",
4
4
  "description": "The dz CLI — install AI skills for Claude Code, Codex, OpenCode, Hermes, OpenClaude, GitHub Copilot. 87 commands, 14 presets, 10 platform targets.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -42,23 +42,23 @@
42
42
  "src"
43
43
  ],
44
44
  "dependencies": {
45
- "@dzhechkov/harness-core": "^0.8.21",
46
- "@dzhechkov/skills-devops": "^0.3.17",
47
- "@dzhechkov/skills-mcp": "^0.3.10",
45
+ "@dzhechkov/harness-core": "^0.8.24",
48
46
  "@dzhechkov/scout": "^0.8.11",
47
+ "@dzhechkov/skills-mcp": "^0.3.10",
49
48
  "@dzhechkov/harness-presets": "^0.5.18",
50
- "@dzhechkov/skills-web3": "^0.2.9",
49
+ "@dzhechkov/skills-devops": "^0.3.17",
50
+ "@dzhechkov/skills-qe": "^0.3.14",
51
51
  "@dzhechkov/skills-meta": "^0.9.55",
52
52
  "@dzhechkov/skills-academic": "^0.3.7",
53
- "@dzhechkov/skills-qe": "^0.3.14",
53
+ "@dzhechkov/skills-ecc": "^0.1.12",
54
54
  "@dzhechkov/skills-news": "^0.1.16",
55
- "@dzhechkov/skills-pm": "^0.1.5",
56
55
  "@dzhechkov/skills-taste": "^0.1.5",
57
- "@dzhechkov/skills-ecc": "^0.1.12",
58
56
  "@dzhechkov/skills-idea2prd": "^0.1.15",
57
+ "@dzhechkov/skills-pm": "^0.1.5",
58
+ "@dzhechkov/skills-reverse-engineering": "^0.3.4",
59
59
  "@dzhechkov/skills-presentation-storyteller": "^0.1.14",
60
- "@dzhechkov/skills-website-cloner": "^0.1.5",
61
- "@dzhechkov/skills-reverse-engineering": "^0.3.4"
60
+ "@dzhechkov/skills-web3": "^0.2.9",
61
+ "@dzhechkov/skills-website-cloner": "^0.1.5"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@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": "ce474e87118603123db01d0d6a15d922e874aa9eaa33229882d930dc7dde04d7"
28
+ "content": "650d078c061e10082536c72852622b391e76ad35d89ae1ae710ff2209eef4686"
29
29
  }
30
30
  ]
31
31
  },
@@ -125,7 +125,7 @@
125
125
  "hashes": [
126
126
  {
127
127
  "alg": "SHA-256",
128
- "content": "15386e1db8287bd1345528d08ef719be9044d5eac621fce86ea6cb13d2866c45"
128
+ "content": "a8f5e5f83daaff53ce46607c9b3e69fb97f0e84223e819bb9e740ce5517b99f9"
129
129
  }
130
130
  ]
131
131
  },
@@ -135,7 +135,7 @@
135
135
  "hashes": [
136
136
  {
137
137
  "alg": "SHA-256",
138
- "content": "d717bdd37c4e8d04d3364dbe37b7a878eadf8d38a25f6ababec98017208cc506"
138
+ "content": "958649fbb537b1bab400f7860ba540aa2cf62799317bcdacdf8e1e6010f2629e"
139
139
  }
140
140
  ]
141
141
  },
@@ -145,7 +145,7 @@
145
145
  "hashes": [
146
146
  {
147
147
  "alg": "SHA-256",
148
- "content": "649c6d2b02b478362d85882c5b01be755a2df4ccfe2f91474d5a418aae5f8b05"
148
+ "content": "718094c24661e25bfca2ef64c46b62e1a0fb9871969cd9c315fbf173186ba82f"
149
149
  }
150
150
  ]
151
151
  },
@@ -379,7 +379,7 @@
379
379
  },
380
380
  {
381
381
  "name": "dz:canonical-json-sha256-v2",
382
- "value": "18211ce5363b82fbaea0593609b687c3705a60dd559c80a96d198f19c3f82402"
382
+ "value": "1052ef8c24990eb1a2f6eed3db71d84240f6ecc2f7e1db1d50af10fa6c33c2af"
383
383
  }
384
384
  ]
385
385
  },
@@ -409,7 +409,7 @@
409
409
  "hashes": [
410
410
  {
411
411
  "alg": "SHA-256",
412
- "content": "7f6d7dbd6216436ffc19888b167d05b77cf6407758d4805d793f8830da315260"
412
+ "content": "43cd47da3a2ffdd54b48989c1b30430473d4d20a903c44c6f640284ffa90fb6c"
413
413
  }
414
414
  ]
415
415
  },
package/src/cli.ts CHANGED
@@ -730,7 +730,7 @@ Usage:
730
730
  dz brain init [--project <dir>] [--k <N>] (wire the grounding hook into .claude/settings.json — opt-in)
731
731
  dz statusline [--json] [--install] [--project <dir>] (live self-learning panel for Claude Code's status bar; reads the CC JSON payload from STDIN)
732
732
  dz store-guard [--status|--reset] [--yes] [--project <dir>] (show the monotonic external high-water mark; --reset is the only lowering path and requires confirmation or --yes)
733
- dz statusline --fa-record --slug <s> --step "<label>" [--kind <feature-adr|loop>] [--tier <S|M|L|XL>] [--recalled <n>] [--stored <n>] [--mode <m>] (feature-adr: record live per-run learning state + phase → 📐 SECOND-LINE phase panel; a plain "Step <n>" label that goes BACKWARDS against a slot younger than 90 min is absorbed as a stale duplicate — prefix the label with ⛔ or ⏸ to record a legitimate regression)
733
+ dz statusline --fa-record --slug <s> --step "<label>" [--kind <feature-adr|loop>] [--tier <S|M|L|XL>] [--run-id <id>] [--recalled <n>] [--stored <n>] [--mode <m>] (feature-adr: record live per-run learning state + phase → 📐 SECOND-LINE phase panel; the monotone guard absorbs a backwards plain "Step <n>" only within the same non-empty run id, while an absent/empty id retains legacy fresh-slot behavior — prefix the label with ⛔ or ⏸ to record a legitimate regression)
734
734
  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)
735
735
  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)
736
736
  dz chain [--project <dir>] [--json] (verify EVERY hash-chained journal in ONE command: coverage is DERIVED from the CHAINED_JOURNALS registry, never typed, so a journal cannot be given a chain and checked by nobody. An ABSENT journal is NAMED absent, never omitted — omission and cleanliness are indistinguishable in a report. Statuses: ok | healed (defects the current unbroken run has outlived — verdicts over present records are sound) | unchained (present, no chained record yet — legal) | absent | broken | unreadable. Exit 1 on broken/unreadable: a verifier that reports damage and exits 0 is one no automation can act on)
@@ -2730,12 +2730,14 @@ function cmdStatuslineFaRecord(options: Map<string, string>, cwd: string, write:
2730
2730
  }
2731
2731
 
2732
2732
  const mode = options.get('mode');
2733
+ const runId = options.get('run-id')?.trim();
2733
2734
  const projectRoot = resolve(cwd, options.get('project') ?? '.');
2734
2735
  const outcome = writeFeatureAdrStateDetailed(projectRoot, {
2735
2736
  kind: kindRaw, slug, step, recalled, stored,
2736
2737
  ...(reinforced > 0 ? { reinforced } : {}),
2737
2738
  ...(mode !== undefined && mode.trim() !== '' ? { mode: mode.trim() } : {}),
2738
2739
  ...(tier !== undefined ? { tier } : {}),
2740
+ ...(runId !== undefined && runId !== '' ? { runId } : {}),
2739
2741
  });
2740
2742
  const state = outcome.state;
2741
2743
 
@@ -2955,23 +2957,32 @@ function cmdStatusline(
2955
2957
  return 0;
2956
2958
  }
2957
2959
 
2960
+ // ТЕКСТ ПАНЕЛИ — ПО-АНГЛИЙСКИ по просьбе владельца 2026-09-09: строка статуса узкая,
2961
+ // английские слова в ней короче русских при той же ясности. Комментарии остаются русскими.
2958
2962
  const breakdown = data.patternBreakdown;
2959
2963
  let line = breakdown === undefined
2960
2964
  ? `🎓 dz: ${data.patterns} patterns`
2961
- : `🎓 dz: ${data.patterns} (${breakdown.active} актив${breakdown.quarantined > 0
2962
- ? ` · ${breakdown.quarantined} карантин${breakdown.attention ? ' ⚠' : ''}`
2963
- : ''})${breakdown.tierDelta !== undefined ? ` ⚠ тиры Δ${breakdown.tierDelta}` : ''}`;
2965
+ : `🎓 dz: ${data.patterns} (${breakdown.active} active${breakdown.quarantined > 0
2966
+ ? ` · ${breakdown.quarantined} quarantined${breakdown.attention ? ' ⚠' : ''}`
2967
+ : ''})${breakdown.tierDelta !== undefined ? ` ⚠ tiers Δ${breakdown.tierDelta}` : ''}`;
2968
+ // Показатель зеркала печатается и здесь: `dz statusline` — та же панель, и показатель,
2969
+ // живущий только во вспомогательном скрипте, для этой поверхности просто не существовал.
2970
+ if (data.patternMirror?.state === 'unavailable') line += ' (mirror unreadable ⚠)';
2971
+ else if (data.patternMirror?.state === 'different') line += ` (mirror ${data.patternMirror.vector} ⚠)`;
2964
2972
  if (data.storeHealth?.verdict === 'collapsed') {
2965
- line += ` ⛔ ОБВАЛ: было ${data.storeHealth.previousMax ?? '?'} · dz store-guard --reset`;
2973
+ line += ` ⛔ COLLAPSE: was ${data.storeHealth.previousMax ?? '?'} · dz store-guard --reset`;
2966
2974
  } else if (data.storeHealth?.verdict === 'cold-start-over-existing') {
2967
- line += ` ⛔ СТОР ПУСТ: было ${data.storeHealth.previousMax ?? '?'} · восстановить из снимков ${data.storeHealth.snapshotPath ?? ''}`.trimEnd();
2975
+ line += ` ⛔ STORE EMPTY: was ${data.storeHealth.previousMax ?? '?'} · restore from snapshots ${data.storeHealth.snapshotPath ?? ''}`.trimEnd();
2968
2976
  } else if (data.storeHealth?.verdict === 'unreadable') {
2969
- line += ` ⛔ СТОР НЕЧИТАЕМ${data.storeHealth.unreadableFiles !== undefined && data.storeHealth.unreadableFiles.length > 0
2977
+ line += ` ⛔ STORE UNREADABLE${data.storeHealth.unreadableFiles !== undefined && data.storeHealth.unreadableFiles.length > 0
2970
2978
  ? `: ${data.storeHealth.unreadableFiles.join(', ')}` : ''}`;
2971
2979
  } else if (data.storeHealth?.verdict === 'source-changed') {
2972
- line += ' ⚠ смена источника хранения';
2980
+ line += ' ⚠ store source changed';
2973
2981
  }
2974
- line += `${data.usedPatterns !== undefined ? ` · ${data.usedPatterns} used` : ''} · 🧠 ${data.brainSources} sources`;
2982
+ // Рядом с числом источников объём каждого через «/» (просьба владельца 2026-09-09):
2983
+ // четыре источника по 300 единиц и четыре по три — разные корпуса, а число одно и то же.
2984
+ const ku = data.brainKuCounts.length > 0 ? ` (${data.brainKuCounts.join('/')})` : '';
2985
+ line += `${data.usedPatterns !== undefined ? ` · ${data.usedPatterns} used` : ''} · 🧠 ${data.brainSources} sources${ku}`;
2975
2986
  const branch = statuslineGitBranch(projectRoot);
2976
2987
  if (branch !== undefined) line += ` · ⎇ ${branch}`;
2977
2988
  if (data.consolidatedAgeH !== undefined) line += ` · ⟳ ${data.consolidatedAgeH}h`;
@@ -11548,13 +11559,33 @@ function cmdMutationGate(
11548
11559
  }
11549
11560
 
11550
11561
  let entries: readonly MutationRegistryEntry[] = parsed.registry.entries;
11562
+ let entryResults: readonly MutationEntryResult[] = parsed.entryResults;
11551
11563
  const only = options.get('only');
11552
11564
  if (only !== undefined) {
11553
11565
  const ids = only.split(',').map((s) => s.trim()).filter(Boolean);
11554
- const known = new Set(entries.map((e) => e.id));
11566
+ const known = new Set([
11567
+ ...entries.map((entry) => entry.id),
11568
+ ...entryResults.map((result) => result.id),
11569
+ ]);
11555
11570
  const unknown = ids.filter((id) => !known.has(id));
11556
11571
  if (unknown.length > 0) return fail(`--only names unknown entry id(s): ${unknown.join(', ')}`);
11557
11572
  entries = entries.filter((e) => ids.includes(e.id));
11573
+ entryResults = entryResults.filter((result) => ids.includes(result.id));
11574
+ }
11575
+
11576
+ if (entries.length === 0) {
11577
+ const scope = only === undefined ? 'registry' : 'selected registry entries';
11578
+ const error = `${scope} has no runnable entries after validation — nothing can be run; the registry is unusable`;
11579
+ const summary = summarizeMutationResults(entryResults);
11580
+ if (json) {
11581
+ write(JSON.stringify({ error, registryPath, results: entryResults, summary, exitCode: 2 }, null, 2));
11582
+ } else {
11583
+ write(`dz mutation-gate: ${error}`);
11584
+ for (const result of entryResults) {
11585
+ write(` - ${result.id}: ${result.verdict} — ${result.detail}`);
11586
+ }
11587
+ }
11588
+ return 2;
11558
11589
  }
11559
11590
 
11560
11591
  const testCmdRaw = options.get('test-cmd') ?? parsed.registry.testCommand ?? 'npm test';
@@ -11590,7 +11621,7 @@ function cmdMutationGate(
11590
11621
  let gitTop: string | null = null;
11591
11622
  try { gitTop = execSync('git rev-parse --show-toplevel', { cwd: pkgDir, stdio: 'pipe', encoding: 'utf-8' }).trim() || null; } catch { /* not in a git repo */ }
11592
11623
  let copyDir = join(scratchParent, 'pkg');
11593
- const results: MutationEntryResult[] = [];
11624
+ const results: MutationEntryResult[] = [...entryResults];
11594
11625
  const observations: MutationObservation[] = [];
11595
11626
  const warnings: string[] = [];
11596
11627
  const internalRetries: {
@@ -11723,8 +11754,8 @@ function cmdMutationGate(
11723
11754
  : undefined,
11724
11755
  );
11725
11756
  if (!baseline.ok) {
11726
- if (json) { write(JSON.stringify({ packageDir: pkgDir, registryPath, testCommand: testCmd, baseline, results: [], internalRetries, exitCode: 1 }, null, 2)); return 1; }
11727
- write(renderMutationReport([], baseline, pkgDir));
11757
+ if (json) { write(JSON.stringify({ packageDir: pkgDir, registryPath, testCommand: testCmd, baseline, results, internalRetries, exitCode: 1 }, null, 2)); return 1; }
11758
+ write(renderMutationReport(results, baseline, pkgDir));
11728
11759
  return 1;
11729
11760
  }
11730
11761