@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/.dz-manifest.json +7 -7
- package/README.md +50 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +46 -13
- package/dist/cli.js.map +1 -1
- package/package.json +10 -10
- package/sbom.json +6 -6
- package/src/cli.ts +44 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dzhechkov/harness-cli",
|
|
3
|
-
"version": "0.8.
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
61
|
-
"@dzhechkov/skills-
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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>"
|
|
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}
|
|
2962
|
-
? ` · ${breakdown.quarantined}
|
|
2963
|
-
: ''})${breakdown.tierDelta !== undefined ? ` ⚠
|
|
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 += ` ⛔
|
|
2973
|
+
line += ` ⛔ COLLAPSE: was ${data.storeHealth.previousMax ?? '?'} · dz store-guard --reset`;
|
|
2966
2974
|
} else if (data.storeHealth?.verdict === 'cold-start-over-existing') {
|
|
2967
|
-
line += ` ⛔
|
|
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 += ` ⛔
|
|
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
|
-
|
|
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(
|
|
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
|
|
11727
|
-
write(renderMutationReport(
|
|
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
|
|