@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/harness-cli",
3
- "version": "0.3.230",
3
+ "version": "0.3.232",
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.122"
58
+ "@dzhechkov/harness-core": "0.3.124"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@types/node": "^25.6.0",
package/src/cli.ts CHANGED
@@ -4282,6 +4282,21 @@ function gatherGuardFacts(op: string, root: string, text: string | undefined, st
4282
4282
  facts['packages'] = packages;
4283
4283
  try { facts['drift'] = sweepSkillDrift(root, { scope: 'packages', allowlist: readDriftAllowlist(root) }).drifted.map((d) => d.name); } catch { /* skip */ }
4284
4284
  facts['counts'] = gatherReadmeCounts(root);
4285
+ // readme-first: from the WORKING-TREE diff (publishes happen pre-commit here), per package: does the
4286
+ // change set contain its package.json (the version-bump signal) without its README.md?
4287
+ try {
4288
+ const status = execSync('git status --porcelain -- "packages/@dzhechkov/"', { cwd: root, encoding: 'utf-8' });
4289
+ const perPack = new Map<string, { pkgJson: boolean; readme: boolean }>();
4290
+ for (const line of status.split('\n')) {
4291
+ const m = line.match(/packages\/@dzhechkov\/([^/]+)\/(.+)$/);
4292
+ if (!m || !m[1] || !m[2]) continue;
4293
+ const e = perPack.get(m[1]) ?? { pkgJson: false, readme: false };
4294
+ if (m[2] === 'package.json') e.pkgJson = true;
4295
+ if (m[2] === 'README.md') e.readme = true;
4296
+ perPack.set(m[1], e);
4297
+ }
4298
+ facts['readmeFirst'] = [...perPack.entries()].map(([name, e]) => ({ name: '@dzhechkov/' + name, versionBumped: e.pkgJson, readmeChanged: e.readme }));
4299
+ } catch { /* not a git repo — rule skips */ }
4285
4300
  }
4286
4301
  if (op === 'consolidate') {
4287
4302
  try { facts['drift'] = sweepSkillDrift(root, { scope: 'packages', allowlist: readDriftAllowlist(root) }).drifted.map((d) => d.name); } catch { /* skip */ }
@@ -4767,10 +4782,21 @@ async function cmdRetro(options: Map<string, string>, flags: Set<string>, cwd: s
4767
4782
  */
4768
4783
  function cmdFeatureAdrSetup(options: Map<string, string>, flags: Set<string>, cwd: string, write: Write): number {
4769
4784
  let repoRoot = cwd;
4770
- try { repoRoot = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf-8' }).trim() || cwd; } catch { /* not git */ }
4785
+ try { repoRoot = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }).trim() || cwd; } catch { /* not git */ }
4786
+
4787
+ // P3 (fa-improvements): --guards scaffolds the deterministic guard set (guards.config.json + the
4788
+ // zero-dependency check.mjs runner) — usable standalone (`dz feature-adr-setup --guards --apply`) or
4789
+ // together with --from-spec. --loc-cap <n> tunes the LOC cap (default 700).
4790
+ const wantGuards = flags.has('guards');
4791
+ const locCapRaw = options.get('loc-cap');
4792
+ const locCap = locCapRaw !== undefined ? Number(locCapRaw) : undefined;
4793
+ if (locCapRaw !== undefined && (!Number.isFinite(locCap) || (locCap as number) <= 0)) {
4794
+ write('dz feature-adr-setup: --loc-cap must be a positive finite number');
4795
+ return 1;
4796
+ }
4771
4797
 
4772
4798
  const specPath = options.get('from-spec');
4773
- if (specPath === undefined) {
4799
+ if (specPath === undefined && !wantGuards) {
4774
4800
  // default + --plan: the read-only "which documents, and where?" answer.
4775
4801
  const plan = buildSetupPlan(scanForSetup(repoRoot));
4776
4802
  if (flags.has('json')) { write(JSON.stringify(plan, null, 2)); return 0; }
@@ -4783,10 +4809,15 @@ function cmdFeatureAdrSetup(options: Map<string, string>, flags: Set<string>, cw
4783
4809
  return 0;
4784
4810
  }
4785
4811
 
4786
- // --from-spec: scaffold (preview, or --apply to write).
4812
+ // --from-spec and/or --guards: scaffold (preview, or --apply to write).
4787
4813
  let spec: SetupSpec;
4788
- try { spec = JSON.parse(readFileSync(resolve(cwd, specPath), 'utf-8')) as SetupSpec; }
4789
- catch (e) { write(`dz feature-adr-setup: cannot read spec ${specPath}: ${e instanceof Error ? e.message : String(e)}`); return 1; }
4814
+ if (specPath !== undefined) {
4815
+ try { spec = JSON.parse(readFileSync(resolve(cwd, specPath), 'utf-8')) as SetupSpec; }
4816
+ catch (e) { write(`dz feature-adr-setup: cannot read spec ${specPath}: ${e instanceof Error ? e.message : String(e)}`); return 1; }
4817
+ } else {
4818
+ spec = {}; // --guards standalone: scaffold just the guard set
4819
+ }
4820
+ if (wantGuards) spec = { ...spec, guards: locCap !== undefined ? { locCap } : true };
4790
4821
 
4791
4822
  const result = scaffoldFromSpec(spec, readExistingForScaffold(repoRoot));
4792
4823
  if (flags.has('json') && !flags.has('apply')) { write(JSON.stringify(result, null, 2)); return 0; }