@dzhechkov/harness-cli 0.3.230 → 0.3.232
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 +23 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +44 -8
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
- package/src/cli.ts +36 -5
package/README.md
CHANGED
|
@@ -501,6 +501,7 @@ dz discrimination-check --test <f[,f]> [--base <ref>] [--name <filter>] [--runne
|
|
|
501
501
|
dz sign --init --out <path> | --pack <dir> --key <path> # --init: generate the Ed25519 keypair (private OUTSIDE the repo, prints the public key for keys/dz.pub); else sign a pack's manifest + CycloneDX SBOM
|
|
502
502
|
dz sbom --pack <dir> [--out <file>] # emit the CycloneDX 1.5 SBOM for a pack standalone (file-level bill of materials); print to stdout or write to a file
|
|
503
503
|
dz guard check --op <publish|teach|consolidate|reindex> [--text <s>] [--json] [--force <reason>] # declarative constraint layer before self-mutating ops: HARD violation → block (exit 1), SOFT → warn; zero-config defaults, .dz/guard.json to customise; dz guard --init | dz guard log (append-only audit). dz publish runs it automatically (--no-guard "<reason>" = logged escape hatch)
|
|
504
|
+
dz feature-adr-setup --guards [--loc-cap <n>] [--apply] # P3: scaffold DETERMINISTIC guard tests into the project — guards.config.json + a zero-dependency check.mjs runner (LOC cap, secret scan, frozen-file sha256 pins, waivers-with-reasons); wire `node architecture/guards/check.mjs` into CI
|
|
504
505
|
dz publish [--filter <name>] [--bump-only] [--claim-check <off|warn|error>] (dry-run by default; pass --yes/--confirm to go live; claim-check gate defaults to warn — surfaces README claim findings, never blocks)
|
|
505
506
|
dz auto-canonicalize --source <github-url> --pack <skills-pack>
|
|
506
507
|
dz sync-upstream [--package <dir>] [--list] [--all]
|
|
@@ -1604,7 +1605,7 @@ invariants: HARD rules **block** the operation, SOFT rules warn. Zero config nee
|
|
|
1604
1605
|
cover the known rakes; `.dz/guard.json` (via `dz guard --init`) exists only if you want to tune a severity
|
|
1605
1606
|
or disable a rule.
|
|
1606
1607
|
```bash
|
|
1607
|
-
dz guard check --op publish # no-workspace-star · no-skill-drift · no-secrets · readme-consistency
|
|
1608
|
+
dz guard check --op publish # no-workspace-star · no-skill-drift · no-secrets · readme-consistency · readme-first
|
|
1608
1609
|
dz guard check --op teach --text "the fix: export sk-abc..." # → BLOCK (exit 1): looks like a credential
|
|
1609
1610
|
dz guard log # append-only audit: every verdict + every forced override
|
|
1610
1611
|
```
|
|
@@ -1619,6 +1620,27 @@ visible, never silent. Calibrated against false gates: in a pnpm workspace, `wor
|
|
|
1619
1620
|
*correct* (pnpm rewrites it at publish), so the rule resolves each workspace dep to the version it would
|
|
1620
1621
|
ship as and blocks only a dep that would ship raw.
|
|
1621
1622
|
|
|
1623
|
+
### `dz feature-adr-setup --guards` — when a project rule should be a TEST, not a reviewer's memory
|
|
1624
|
+
|
|
1625
|
+
A 700-line cap enforced by reviewer judgment catches one file and misses its sibling in the same change;
|
|
1626
|
+
`wc -l` catches both, always (the cost-of-detection ladder). `--guards` scaffolds a deterministic guard set
|
|
1627
|
+
into the TARGET project — no framework, no dependency, any stack with Node:
|
|
1628
|
+
```bash
|
|
1629
|
+
dz feature-adr-setup --guards # preview (existing files are never clobbered)
|
|
1630
|
+
dz feature-adr-setup --guards --apply # writes architecture/guards/{guards.config.json,check.mjs}
|
|
1631
|
+
node architecture/guards/check.mjs # run locally / wire into CI or the test command
|
|
1632
|
+
```
|
|
1633
|
+
```
|
|
1634
|
+
guards: ✗ 1 violation(s)
|
|
1635
|
+
[loc-cap] src/huge.ts — 801 lines > cap 700
|
|
1636
|
+
```
|
|
1637
|
+
Three deterministic rules, each with a **waiver mechanism that requires a reason** (a waiver without one is
|
|
1638
|
+
itself a violation — a conscious exception is recorded, not silently allowed): **loc-cap** (god-object
|
|
1639
|
+
guard, `--loc-cap <n>` tunes, default 700), **secret-scan** (the same high-signal credential shapes as
|
|
1640
|
+
`dz guard`), **frozen-files** (sha256 pins for files that must not change silently). The config is data —
|
|
1641
|
+
edit caps/paths/waivers in `guards.config.json`; the project-critic role should then *not* re-flag these
|
|
1642
|
+
rules, only waivers without a reason.
|
|
1643
|
+
|
|
1622
1644
|
### Semantic recall (vector tier)
|
|
1623
1645
|
|
|
1624
1646
|
`dz recall` is **hybrid** when the vector tier is available and **exactly the old lexical command** when it is not — enabling it never changes behavior for projects that skip it.
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiPH,2EAA2E;AAC3E,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiPH,2EAA2E;AAC3E,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AA48JD,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,KAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CA4I5E"}
|
package/dist/cli.js
CHANGED
|
@@ -3999,6 +3999,25 @@ function gatherGuardFacts(op, root, text, storeCap) {
|
|
|
3999
3999
|
}
|
|
4000
4000
|
catch { /* skip */ }
|
|
4001
4001
|
facts['counts'] = gatherReadmeCounts(root);
|
|
4002
|
+
// readme-first: from the WORKING-TREE diff (publishes happen pre-commit here), per package: does the
|
|
4003
|
+
// change set contain its package.json (the version-bump signal) without its README.md?
|
|
4004
|
+
try {
|
|
4005
|
+
const status = execSync('git status --porcelain -- "packages/@dzhechkov/"', { cwd: root, encoding: 'utf-8' });
|
|
4006
|
+
const perPack = new Map();
|
|
4007
|
+
for (const line of status.split('\n')) {
|
|
4008
|
+
const m = line.match(/packages\/@dzhechkov\/([^/]+)\/(.+)$/);
|
|
4009
|
+
if (!m || !m[1] || !m[2])
|
|
4010
|
+
continue;
|
|
4011
|
+
const e = perPack.get(m[1]) ?? { pkgJson: false, readme: false };
|
|
4012
|
+
if (m[2] === 'package.json')
|
|
4013
|
+
e.pkgJson = true;
|
|
4014
|
+
if (m[2] === 'README.md')
|
|
4015
|
+
e.readme = true;
|
|
4016
|
+
perPack.set(m[1], e);
|
|
4017
|
+
}
|
|
4018
|
+
facts['readmeFirst'] = [...perPack.entries()].map(([name, e]) => ({ name: '@dzhechkov/' + name, versionBumped: e.pkgJson, readmeChanged: e.readme }));
|
|
4019
|
+
}
|
|
4020
|
+
catch { /* not a git repo — rule skips */ }
|
|
4002
4021
|
}
|
|
4003
4022
|
if (op === 'consolidate') {
|
|
4004
4023
|
try {
|
|
@@ -4493,11 +4512,21 @@ async function cmdRetro(options, flags, cwd, write) {
|
|
|
4493
4512
|
function cmdFeatureAdrSetup(options, flags, cwd, write) {
|
|
4494
4513
|
let repoRoot = cwd;
|
|
4495
4514
|
try {
|
|
4496
|
-
repoRoot = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf-8' }).trim() || cwd;
|
|
4515
|
+
repoRoot = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }).trim() || cwd;
|
|
4497
4516
|
}
|
|
4498
4517
|
catch { /* not git */ }
|
|
4518
|
+
// P3 (fa-improvements): --guards scaffolds the deterministic guard set (guards.config.json + the
|
|
4519
|
+
// zero-dependency check.mjs runner) — usable standalone (`dz feature-adr-setup --guards --apply`) or
|
|
4520
|
+
// together with --from-spec. --loc-cap <n> tunes the LOC cap (default 700).
|
|
4521
|
+
const wantGuards = flags.has('guards');
|
|
4522
|
+
const locCapRaw = options.get('loc-cap');
|
|
4523
|
+
const locCap = locCapRaw !== undefined ? Number(locCapRaw) : undefined;
|
|
4524
|
+
if (locCapRaw !== undefined && (!Number.isFinite(locCap) || locCap <= 0)) {
|
|
4525
|
+
write('dz feature-adr-setup: --loc-cap must be a positive finite number');
|
|
4526
|
+
return 1;
|
|
4527
|
+
}
|
|
4499
4528
|
const specPath = options.get('from-spec');
|
|
4500
|
-
if (specPath === undefined) {
|
|
4529
|
+
if (specPath === undefined && !wantGuards) {
|
|
4501
4530
|
// default + --plan: the read-only "which documents, and where?" answer.
|
|
4502
4531
|
const plan = buildSetupPlan(scanForSetup(repoRoot));
|
|
4503
4532
|
if (flags.has('json')) {
|
|
@@ -4519,15 +4548,22 @@ function cmdFeatureAdrSetup(options, flags, cwd, write) {
|
|
|
4519
4548
|
write(' → the `configure-feature-adr` skill walks you through the missing docs; or pass a filled spec with --from-spec.');
|
|
4520
4549
|
return 0;
|
|
4521
4550
|
}
|
|
4522
|
-
// --from-spec: scaffold (preview, or --apply to write).
|
|
4551
|
+
// --from-spec and/or --guards: scaffold (preview, or --apply to write).
|
|
4523
4552
|
let spec;
|
|
4524
|
-
|
|
4525
|
-
|
|
4553
|
+
if (specPath !== undefined) {
|
|
4554
|
+
try {
|
|
4555
|
+
spec = JSON.parse(readFileSync(resolve(cwd, specPath), 'utf-8'));
|
|
4556
|
+
}
|
|
4557
|
+
catch (e) {
|
|
4558
|
+
write(`dz feature-adr-setup: cannot read spec ${specPath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
4559
|
+
return 1;
|
|
4560
|
+
}
|
|
4526
4561
|
}
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
return 1;
|
|
4562
|
+
else {
|
|
4563
|
+
spec = {}; // --guards standalone: scaffold just the guard set
|
|
4530
4564
|
}
|
|
4565
|
+
if (wantGuards)
|
|
4566
|
+
spec = { ...spec, guards: locCap !== undefined ? { locCap } : true };
|
|
4531
4567
|
const result = scaffoldFromSpec(spec, readExistingForScaffold(repoRoot));
|
|
4532
4568
|
if (flags.has('json') && !flags.has('apply')) {
|
|
4533
4569
|
write(JSON.stringify(result, null, 2));
|