@dzhechkov/harness-cli 0.4.5 → 0.5.0

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.
@@ -0,0 +1,106 @@
1
+ /**
2
+ * `@dzhechkov/harness-core` compatibility guard — the import-free island.
3
+ *
4
+ * ## Why this module exists
5
+ *
6
+ * ESM resolves and link-checks **every named binding of the whole static graph** before
7
+ * the first byte of user code runs. `bin.ts` used to `import { runCli } from './cli.js'`
8
+ * statically, and `cli.ts` statically imports ~100 names from `@dzhechkov/harness-core`.
9
+ * Against a cached lower core the linker threw
10
+ * `SyntaxError: … does not provide an export named 'GRADE_SUCCESS_FLOOR'` at
11
+ * `#asyncInstantiate` — every subcommand, `--version` included, died before any guard
12
+ * could speak. (MEASURED against `@dzhechkov/harness-core@0.4.1`; `^0.4.0` legally
13
+ * resolves it and the symbol only exists from core 0.4.2.)
14
+ *
15
+ * ## The defining constraint — negative, and enforced rather than remembered
16
+ *
17
+ * **This file may not import anything from `@dzhechkov/harness-core`, directly or
18
+ * transitively — only `node:` builtins.** If it joins the graph it is guarding, it dies
19
+ * with it and the guard is decorative. `test/core-compat-guard.test.ts` parses this
20
+ * file's import list and asserts exactly that.
21
+ *
22
+ * ## Fail-open on an unreadable version — a deliberate exception
23
+ *
24
+ * When the installed core's version cannot be determined the guard **proceeds**. Its job
25
+ * is to replace a bad message with a good one, not to gate execution; blocking a working
26
+ * install because a version string was unreadable would be a self-inflicted outage
27
+ * strictly worse than the `SyntaxError`. This is a conscious exception to the house rule
28
+ * "inconclusive never passes", which governs gates that grant a *quality* verdict — do
29
+ * not "fix" it. The symmetric hazard (a guard that fires wrongly and bricks a good
30
+ * install) is covered by {@link compareSemver} treating any unparseable component as
31
+ * compatible.
32
+ *
33
+ * @packageDocumentation
34
+ */
35
+ /**
36
+ * The lowest `@dzhechkov/harness-core` this CLI build can run against.
37
+ *
38
+ * Kept equal to the minimum of the declared dependency range in `package.json` — a
39
+ * standing test (`test/core-import-floor.test.ts`, F1) fails if the two drift apart,
40
+ * because a guard that says 0.4.7 while npm may install 0.4.2 is worse than no guard.
41
+ */
42
+ export declare const MIN_CORE = "0.5.0";
43
+ /** The npm name of the guarded package — one literal, used by every leg below. */
44
+ export declare const CORE_PACKAGE_NAME = "@dzhechkov/harness-core";
45
+ /**
46
+ * Compare two semver strings by `major.minor.patch`, then by prerelease.
47
+ *
48
+ * Rules that matter here:
49
+ * - every component runs through a `Number.isFinite` clamp; a non-finite or missing
50
+ * component makes the comparison return `0` (compatible), never a false "too old";
51
+ * - **prerelease (`-…`) and build metadata (`+…`) are parsed SEPARATELY**, because they
52
+ * mean opposite things. A prerelease sorts BELOW its release (`0.4.6-rc.1` < `0.4.6`),
53
+ * so a release-candidate core does not silently satisfy a floor it has not reached;
54
+ * build metadata is **ignored entirely** (`0.4.6+sha1234` === `0.4.6`), because a core
55
+ * built from a tagged commit is that version and refusing it would be a self-inflicted
56
+ * outage — exactly what ADR-003 driver D6 forbids.
57
+ *
58
+ * Both halves were wrong before fix round 1 (QE F3): one capture group `(?:[-+](.*))?`
59
+ * swallowed either sigil, patched over by `!m[4].startsWith('build')`. MEASURED
60
+ * consequences: `0.4.6+sha1234` was REFUSED (false block) and `0.4.6-build.5` was
61
+ * ACCEPTED (false pass) against a `0.4.6` floor. A string special case is not SemVer.
62
+ */
63
+ export declare function compareSemver(a: string, b: string): -1 | 0 | 1;
64
+ /**
65
+ * Best-effort: what version of `@dzhechkov/harness-core` will actually be loaded?
66
+ *
67
+ * Three legs, in order — the obvious one does **not** work on its own:
68
+ *
69
+ * 1. `import.meta.resolve(CORE_PACKAGE_NAME)` (a function on node ≥20.6; `typeof`-guarded
70
+ * because `engines` says `>=20` and it is flagged on 20.0–20.5), then walk up to the
71
+ * nearest `package.json`.
72
+ * 2. Ancestor-walk from this file for `node_modules/@dzhechkov/harness-core/package.json`
73
+ * — **no resolver semantics**. This leg is load-bearing rather than a fallback: an old
74
+ * core's `exports` map declares only `{".": {"import": …}}`, so
75
+ * `require.resolve('@dzhechkov/harness-core/package.json')` fails with
76
+ * `ERR_PACKAGE_PATH_NOT_EXPORTED` (MEASURED in this tree) — and the old core is
77
+ * precisely the case the guard exists for.
78
+ * 3. `null` — the fail-open path documented at the top of this file.
79
+ */
80
+ export declare function resolveInstalledCoreVersion(fromUrl: string): string | null;
81
+ /** The verdict of {@link checkCoreCompat}. */
82
+ export type CoreCompatVerdict = {
83
+ readonly ok: true;
84
+ } | {
85
+ readonly ok: false;
86
+ readonly message: string;
87
+ };
88
+ /**
89
+ * Decide whether the found core is usable, and if not, say so in words a user can act on.
90
+ *
91
+ * `found === null` ⇒ `{ ok: true }` (fail-open — see the module doc comment).
92
+ */
93
+ export declare function checkCoreCompat(input: {
94
+ found: string | null;
95
+ min: string;
96
+ }): CoreCompatVerdict;
97
+ /**
98
+ * Reactive translator for the failure the pre-emptive guard could not see.
99
+ *
100
+ * If the version probe fails open (leg 3) and the dynamic import then dies on a missing
101
+ * ESM binding, the raw `SyntaxError` reads like a corrupted install or a Node problem.
102
+ * Rewrite it into the same named form. Returns `null` for any OTHER error — the caller
103
+ * must re-throw those unchanged, so real bugs still surface.
104
+ */
105
+ export declare function describeMissingExportError(error: unknown, found: string | null): string | null;
106
+ //# sourceMappingURL=core-compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-compat.d.ts","sourceRoot":"","sources":["../src/core-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAMH;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,UAAU,CAAC;AAEhC,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,4BAA4B,CAAC;AAiC3D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CA0B9D;AA2BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA4B1E;AAED,8CAA8C;AAC9C,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzG;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,iBAAiB,CAY/F;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAU9F"}
@@ -0,0 +1,252 @@
1
+ /**
2
+ * `@dzhechkov/harness-core` compatibility guard — the import-free island.
3
+ *
4
+ * ## Why this module exists
5
+ *
6
+ * ESM resolves and link-checks **every named binding of the whole static graph** before
7
+ * the first byte of user code runs. `bin.ts` used to `import { runCli } from './cli.js'`
8
+ * statically, and `cli.ts` statically imports ~100 names from `@dzhechkov/harness-core`.
9
+ * Against a cached lower core the linker threw
10
+ * `SyntaxError: … does not provide an export named 'GRADE_SUCCESS_FLOOR'` at
11
+ * `#asyncInstantiate` — every subcommand, `--version` included, died before any guard
12
+ * could speak. (MEASURED against `@dzhechkov/harness-core@0.4.1`; `^0.4.0` legally
13
+ * resolves it and the symbol only exists from core 0.4.2.)
14
+ *
15
+ * ## The defining constraint — negative, and enforced rather than remembered
16
+ *
17
+ * **This file may not import anything from `@dzhechkov/harness-core`, directly or
18
+ * transitively — only `node:` builtins.** If it joins the graph it is guarding, it dies
19
+ * with it and the guard is decorative. `test/core-compat-guard.test.ts` parses this
20
+ * file's import list and asserts exactly that.
21
+ *
22
+ * ## Fail-open on an unreadable version — a deliberate exception
23
+ *
24
+ * When the installed core's version cannot be determined the guard **proceeds**. Its job
25
+ * is to replace a bad message with a good one, not to gate execution; blocking a working
26
+ * install because a version string was unreadable would be a self-inflicted outage
27
+ * strictly worse than the `SyntaxError`. This is a conscious exception to the house rule
28
+ * "inconclusive never passes", which governs gates that grant a *quality* verdict — do
29
+ * not "fix" it. The symmetric hazard (a guard that fires wrongly and bricks a good
30
+ * install) is covered by {@link compareSemver} treating any unparseable component as
31
+ * compatible.
32
+ *
33
+ * @packageDocumentation
34
+ */
35
+ import { existsSync, readFileSync } from 'node:fs';
36
+ import { dirname, join, resolve } from 'node:path';
37
+ import { fileURLToPath } from 'node:url';
38
+ /**
39
+ * The lowest `@dzhechkov/harness-core` this CLI build can run against.
40
+ *
41
+ * Kept equal to the minimum of the declared dependency range in `package.json` — a
42
+ * standing test (`test/core-import-floor.test.ts`, F1) fails if the two drift apart,
43
+ * because a guard that says 0.4.7 while npm may install 0.4.2 is worse than no guard.
44
+ */
45
+ export const MIN_CORE = '0.5.0';
46
+ /** The npm name of the guarded package — one literal, used by every leg below. */
47
+ export const CORE_PACKAGE_NAME = '@dzhechkov/harness-core';
48
+ /**
49
+ * Compare the dot-separated identifiers of two SemVer prerelease strings (§11.4).
50
+ *
51
+ * Numeric identifiers compare numerically and rank BELOW alphanumeric ones; when every
52
+ * shared identifier is equal, the longer list is the higher version.
53
+ */
54
+ function comparePrerelease(a, b) {
55
+ if (a === b)
56
+ return 0;
57
+ const xs = a.split('.');
58
+ const ys = b.split('.');
59
+ for (let i = 0; i < Math.max(xs.length, ys.length); i += 1) {
60
+ const x = xs[i];
61
+ const y = ys[i];
62
+ // A shorter identifier list is the LOWER version (`1.0.0-rc` < `1.0.0-rc.1`).
63
+ if (x === undefined)
64
+ return -1;
65
+ if (y === undefined)
66
+ return 1;
67
+ const xNum = /^\d+$/.test(x);
68
+ const yNum = /^\d+$/.test(y);
69
+ if (xNum && yNum) {
70
+ const nx = Number(x);
71
+ const ny = Number(y);
72
+ if (nx !== ny)
73
+ return nx < ny ? -1 : 1;
74
+ continue;
75
+ }
76
+ // Numeric identifiers always have lower precedence than alphanumeric ones.
77
+ if (xNum !== yNum)
78
+ return xNum ? -1 : 1;
79
+ if (x !== y)
80
+ return x < y ? -1 : 1;
81
+ }
82
+ return 0;
83
+ }
84
+ /**
85
+ * Compare two semver strings by `major.minor.patch`, then by prerelease.
86
+ *
87
+ * Rules that matter here:
88
+ * - every component runs through a `Number.isFinite` clamp; a non-finite or missing
89
+ * component makes the comparison return `0` (compatible), never a false "too old";
90
+ * - **prerelease (`-…`) and build metadata (`+…`) are parsed SEPARATELY**, because they
91
+ * mean opposite things. A prerelease sorts BELOW its release (`0.4.6-rc.1` < `0.4.6`),
92
+ * so a release-candidate core does not silently satisfy a floor it has not reached;
93
+ * build metadata is **ignored entirely** (`0.4.6+sha1234` === `0.4.6`), because a core
94
+ * built from a tagged commit is that version and refusing it would be a self-inflicted
95
+ * outage — exactly what ADR-003 driver D6 forbids.
96
+ *
97
+ * Both halves were wrong before fix round 1 (QE F3): one capture group `(?:[-+](.*))?`
98
+ * swallowed either sigil, patched over by `!m[4].startsWith('build')`. MEASURED
99
+ * consequences: `0.4.6+sha1234` was REFUSED (false block) and `0.4.6-build.5` was
100
+ * ACCEPTED (false pass) against a `0.4.6` floor. A string special case is not SemVer.
101
+ */
102
+ export function compareSemver(a, b) {
103
+ const parse = (v) => {
104
+ // Prerelease and build metadata get one capture EACH, in SemVer's own order.
105
+ const m = /^\s*v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?\s*$/.exec(v);
106
+ if (m === null)
107
+ return null;
108
+ const nums = [Number(m[1]), Number(m[2]), Number(m[3])];
109
+ if (!nums.every((n) => Number.isFinite(n)))
110
+ return null;
111
+ // m[5] (build metadata) is deliberately never read: SemVer §10 says it is not
112
+ // part of precedence.
113
+ return { nums, pre: m[4] !== undefined && m[4].length > 0 ? m[4] : null };
114
+ };
115
+ const pa = parse(a);
116
+ const pb = parse(b);
117
+ // Unparseable on either side ⇒ "compatible": never brick a working install on a
118
+ // version string we failed to read.
119
+ if (pa === null || pb === null)
120
+ return 0;
121
+ for (let i = 0; i < 3; i += 1) {
122
+ const x = pa.nums[i] ?? 0;
123
+ const y = pb.nums[i] ?? 0;
124
+ if (x < y)
125
+ return -1;
126
+ if (x > y)
127
+ return 1;
128
+ }
129
+ if (pa.pre === null && pb.pre === null)
130
+ return 0;
131
+ if (pa.pre === null)
132
+ return 1;
133
+ if (pb.pre === null)
134
+ return -1;
135
+ return comparePrerelease(pa.pre, pb.pre);
136
+ }
137
+ /** Read `.version` out of a `package.json`, or `null` if it is missing/unreadable. */
138
+ function readVersion(packageJsonPath) {
139
+ try {
140
+ const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
141
+ return typeof parsed.version === 'string' ? parsed.version : null;
142
+ }
143
+ catch {
144
+ return null;
145
+ }
146
+ }
147
+ /** Walk up from `start` to the nearest enclosing `package.json`, reading its version. */
148
+ function versionFromEnclosingPackage(start) {
149
+ let dir = start;
150
+ for (;;) {
151
+ const candidate = join(dir, 'package.json');
152
+ if (existsSync(candidate)) {
153
+ const version = readVersion(candidate);
154
+ if (version !== null)
155
+ return version;
156
+ }
157
+ const parent = dirname(dir);
158
+ if (parent === dir)
159
+ return null;
160
+ dir = parent;
161
+ }
162
+ }
163
+ /**
164
+ * Best-effort: what version of `@dzhechkov/harness-core` will actually be loaded?
165
+ *
166
+ * Three legs, in order — the obvious one does **not** work on its own:
167
+ *
168
+ * 1. `import.meta.resolve(CORE_PACKAGE_NAME)` (a function on node ≥20.6; `typeof`-guarded
169
+ * because `engines` says `>=20` and it is flagged on 20.0–20.5), then walk up to the
170
+ * nearest `package.json`.
171
+ * 2. Ancestor-walk from this file for `node_modules/@dzhechkov/harness-core/package.json`
172
+ * — **no resolver semantics**. This leg is load-bearing rather than a fallback: an old
173
+ * core's `exports` map declares only `{".": {"import": …}}`, so
174
+ * `require.resolve('@dzhechkov/harness-core/package.json')` fails with
175
+ * `ERR_PACKAGE_PATH_NOT_EXPORTED` (MEASURED in this tree) — and the old core is
176
+ * precisely the case the guard exists for.
177
+ * 3. `null` — the fail-open path documented at the top of this file.
178
+ */
179
+ export function resolveInstalledCoreVersion(fromUrl) {
180
+ const meta = import.meta;
181
+ if (typeof meta.resolve === 'function') {
182
+ try {
183
+ const resolved = meta.resolve(CORE_PACKAGE_NAME);
184
+ const version = versionFromEnclosingPackage(dirname(fileURLToPath(resolved)));
185
+ if (version !== null)
186
+ return version;
187
+ }
188
+ catch {
189
+ /* fall through to the filesystem walk */
190
+ }
191
+ }
192
+ let dir;
193
+ try {
194
+ dir = dirname(fileURLToPath(fromUrl));
195
+ }
196
+ catch {
197
+ dir = resolve('.');
198
+ }
199
+ for (;;) {
200
+ const candidate = join(dir, 'node_modules', ...CORE_PACKAGE_NAME.split('/'), 'package.json');
201
+ if (existsSync(candidate)) {
202
+ const version = readVersion(candidate);
203
+ if (version !== null)
204
+ return version;
205
+ }
206
+ const parent = dirname(dir);
207
+ if (parent === dir)
208
+ return null;
209
+ dir = parent;
210
+ }
211
+ }
212
+ /**
213
+ * Decide whether the found core is usable, and if not, say so in words a user can act on.
214
+ *
215
+ * `found === null` ⇒ `{ ok: true }` (fail-open — see the module doc comment).
216
+ */
217
+ export function checkCoreCompat(input) {
218
+ const { found, min } = input;
219
+ if (found === null)
220
+ return { ok: true };
221
+ if (compareSemver(found, min) >= 0)
222
+ return { ok: true };
223
+ return {
224
+ ok: false,
225
+ message: [
226
+ `dz: needs ${CORE_PACKAGE_NAME} >= ${min}, found ${found}`,
227
+ ' Your resolver reused a cached lower core. Fix: rm -rf ~/.npm/_npx && npx @dzhechkov/harness-cli@latest --version',
228
+ ` (or: npm i -D ${CORE_PACKAGE_NAME}@latest)`,
229
+ ].join('\n'),
230
+ };
231
+ }
232
+ /**
233
+ * Reactive translator for the failure the pre-emptive guard could not see.
234
+ *
235
+ * If the version probe fails open (leg 3) and the dynamic import then dies on a missing
236
+ * ESM binding, the raw `SyntaxError` reads like a corrupted install or a Node problem.
237
+ * Rewrite it into the same named form. Returns `null` for any OTHER error — the caller
238
+ * must re-throw those unchanged, so real bugs still surface.
239
+ */
240
+ export function describeMissingExportError(error, found) {
241
+ const message = error instanceof Error ? error.message : String(error);
242
+ const match = /does not provide an export named '?([A-Za-z0-9_$]+)'?/.exec(message);
243
+ if (match === null)
244
+ return null;
245
+ return [
246
+ `dz: this build needs ${CORE_PACKAGE_NAME} >= ${MIN_CORE}${found !== null ? `, found ${found}` : ''}`,
247
+ ` The installed core does not export ${JSON.stringify(match[1] ?? '')}, which this CLI imports.`,
248
+ ' Fix: rm -rf ~/.npm/_npx && npx @dzhechkov/harness-cli@latest --version',
249
+ ` (or: npm i -D ${CORE_PACKAGE_NAME}@latest)`,
250
+ ].join('\n');
251
+ }
252
+ //# sourceMappingURL=core-compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-compat.js","sourceRoot":"","sources":["../src/core-compat.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dzhechkov/harness-cli",
3
- "version": "0.4.5",
4
- "description": "The dz CLI — install AI skills for Claude Code, Codex, OpenCode, Hermes, OpenClaude, GitHub Copilot. 35 commands, 13 presets, 6 platform targets.",
3
+ "version": "0.5.0",
4
+ "description": "The dz CLI — install AI skills for Claude Code, Codex, OpenCode, Hermes, OpenClaude, GitHub Copilot. 67 commands, 14 presets, 10 platform targets.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "dzhechko",
@@ -40,15 +40,8 @@
40
40
  ".dz-manifest.json",
