@dzhechkov/harness-cli 0.3.247 → 0.3.249
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 +2 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +91 -1
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
- package/sbom.json +6 -6
- package/src/cli.ts +86 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dzhechkov/harness-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.249",
|
|
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,6 +41,7 @@
|
|
|
41
41
|
"sbom.json"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
+
"@dzhechkov/harness-core": "^0.3.140",
|
|
44
45
|
"@dzhechkov/harness-presets": "^0.5.0",
|
|
45
46
|
"@dzhechkov/scout": "^0.8.0",
|
|
46
47
|
"@dzhechkov/skills-devops": "^0.3.0",
|
|
@@ -56,8 +57,7 @@
|
|
|
56
57
|
"@dzhechkov/skills-idea2prd": "^0.1.0",
|
|
57
58
|
"@dzhechkov/skills-reverse-engineering": "^0.1.0",
|
|
58
59
|
"@dzhechkov/skills-presentation-storyteller": "^0.1.0",
|
|
59
|
-
"@dzhechkov/skills-website-cloner": "^0.1.0"
|
|
60
|
-
"@dzhechkov/harness-core": "0.3.138"
|
|
60
|
+
"@dzhechkov/skills-website-cloner": "^0.1.0"
|
|
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": "
|
|
28
|
+
"content": "0a4369c88d48323b3b2ceb18b89ec3a0b6f6f7016778de3ac583f8397531b1b3"
|
|
29
29
|
}
|
|
30
30
|
]
|
|
31
31
|
},
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"hashes": [
|
|
106
106
|
{
|
|
107
107
|
"alg": "SHA-256",
|
|
108
|
-
"content": "
|
|
108
|
+
"content": "e176f74bf8ff0fe938e1bf9b25db392c1adbbd4b7b5b2b63520cb8baa99df82d"
|
|
109
109
|
}
|
|
110
110
|
]
|
|
111
111
|
},
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
"hashes": [
|
|
116
116
|
{
|
|
117
117
|
"alg": "SHA-256",
|
|
118
|
-
"content": "
|
|
118
|
+
"content": "8bfdc5551ea8d4897f8bb2ab50e374145965e73b4dca8d01325f5388412d804c"
|
|
119
119
|
}
|
|
120
120
|
]
|
|
121
121
|
},
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"hashes": [
|
|
126
126
|
{
|
|
127
127
|
"alg": "SHA-256",
|
|
128
|
-
"content": "
|
|
128
|
+
"content": "0ae60f97c9b1b9e7afabcc8aa540eae700950539f5adc511c6f02cbe634775bd"
|
|
129
129
|
}
|
|
130
130
|
]
|
|
131
131
|
},
|
|
@@ -185,7 +185,7 @@
|
|
|
185
185
|
"hashes": [
|
|
186
186
|
{
|
|
187
187
|
"alg": "SHA-256",
|
|
188
|
-
"content": "
|
|
188
|
+
"content": "207f5a322bb9154eb34478746318abf1f67660f670a92d7bede2fd4a725d4962"
|
|
189
189
|
}
|
|
190
190
|
]
|
|
191
191
|
},
|
|
@@ -205,7 +205,7 @@
|
|
|
205
205
|
"hashes": [
|
|
206
206
|
{
|
|
207
207
|
"alg": "SHA-256",
|
|
208
|
-
"content": "
|
|
208
|
+
"content": "1d3e6fb9e19aa8fd589487335a8004cc6f7a6af43472b40e31f9139a482f7e85"
|
|
209
209
|
}
|
|
210
210
|
]
|
|
211
211
|
},
|
package/src/cli.ts
CHANGED
|
@@ -200,6 +200,8 @@ import {
|
|
|
200
200
|
renderContentProbe,
|
|
201
201
|
findNonRegistrableSkillDirs,
|
|
202
202
|
assembleCompoundingReport,
|
|
203
|
+
scoreRun,
|
|
204
|
+
renderScorecard,
|
|
203
205
|
renderCompoundingReport,
|
|
204
206
|
readReinforcementState,
|
|
205
207
|
readQuarantineState,
|
|
@@ -237,6 +239,7 @@ Usage:
|
|
|
237
239
|
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)
|
|
238
240
|
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
241
|
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)
|
|
242
|
+
dz score --slug <feature> [--project <dir>] [--json] (process scorecard for ONE feature-adr run, from its artifacts: ADR confirmation, discrimination, cross-model QE grade, live verification, README-first, learning loop, amendments — descriptive-only, a low score exits 0)
|
|
240
243
|
dz setup --target <name> [--preset <name>] [--select id,id,...] [--skills-dir <dir>] [--project <dir>] [--memory agentdb] [--no-memory] [--no-hooks] [--install-driver] [--force] [--enrich]
|
|
241
244
|
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)
|
|
242
245
|
dz teach --from-json <file> [--project <dir>] [--no-mirror] (bulk-import a 'dz recall --all --json' export — share a learned store across machines)
|
|
@@ -5625,6 +5628,87 @@ function nameFor(t: { file: string; name?: string }, outcome: 'pass' | 'fail' |
|
|
|
5625
5628
|
* --author <model> cosmetic: the reviewer to dispatch, printed alongside the brief
|
|
5626
5629
|
* --json machine contract { planesChecked, planesSkipped, findings, handoff, artifact }
|
|
5627
5630
|
*/
|
|
5631
|
+
/**
|
|
5632
|
+
* `dz score --slug <feature>` — score a feature-adr RUN's process discipline from its artifacts
|
|
5633
|
+
* (feature dz-score, Reading C). Descriptive-only: exit 0 on any score; non-zero only on usage errors.
|
|
5634
|
+
*/
|
|
5635
|
+
function cmdScore(options: Map<string, string>, flags: Set<string>, cwd: string, write: Write): number {
|
|
5636
|
+
const json = flags.has('json');
|
|
5637
|
+
if (flags.has('help')) {
|
|
5638
|
+
const usage = 'dz score --slug <feature> [--project <dir>] [--json] — process scorecard for one feature-adr run (descriptive-only, never a gate)';
|
|
5639
|
+
if (json) write(JSON.stringify({ help: usage, exitCode: 0 })); // --json stays ONE document even for help
|
|
5640
|
+
else {
|
|
5641
|
+
write(usage);
|
|
5642
|
+
write(' disciplines: ADR confirmation · discrimination · cross-model QE · live verification · README-first · learning loop · amendments');
|
|
5643
|
+
write(' descriptive-only, never a gate: a low score exits 0');
|
|
5644
|
+
}
|
|
5645
|
+
return 0;
|
|
5646
|
+
}
|
|
5647
|
+
for (const flag of flags) {
|
|
5648
|
+
if (!new Set(['json', 'help']).has(flag)) {
|
|
5649
|
+
write(json ? JSON.stringify({ error: `unknown option --${flag}`, exitCode: 1 }) : `dz score: unknown option --${flag}\n allowed: --slug <feature>, --project <dir>, --json`);
|
|
5650
|
+
return 1;
|
|
5651
|
+
}
|
|
5652
|
+
}
|
|
5653
|
+
for (const key of options.keys()) {
|
|
5654
|
+
if (key.startsWith('_positional_') || !new Set(['slug', 'project']).has(key)) {
|
|
5655
|
+
const what = key.startsWith('_positional_') ? `unexpected argument "${options.get(key)}"` : `unknown option --${key}`;
|
|
5656
|
+
write(json ? JSON.stringify({ error: what, exitCode: 1 }) : `dz score: ${what}\n allowed: --slug <feature>, --project <dir>, --json`);
|
|
5657
|
+
return 1;
|
|
5658
|
+
}
|
|
5659
|
+
}
|
|
5660
|
+
const slug = options.get('slug') ?? '';
|
|
5661
|
+
// The delivery-check traversal lesson, upgraded to a WHITELIST: `.` slipped the blacklist and
|
|
5662
|
+
// silently aggregated the entire features/ tree as one "run" (Codex QE #2).
|
|
5663
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(slug) || slug === '.' || slug === '..' || slug.includes('..')) {
|
|
5664
|
+
write(json ? JSON.stringify({ error: 'a plain --slug <feature> is required (no path separators)', exitCode: 1 }) : 'dz score: a plain --slug <feature> is required (no path separators)');
|
|
5665
|
+
return 1;
|
|
5666
|
+
}
|
|
5667
|
+
const root = resolve(cwd, options.get('project') ?? '.');
|
|
5668
|
+
const dir = join(root, 'features', slug);
|
|
5669
|
+
if (!existsSync(dir)) {
|
|
5670
|
+
write(json ? JSON.stringify({ error: `no run at features/${slug}/`, exitCode: 1 }) : `dz score: no run at features/${slug}/`);
|
|
5671
|
+
return 1;
|
|
5672
|
+
}
|
|
5673
|
+
|
|
5674
|
+
// Gather the artifact texts (bounded, best-effort — an unreadable file is skipped, not fatal).
|
|
5675
|
+
const artifacts: Record<string, string> = {};
|
|
5676
|
+
let fileBudget = 200; // a run has ~a dozen artifacts; a wide tree must degrade, not exhaust memory
|
|
5677
|
+
const walk = (d: string, prefix: string, depth: number): void => {
|
|
5678
|
+
if (depth > 3 || fileBudget <= 0) return;
|
|
5679
|
+
let entries: string[];
|
|
5680
|
+
try {
|
|
5681
|
+
entries = readdirSync(d);
|
|
5682
|
+
} catch {
|
|
5683
|
+
return;
|
|
5684
|
+
}
|
|
5685
|
+
for (const name of entries) {
|
|
5686
|
+
if (fileBudget <= 0) return;
|
|
5687
|
+
const full = join(d, name);
|
|
5688
|
+
const rel = prefix === '' ? name : `${prefix}/${name}`;
|
|
5689
|
+
try {
|
|
5690
|
+
// lstat: a symlinked artifact (or a symlinked features/<slug> subtree) could smuggle
|
|
5691
|
+
// OUTSIDE text into the scorecard's evidence (Codex QE #5).
|
|
5692
|
+
const st = lstatSync(full);
|
|
5693
|
+
if (st.isSymbolicLink()) continue;
|
|
5694
|
+
if (st.isDirectory()) walk(full, rel, depth + 1);
|
|
5695
|
+
else if (st.isFile() && name.endsWith('.md') && st.size < 512 * 1024) {
|
|
5696
|
+
artifacts[rel] = readFileSync(full, 'utf-8');
|
|
5697
|
+
fileBudget -= 1;
|
|
5698
|
+
}
|
|
5699
|
+
} catch {
|
|
5700
|
+
/* skip unreadable */
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5703
|
+
};
|
|
5704
|
+
walk(dir, '', 0);
|
|
5705
|
+
|
|
5706
|
+
const card = scoreRun(slug, artifacts);
|
|
5707
|
+
if (json) write(JSON.stringify({ ...card, exitCode: 0 }, null, 2));
|
|
5708
|
+
else write(renderScorecard(card));
|
|
5709
|
+
return 0;
|
|
5710
|
+
}
|
|
5711
|
+
|
|
5628
5712
|
/**
|
|
5629
5713
|
* `dz compounding` — does the learning loop actually PAY? (feature compounding, scout C2.)
|
|
5630
5714
|
* Gathers the facts (store rows, apply-leg usage log, guard audit) and hands them to the PURE
|
|
@@ -6495,6 +6579,8 @@ export async function runCli(argv: string[], io: CliIo = {}): Promise<number> {
|
|
|
6495
6579
|
return cmdSkillsVerify(options, flags, cwd, write);
|
|
6496
6580
|
case 'compounding':
|
|
6497
6581
|
return cmdCompounding(options, flags, cwd, write);
|
|
6582
|
+
case 'score':
|
|
6583
|
+
return cmdScore(options, flags, cwd, write);
|
|
6498
6584
|
case 'routing':
|
|
6499
6585
|
return cmdRouting(options, flags, cwd, write);
|
|
6500
6586
|
case 'bto-optimize':
|