@dzhechkov/harness-cli 0.3.221 → 0.3.223
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/README.md +57 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +133 -1
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
- package/src/cli.ts +124 -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.223",
|
|
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",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@dzhechkov/skills-reverse-engineering": "^0.1.0",
|
|
56
56
|
"@dzhechkov/skills-presentation-storyteller": "^0.1.0",
|
|
57
57
|
"@dzhechkov/skills-website-cloner": "^0.1.0",
|
|
58
|
-
"@dzhechkov/harness-core": "0.3.
|
|
58
|
+
"@dzhechkov/harness-core": "0.3.117"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/node": "^25.6.0",
|
package/src/cli.ts
CHANGED
|
@@ -135,7 +135,17 @@ import {
|
|
|
135
135
|
retroLessonText,
|
|
136
136
|
PROCESS_SIGNATURES,
|
|
137
137
|
RETRO_DOMAIN,
|
|
138
|
+
scanForSetup,
|
|
139
|
+
buildSetupPlan,
|
|
140
|
+
scaffoldFromSpec,
|
|
141
|
+
renderScaffoldPreview,
|
|
142
|
+
readExistingForScaffold,
|
|
143
|
+
assembleChallengeContext,
|
|
144
|
+
buildChallengeBrief,
|
|
145
|
+
pickAdversaryModel,
|
|
146
|
+
CHALLENGE_QUESTIONS,
|
|
138
147
|
} from '@dzhechkov/harness-core';
|
|
148
|
+
import type { SetupSpec } from '@dzhechkov/harness-core';
|
|
139
149
|
import type { ProvenanceMode, PackVerdict, ClaudeUsageModel, PatternRecord, TargetName, BookKU, HarmonizeReport, UsageCalibrationPlan, ClaimFinding, RecallUsagePatternRow } from '@dzhechkov/harness-core';
|
|
140
150
|
import { getPreset, PRESET_NAMES } from '@dzhechkov/harness-presets';
|
|
141
151
|
import { scanGitHub, analyzeRepo, generateReport, deepAnalyze, scanAllSources, ScoutMemory } from '@dzhechkov/scout';
|
|
@@ -4438,6 +4448,116 @@ async function cmdRetro(options: Map<string, string>, flags: Set<string>, cwd: s
|
|
|
4438
4448
|
return 0;
|
|
4439
4449
|
}
|
|
4440
4450
|
|
|
4451
|
+
/**
|
|
4452
|
+
* `dz feature-adr-setup` — the deterministic engine behind the `configure-feature-adr` SKILL (R5). Scaffolds
|
|
4453
|
+
* the project-awareness files (vision / map / testing / project-skills) so a user configures feature-adr
|
|
4454
|
+
* without knowing any schema.
|
|
4455
|
+
* --plan [--json] read-only: what exists / discoverable / missing (the "which docs, where?" answer)
|
|
4456
|
+
* --from-spec <spec.json> preview the scaffold (create / augment per file); the SKILL fills the spec
|
|
4457
|
+
* --apply with --from-spec: WRITE (create missing, AUGMENT existing — never clobber)
|
|
4458
|
+
*/
|
|
4459
|
+
function cmdFeatureAdrSetup(options: Map<string, string>, flags: Set<string>, cwd: string, write: Write): number {
|
|
4460
|
+
let repoRoot = cwd;
|
|
4461
|
+
try { repoRoot = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf-8' }).trim() || cwd; } catch { /* not git */ }
|
|
4462
|
+
|
|
4463
|
+
const specPath = options.get('from-spec');
|
|
4464
|
+
if (specPath === undefined) {
|
|
4465
|
+
// default + --plan: the read-only "which documents, and where?" answer.
|
|
4466
|
+
const plan = buildSetupPlan(scanForSetup(repoRoot));
|
|
4467
|
+
if (flags.has('json')) { write(JSON.stringify(plan, null, 2)); return 0; }
|
|
4468
|
+
write('feature-adr project setup — current state:');
|
|
4469
|
+
write(` vision.md: ${plan.exists.vision ? '✓' : '✗ missing'} manifest: ${plan.exists.manifest ? '✓' : '✗ missing'} testing.md: ${plan.exists.testing ? '✓' : '✗ missing'} project-skills.json: ${plan.exists.projectSkills ? '✓' : '✗ missing'}`);
|
|
4470
|
+
if (plan.discoveredPackages.length > 0) write(` discovered ${plan.discoveredPackages.length} workspace package(s) → a map can be auto-scaffolded`);
|
|
4471
|
+
if (plan.suggestions.length > 0) { write(' next steps:'); for (const s of plan.suggestions) write(` • ${s}`); }
|
|
4472
|
+
if (plan.missing.length === 0) write(' all set — feature-adr is project-aware here.');
|
|
4473
|
+
else write(' → the `configure-feature-adr` skill walks you through the missing docs; or pass a filled spec with --from-spec.');
|
|
4474
|
+
return 0;
|
|
4475
|
+
}
|
|
4476
|
+
|
|
4477
|
+
// --from-spec: scaffold (preview, or --apply to write).
|
|
4478
|
+
let spec: SetupSpec;
|
|
4479
|
+
try { spec = JSON.parse(readFileSync(resolve(cwd, specPath), 'utf-8')) as SetupSpec; }
|
|
4480
|
+
catch (e) { write(`dz feature-adr-setup: cannot read spec ${specPath}: ${e instanceof Error ? e.message : String(e)}`); return 1; }
|
|
4481
|
+
|
|
4482
|
+
const result = scaffoldFromSpec(spec, readExistingForScaffold(repoRoot));
|
|
4483
|
+
if (flags.has('json') && !flags.has('apply')) { write(JSON.stringify(result, null, 2)); return 0; }
|
|
4484
|
+
write(renderScaffoldPreview(result));
|
|
4485
|
+
|
|
4486
|
+
if (!flags.has('apply')) { write('\n(preview only — pass --apply to write)'); return 0; }
|
|
4487
|
+
|
|
4488
|
+
let wrote = 0;
|
|
4489
|
+
for (const f of result.files) {
|
|
4490
|
+
if (f.action === 'unchanged') continue; // never clobber
|
|
4491
|
+
const abs = resolve(repoRoot, f.path);
|
|
4492
|
+
// Write-boundary augment-never-clobber guard (defense in depth): a 'create' must NEVER overwrite an
|
|
4493
|
+
// existing file, even if the plan (built from a caller-supplied `existing`) said create. 'augment' has
|
|
4494
|
+
// already union-merged the prior content, so overwriting there is the merged result, not a clobber.
|
|
4495
|
+
if (f.action === 'create' && existsSync(abs)) {
|
|
4496
|
+
write(` · skipped ${f.path} — already exists (not overwritten)`);
|
|
4497
|
+
continue;
|
|
4498
|
+
}
|
|
4499
|
+
try {
|
|
4500
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
4501
|
+
writeFileSync(abs, f.content);
|
|
4502
|
+
write(` ✓ ${f.action === 'create' ? 'created' : 'augmented'} ${f.path}`);
|
|
4503
|
+
wrote++;
|
|
4504
|
+
} catch (e) { write(` ✗ ${f.path}: ${e instanceof Error ? e.message : String(e)}`); }
|
|
4505
|
+
}
|
|
4506
|
+
write(`\n↳ wrote ${wrote} file(s). Verify: dz project-skills + dz architecture --revise`);
|
|
4507
|
+
return 0;
|
|
4508
|
+
}
|
|
4509
|
+
|
|
4510
|
+
/**
|
|
4511
|
+
* `dz challenge` — the deterministic "cartridge" behind the `challenge-panel` adversarial plan-gate (R6).
|
|
4512
|
+
* Assembles a WIDE context pack (plan + vision + testing + map + degradations) and prints the fixed C1-C8
|
|
4513
|
+
* "break it, don't confirm it" brief + the verdict schema. It runs NO LLM and writes nothing — the
|
|
4514
|
+
* `challenge-panel` SKILL fires the brief at a FRESH adversary (a model ≠ the plan author) + a mandatory
|
|
4515
|
+
* cross-validator. ADVISE, never block.
|
|
4516
|
+
* --plan <plan.md> the plan under review (required)
|
|
4517
|
+
* --json emit the assembled context + brief as JSON
|
|
4518
|
+
* --context-only just the assembled context summary (what the panel will read)
|
|
4519
|
+
* --author <model> the plan-author model → prints the cross-family adversary to dispatch (FR-4)
|
|
4520
|
+
*/
|
|
4521
|
+
function cmdChallenge(options: Map<string, string>, flags: Set<string>, cwd: string, write: Write): number {
|
|
4522
|
+
let repoRoot = cwd;
|
|
4523
|
+
try { repoRoot = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf-8' }).trim() || cwd; } catch { /* not git */ }
|
|
4524
|
+
|
|
4525
|
+
const planPath = options.get('plan');
|
|
4526
|
+
if (planPath === undefined) {
|
|
4527
|
+
write('dz challenge: pass --plan <plan.md> (the implementation plan to challenge).');
|
|
4528
|
+
return 1;
|
|
4529
|
+
}
|
|
4530
|
+
|
|
4531
|
+
const ctx = assembleChallengeContext(repoRoot, planPath);
|
|
4532
|
+
if (ctx.plan === '') {
|
|
4533
|
+
write(`dz challenge: plan not found or empty: ${planPath}`);
|
|
4534
|
+
return 1;
|
|
4535
|
+
}
|
|
4536
|
+
|
|
4537
|
+
const adversary = pickAdversaryModel(options.get('author') ?? 'claude');
|
|
4538
|
+
|
|
4539
|
+
if (flags.has('json')) {
|
|
4540
|
+
write(JSON.stringify({ context: ctx, brief: buildChallengeBrief(ctx), adversary, questions: CHALLENGE_QUESTIONS }, null, 2));
|
|
4541
|
+
return 0;
|
|
4542
|
+
}
|
|
4543
|
+
|
|
4544
|
+
if (flags.has('context-only')) {
|
|
4545
|
+
const has = (v: string | undefined): string => (v === undefined ? '✗ (less calibration)' : `✓ ${v.length} chars`);
|
|
4546
|
+
write(`challenge context for ${planPath}:`);
|
|
4547
|
+
write(` plan: ✓ ${ctx.plan.length} chars`);
|
|
4548
|
+
write(` vision: ${has(ctx.vision)}`);
|
|
4549
|
+
write(` testing: ${has(ctx.testing)}`);
|
|
4550
|
+
write(` map: ${has(ctx.map)}`);
|
|
4551
|
+
write(` degradations:${has(ctx.degradations)}`);
|
|
4552
|
+
write(` → adversary: ${adversary.model} — ${adversary.note}`);
|
|
4553
|
+
return 0;
|
|
4554
|
+
}
|
|
4555
|
+
|
|
4556
|
+
write(buildChallengeBrief(ctx));
|
|
4557
|
+
write(`\n── dispatch (panel ≠ plan author) ──\n${adversary.model}: ${adversary.note}`);
|
|
4558
|
+
return 0;
|
|
4559
|
+
}
|
|
4560
|
+
|
|
4441
4561
|
function cmdStats(cwd: string, write: Write): number {
|
|
4442
4562
|
const baseDir = join(cwd, 'packages', '@dzhechkov');
|
|
4443
4563
|
if (!existsSync(baseDir)) {
|
|
@@ -4710,6 +4830,10 @@ export async function runCli(argv: string[], io: CliIo = {}): Promise<number> {
|
|
|
4710
4830
|
return await cmdMrRakes(options, flags, cwd, write);
|
|
4711
4831
|
case 'retro':
|
|
4712
4832
|
return await cmdRetro(options, flags, cwd, write);
|
|
4833
|
+
case 'feature-adr-setup':
|
|
4834
|
+
return cmdFeatureAdrSetup(options, flags, cwd, write);
|
|
4835
|
+
case 'challenge':
|
|
4836
|
+
return cmdChallenge(options, flags, cwd, write);
|
|
4713
4837
|
case 'dashboard':
|
|
4714
4838
|
return cmdDashboard(cwd, write);
|
|
4715
4839
|
case 'roam':
|