41
41
  "sbom.json"
42
42
  ],
43
- "scripts": {
44
- "build": "tsc -p tsconfig.json",
45
- "test": "vitest run",
46
- "test:watch": "vitest",
47
- "typecheck": "tsc -p tsconfig.json --noEmit",
48
- "lint": "tsc -p tsconfig.json --noEmit"
49
- },
50
43
  "dependencies": {
51
- "@dzhechkov/harness-core": "^0.4.0",
44
+ "@dzhechkov/harness-core": "^0.5.0",
52
45
  "@dzhechkov/harness-presets": "^0.5.0",
53
46
  "@dzhechkov/scout": "^0.8.0",
54
47
  "@dzhechkov/skills-devops": "^0.3.0",
@@ -82,5 +75,12 @@
82
75
  "url": "https://github.com/djd1m/dz-harness-hub.git",
83
76
  "directory": "packages/@dzhechkov/harness-cli"
84
77
  },
85
- "homepage": "https://github.com/djd1m/dz-harness-hub/tree/main/packages/@dzhechkov/harness-cli#readme"
86
- }
78
+ "homepage": "https://github.com/djd1m/dz-harness-hub/tree/main/packages/@dzhechkov/harness-cli#readme",
79
+ "scripts": {
80
+ "build": "tsc -p tsconfig.json",
81
+ "test": "vitest run",
82
+ "test:watch": "vitest",
83
+ "typecheck": "tsc -p tsconfig.json --noEmit",
84
+ "lint": "tsc -p tsconfig.json --noEmit"
85
+ }
86
+ }