@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.
- package/.dz-manifest.json +92 -16
- package/LICENSE +21 -0
- package/README.md +345 -18
- package/dist/bin.d.ts +10 -0
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +45 -12
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +712 -170
- package/dist/cli.js.map +1 -1
- package/dist/core-compat.d.ts +106 -0
- package/dist/core-compat.d.ts.map +1 -0
- package/dist/core-compat.js +252 -0
- package/dist/core-compat.js.map +1 -0
- package/package.json +12 -12
- package/sbom.json +205 -15
- package/src/bin.ts +43 -12
- package/src/cli.ts +707 -146
- package/src/core-compat.ts +240 -0
package/README.md
CHANGED
|
@@ -125,6 +125,140 @@ point any tool at (a skill is just Markdown). Dedicated targets are on the [road
|
|
|
125
125
|
**❌ No target applies:** `nemoclaw` (NVIDIA agent-safety runtime — not a code editor, no rules file) ·
|
|
126
126
|
`v0` (UI-only, no repo file). *(`pi` is a real coder but reads `AGENTS.md` → covered by `agents-md`.)*
|
|
127
127
|
|
|
128
|
+
#### `--target` aliases and did-you-mean
|
|
129
|
+
|
|
130
|
+
`--target claude` used to be rejected outright — the canonical name is `claude-code`, and the error
|
|
131
|
+
just re-printed the list. All **eight** `--target`-taking commands (`init`, `verify`, `install`,
|
|
132
|
+
`compose`, `setup`, `upgrade`, `parity`, `feature-adr-setup`) now resolve the value first.
|
|
133
|
+
|
|
134
|
+
*(This sentence used to say "every" and name only seven: `dz parity` was missed, and shipped the
|
|
135
|
+
original defect verbatim. It is now checked rather than promised — `test/target-alias-cli.test.ts`
|
|
136
|
+
asserts that no command reads `--target` without reaching the resolver, and that every command whose
|
|
137
|
+
`--help` advertises `--target` appears in the per-command sweep.)*
|
|
138
|
+
|
|
139
|
+
**Accepted aliases** (a table, so adding one is a data edit):
|
|
140
|
+
|
|
141
|
+
| You type | You get | Why it is a row |
|
|
142
|
+
|----------|---------|-----------------|
|
|
143
|
+
| `claude` · `cc` | `claude-code` | the tool's everyday name |
|
|
144
|
+
| `agents` | `agents-md` | the everyday name of the `AGENTS.md` target |
|
|
145
|
+
| `gpt` · `openai` | `codex` | the vendor name, not the CLI's |
|
|
146
|
+
|
|
147
|
+
Case, padding and separators are handled **without** a row: `CLAUDE`, `Claude_Code`, `claudecode`
|
|
148
|
+
and ` claude-code ` all resolve to `claude-code`; `agentsmd` and `agents.md` resolve to `agents-md`.
|
|
149
|
+
|
|
150
|
+
**A typo is SUGGESTED, never silently accepted** — installing to the wrong target on a guess is worse
|
|
151
|
+
than one round-trip:
|
|
152
|
+
|
|
153
|
+
```console
|
|
154
|
+
$ dz init --target clade-code --preset devops > out.txt # the refusal is on STDERR
|
|
155
|
+
dz init: unknown --target "clade-code" — did you mean "claude-code"?
|
|
156
|
+
--target must be one of: agents-md, claude-code, codex, copilot, cursor, gemini, hermes, openclaude, opencode, windsurf
|
|
157
|
+
$ echo $?
|
|
158
|
+
1
|
|
159
|
+
$ wc -c out.txt
|
|
160
|
+
0 out.txt # stdout stays a clean data channel, even on a refusal
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Both lines go to stderr** — the refusal, like the alias note below, is diagnosis, not data. `dz
|
|
164
|
+
parity --target <bad> --json` likewise writes its structured error to stderr and leaves stdout empty,
|
|
165
|
+
so `| jq` is never handed a diagnostic.
|
|
166
|
+
|
|
167
|
+
An ambiguous prefix gets no guess at all (`--target co` could be `codex` or `copilot`), and neither
|
|
168
|
+
does nonsense (`--target totally-bogus` prints the plain list). When an alias IS accepted, the
|
|
169
|
+
substitution is announced **on stderr**, so piped stdout stays machine-readable:
|
|
170
|
+
|
|
171
|
+
```console
|
|
172
|
+
$ dz init --target claude --preset devops > installed.txt
|
|
173
|
+
dz init: --target "claude" → claude-code (alias)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**When this matters:** you are following a blog post or a teammate's snippet that says `--target claude`.
|
|
177
|
+
It now works, and you are told what it resolved to.
|
|
178
|
+
|
|
179
|
+
### `dz list` — one broken skill never hides the rest
|
|
180
|
+
|
|
181
|
+
`dz list` used to abort on the FIRST unparseable `SKILL.md`: exit 1, an error naming neither the file
|
|
182
|
+
nor a count, and every other skill in the tree invisible. A pack you installed could blank your whole
|
|
183
|
+
listing. Now the loadable skills are listed on **stdout** and the unloadable ones are named on
|
|
184
|
+
**stderr**:
|
|
185
|
+
|
|
186
|
+
```console
|
|
187
|
+
$ dz list --skills-dir .claude/skills
|
|
188
|
+
105 skill(s) in /home/you/proj/.claude/skills:
|
|
189
|
+
|
|
190
|
+
api-design Designs REST and GraphQL APIs with OpenAPI specs…
|
|
191
|
+
…103 more…
|
|
192
|
+
test-writer Writes focused unit and integration tests…
|
|
193
|
+
$ echo $?
|
|
194
|
+
1
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
…with the diagnosis kept out of the data:
|
|
198
|
+
|
|
199
|
+
```console
|
|
200
|
+
$ dz list --skills-dir .claude/skills 2>/dev/null # stdout only — clean, pipeable
|
|
201
|
+
105 skill(s) in …
|
|
202
|
+
|
|
203
|
+
$ dz list --skills-dir .claude/skills 1>/dev/null # stderr only — the actionable part
|
|
204
|
+
dz list: 105 listed, 1 skipped in /home/you/proj/.claude/skills
|
|
205
|
+
⚠ 1 skill(s) skipped (unparseable SKILL.md):
|
|
206
|
+
/home/you/proj/.claude/skills/broken-one/SKILL.md
|
|
207
|
+
SKILL.md must begin with a "---" frontmatter fence
|
|
208
|
+
(line 1: "# Broken One")
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The full contract:
|
|
212
|
+
|
|
213
|
+
| valid skills | skipped | stdout | stderr | exit |
|
|
214
|
+
|--------------|---------|--------|--------|------|
|
|
215
|
+
| >0 | 0 | the listing | *empty* | 0 |
|
|
216
|
+
| >0 | >0 | the listing of the valid ones | named summary | 1 |
|
|
217
|
+
| 0 | >0 | *nothing* | named summary (`0 listed, N skipped`) | 1 |
|
|
218
|
+
| 0 | 0 | *nothing* | `dz list: no skills found in <dir>` | 1 |
|
|
219
|
+
|
|
220
|
+
`dz init`, `dz install` and `dz sync` behave the same way — the good skills are installed, the bad ones
|
|
221
|
+
are named, and the command exits 1.
|
|
222
|
+
|
|
223
|
+
**Two failure kinds, two headers, two subjects.** A skill that will not PARSE and a skill that will not
|
|
224
|
+
WRITE are different accusations, so `dz init` reports them separately:
|
|
225
|
+
|
|
226
|
+
```console
|
|
227
|
+
$ dz init --target claude-code --skills-dir ./skills --project ./proj
|
|
228
|
+
dz init --target claude-code: 1 skill(s), 1 file(s) written, 0 skipped
|
|
229
|
+
dz init: 1 installed, 1 failed to write # ← stderr
|
|
230
|
+
✗ 1 skill(s) failed to install (compile/write error):
|
|
231
|
+
alpha
|
|
232
|
+
EEXIST: file already exists, mkdir './proj/.claude/skills/alpha'
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The header names the **target**, not `alpha/SKILL.md` — which is perfectly valid. (It used to print
|
|
236
|
+
`⚠ 1 skill(s) skipped (unparseable SKILL.md)` and quote `line 1: "---"`, a valid frontmatter fence, as
|
|
237
|
+
its evidence: a failure that names the wrong artifact is worse than an anonymous one.)
|
|
238
|
+
|
|
239
|
+
`dz install` renders the offending path **relative to the package**
|
|
240
|
+
and says so explicitly, because a `node_modules/**` path is not something you can act on:
|
|
241
|
+
|
|
242
|
+
```console
|
|
243
|
+
$ dz install @someone/skills-pack
|
|
244
|
+
dz install @someone/skills-pack: 12 skill(s), 24 file(s) written, 0 skipped
|
|
245
|
+
dz install: @someone/skills-pack ships 1 unparseable skill(s) —
|
|
246
|
+
⚠ 1 skill(s) skipped (unparseable SKILL.md):
|
|
247
|
+
skills/broken-one/SKILL.md
|
|
248
|
+
SKILL.md must begin with a "---" frontmatter fence
|
|
249
|
+
This is a defect in the package, not in your project.
|
|
250
|
+
Workaround: npx -y @someone/skills-pack init
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**When this matters:** a package you installed shipped a broken skill — you still see everything else,
|
|
254
|
+
you know exactly which file is at fault, and you know whose defect it is.
|
|
255
|
+
|
|
256
|
+
> **`dz` requires `@dzhechkov/harness-core >= 0.4.7`.** If you ever see
|
|
257
|
+
> `dz: needs @dzhechkov/harness-core >= 0.4.7, found 0.4.1`, a stale core was reused from a cache:
|
|
258
|
+
> `rm -rf ~/.npm/_npx && npx @dzhechkov/harness-cli@latest --version`. That named message replaced a
|
|
259
|
+
> bare `SyntaxError: … does not provide an export named 'GRADE_SUCCESS_FLOOR'` that used to kill even
|
|
260
|
+
> `dz --version`.
|
|
261
|
+
|
|
128
262
|
> **"Nothing installs" / "no skills found"?** Update the CLI:
|
|
129
263
|
> `cd /tmp && npm i -g @dzhechkov/harness-cli@latest`. Older global installs couldn't locate their
|
|
130
264
|
> own bundled packs outside the monorepo — now fixed, so `dz registry`/`dz init`/`dz setup` work
|
|
@@ -132,7 +266,7 @@ point any tool at (a skill is just Markdown). Dedicated targets are on the [road
|
|
|
132
266
|
|
|
133
267
|
## User Journey — from install to mastery
|
|
134
268
|
|
|
135
|
-
All
|
|
269
|
+
All 67 commands (MEASURED — reproducer: `grep -c "^ case '" src/cli.ts`, the dispatch cases) mapped to a real workflow:
|
|
136
270
|
|
|
137
271
|
```
|
|
138
272
|
DISCOVER → INSTALL → USE → CREATE → MAINTAIN → SHARE
|
|
@@ -1015,7 +1149,7 @@ green: re-sign reminder (`dz sign …` — the publish signature gate is refuse-
|
|
|
1015
1149
|
before a multi-package npm release, or whenever a broken dist/bin must be impossible to ship; keep plain
|
|
1016
1150
|
`dz publish` for routine pushes. `dz publish` itself is byte-identical whether or not release exists.
|
|
1017
1151
|
|
|
1018
|
-
### Skill Packs (
|
|
1152
|
+
### Skill Packs (18 packs · 189 skills)
|
|
1019
1153
|
|
|
1020
1154
|
Each pack is an npm package — click through for the **full per-skill documentation** (what each skill does + how to trigger it). Install a whole pack with `dz install <pkg>`, or pick skills with `dz init --select` / a `--preset`.
|
|
1021
1155
|
|
|
@@ -1027,7 +1161,7 @@ Each pack is an npm package — click through for the **full per-skill documenta
|
|
|
1027
1161
|
| [@dzhechkov/skills-qe](https://www.npmjs.com/package/@dzhechkov/skills-qe) | 20 | Quality engineering — test-gen, coverage, chaos, defect intelligence, QCSD swarms |
|
|
1028
1162
|
| [@dzhechkov/skills-reasoning](https://www.npmjs.com/package/@dzhechkov/skills-reasoning) | 4 | Generic reasoning & code-quality — investigate (root-cause), solid (SOLID/TDD), karpathy-guidelines, agents-md-creator |
|
|
1029
1163
|
| [@dzhechkov/skills-ecc](https://www.npmjs.com/package/@dzhechkov/skills-ecc) | 20 | Claude-Code engineering craft — agent architecture, autonomous loops, framework patterns |
|
|
1030
|
-
| [@dzhechkov/skills-meta](https://www.npmjs.com/package/@dzhechkov/skills-meta) |
|
|
1164
|
+
| [@dzhechkov/skills-meta](https://www.npmjs.com/package/@dzhechkov/skills-meta) | 19 | Dev-process meta skills — explore, feature-adr, design-thinking, audit, skill-advisor, loop-plan-author |
|
|
1031
1165
|
| [@dzhechkov/skills-academic](https://www.npmjs.com/package/@dzhechkov/skills-academic) | 5 | Thesis-defense toolkit — dissertation review, questions, doc-check, defense eval |
|
|
1032
1166
|
| [@dzhechkov/skills-news](https://www.npmjs.com/package/@dzhechkov/skills-news) | 3 | *dz-original* — news digests (`news-digest`) + delta watches (`news-monitor`) + bundled `goap-research-ed25519` verified-research backend (mandatory) |
|
|
1033
1167
|
| [@dzhechkov/skills-idea2prd](https://www.npmjs.com/package/@dzhechkov/skills-idea2prd) | 1 | *dz-original* — `idea2prd-manual`: idea/problem → PRD+ADR+DDD+C4+Pseudocode+Tests+Completion (9 checkpoints); bundles the analyst trio as a sources.json-tracked vendor ([ADR-0001](https://github.com/djd1m/dz-harness-hub/blob/main/docs/adr/0001-skill-canonicalization-and-dependency-model.md)) |
|
|
@@ -1038,6 +1172,7 @@ Each pack is an npm package — click through for the **full per-skill documenta
|
|
|
1038
1172
|
| [@dzhechkov/skills-taste](https://www.npmjs.com/package/@dzhechkov/skills-taste) | 1 | *imported (MIT)* — `design-taste-frontend`: anti-slop landing/portfolio/redesign framework (dials + pre-flight + GSAP skeletons); complements frontend-design (`dz init --select design-taste-frontend`) ([ADR-0002](https://github.com/djd1m/dz-harness-hub/blob/main/docs/adr/0002-product-and-design-expansion.md)) |
|
|
1039
1173
|
| [@dzhechkov/skills-book-digitizer](https://www.npmjs.com/package/@dzhechkov/skills-book-digitizer) | 8 | *dz-original* — book → installable methodology pack: `digitize-book` (orchestrator) + ingest/extract/distill/pack/kb-index + `book-brain-register` (CP6 promote → cross-project brain) + `source-brain-ingest` (repo sibling). Verified provenance, IP-safe, resumable (`dz init --select digitize-book`) ([ADR-001](https://github.com/djd1m/dz-harness-hub/blob/main/features/book-knowledge-digitizer/03_adr/001-book-to-skillpack-pipeline.md)) |
|
|
1040
1174
|
| [@dzhechkov/skills-12factor](https://www.npmjs.com/package/@dzhechkov/skills-12factor) | 12 | *generated by the digitizer, CC BY 4.0* — The Twelve-Factor App distilled into 12 decision-moment skills (one per factor). The first PUBLIC digitized-book pack; paraphrased (shingling-gated), routing-gated (every factor carries triggers), attributed (`NOTICE`) (`dz init --select 12factor-config-in-environment,…`) |
|
|
1175
|
+
| [@dzhechkov/skills-book-ai-apps](https://www.npmjs.com/package/@dzhechkov/skills-book-ai-apps) | 17 | *generated by the digitizer, CP5-published* — «Building Applications with AI Agents» (Albada, рус. пер.) distilled into 17 decision-moment skills across the whole agent-building arc: agent-fit & model choice, single-vs-multi, orchestration, tool design, knowledge & memory, context engineering, evaluation, probabilistic behaviour checks, release gates, improvement loops, drift, human-in-the-loop, agent UX, governance, security. Ships our page-anchored Knowledge Units, NOT the book text — shingling-gated at 0 uncited verbatim runs >=8 words; publication is the recorded CP5 owner decision; `trust_tier 1` (routing-gated, not human-reviewed) Since 0.2.2 it also ships `brain/ai-apps.sqlite`, the 223-KU knowledge slice: `dz brain add --from-pack @dzhechkov/skills-book-ai-apps` loads it into your `~/.dz/brain`, then `dz brain query --source ai-apps` answers in any project (`dz install @dzhechkov/skills-book-ai-apps --target claude-code`) |
|
|
1041
1176
|
|
|
1042
1177
|
### Available Presets (14)
|
|
1043
1178
|
|
|
@@ -1097,7 +1232,7 @@ Get the whole set with `dz init --target claude-code --preset meta`, or pick one
|
|
|
1097
1232
|
|
|
1098
1233
|
Custom loops used to be born by copy-pasting a 1470-line workflow script; nothing deterministic
|
|
1099
1234
|
checked the copy. The loop-designer meta-factory replaces that: a versioned typed plan
|
|
1100
|
-
(`loop-plan/1`), a schema-driven generator,
|
|
1235
|
+
(`loop-plan/1`), a schema-driven generator, an 18-rule lint gate, and a local trace plane.
|
|
1101
1236
|
|
|
1102
1237
|
```bash
|
|
1103
1238
|
# 1. Scaffold a plan (pipeline | barrier | fanout | gate), edit the TODO prompts:
|
|
@@ -1116,7 +1251,7 @@ dz workflow render triage-loop.plan.json --o triage-loop.js
|
|
|
1116
1251
|
|
|
1117
1252
|
# 4. Gate it (generated-loop CI mode; exit 0/1/3 — inconclusive is NEVER a pass):
|
|
1118
1253
|
dz workflow-lint triage-loop.js --plan triage-loop.plan.json --require-plan
|
|
1119
|
-
# → dz workflow-lint: PASS (mode=require-plan; 0 fail, 0 warn, 0 inconclusive over
|
|
1254
|
+
# → dz workflow-lint: PASS (mode=require-plan; 0 fail, 0 warn, 0 inconclusive over 18 rules)
|
|
1120
1255
|
|
|
1121
1256
|
# 5. Run it via Workflow({scriptPath:'triage-loop.js', args:{traceDir:'/abs/run-dir'}}), then read
|
|
1122
1257
|
# the run's own trace (seq-ordered; wallTime is diagnostic only):
|
|
@@ -1207,12 +1342,46 @@ dz workflow render audit.plan.json --o audit.loop.js
|
|
|
1207
1342
|
# → wrote audit.loop.plan.json then audit.loop.js (exec-fp sha256:49feb8a2c1e17038…, blobs: trace)
|
|
1208
1343
|
|
|
1209
1344
|
dz workflow-lint audit.loop.js --plan audit.loop.plan.json --require-plan
|
|
1210
|
-
# → dz workflow-lint: PASS (mode=require-plan; 0 fail, 1 warn, 0 inconclusive over
|
|
1345
|
+
# → dz workflow-lint: PASS (mode=require-plan; 0 fail, 1 warn, 0 inconclusive over 18 rules)
|
|
1211
1346
|
```
|
|
1212
1347
|
|
|
1213
1348
|
`inconclusive` is never a pass, and the rendered script keeps your hand edits across re-renders
|
|
1214
1349
|
(USER regions are preserved).
|
|
1215
1350
|
|
|
1351
|
+
#### Declare each step's tool perimeter — `LoopStep.tools`
|
|
1352
|
+
|
|
1353
|
+
**When to use it:** any loop whose steps reach external systems (a ticket tracker, a wiki, a repo
|
|
1354
|
+
host) through MCP, and you want the intended perimeter written down, well-formed, and gated rather
|
|
1355
|
+
than living in a prompt someone will edit.
|
|
1356
|
+
|
|
1357
|
+
```jsonc
|
|
1358
|
+
// in your plan.json — one array per DISPATCHING step (agent | gate)
|
|
1359
|
+
{"stepId":"discovery","kind":"agent","phase":"Discovery",
|
|
1360
|
+
"tools":["gitlab:read","jira:read","wiki:read"], "budget":{"maxAgents":1}},
|
|
1361
|
+
{"stepId":"verdict-gate","kind":"gate","phase":"Discovery","deps":["discovery"],
|
|
1362
|
+
"tools":[], "budget":{"maxAgents":1}}
|
|
1363
|
+
```
|
|
1364
|
+
|
|
1365
|
+
`tools: []` is the **meaningful** value for a step that touches no external tool — absence is a lint
|
|
1366
|
+
finding, because silence is never permission:
|
|
1367
|
+
|
|
1368
|
+
```bash
|
|
1369
|
+
dz workflow-lint my-loop.js --plan my-loop.plan.json --require-plan
|
|
1370
|
+
# → FAIL tool-perimeter-declared: dispatching step sa declares no `tools` perimeter — absence
|
|
1371
|
+
# FLAGS: silence is never permission (declare `tools: []` if the step touches no external tool)
|
|
1372
|
+
```
|
|
1373
|
+
|
|
1374
|
+
A non-empty array is **enacted**, not decorative: it renders a fixed contract line into that step's
|
|
1375
|
+
prompt, and the lint rule cross-checks the script against the plan (so a plan edit you forgot to
|
|
1376
|
+
re-render fails too). Severity is staged — **WARN by default, FAIL only under `--require-plan`.**
|
|
1377
|
+
|
|
1378
|
+
**It is a DECLARATION, not enforcement.** `agent()` exposes no tool restriction; real enforcement
|
|
1379
|
+
lives at the MCP server. Do not read this field as a sandbox.
|
|
1380
|
+
|
|
1381
|
+
Worked consumer in this repo: `.claude/workflows/cfr-pipeline.js` — a 12-step, 6-gate Customer
|
|
1382
|
+
Feature Request pipeline with seven typed terminal exits, whose five source-touching stages each
|
|
1383
|
+
declare their perimeter (`features/cfr-pipeline/`).
|
|
1384
|
+
|
|
1216
1385
|
#### Step 4 — run it (Claude Code), read it back (anywhere)
|
|
1217
1386
|
|
|
1218
1387
|
In **Claude Code**, paste exactly this shape:
|
|
@@ -1342,9 +1511,9 @@ only at their documented scopes (plan + step), and `fanouts[].registry` items mu
|
|
|
1342
1511
|
ItemKey domain the trace plane enforces — `trace.emit` can never decide whether a valid plan runs.
|
|
1343
1512
|
Deferred options are on the loop-designer roadmap.
|
|
1344
1513
|
|
|
1345
|
-
## All Commands (
|
|
1514
|
+
## All Commands (68)
|
|
1346
1515
|
|
|
1347
|
-
*(
|
|
1516
|
+
*(67 MEASURED — reproducer: `grep -c "^ case '" src/cli.ts`, the dispatch cases.)*
|
|
1348
1517
|
|
|
1349
1518
|
```
|
|
1350
1519
|
dz setup --target <name> [--preset <name>] [--select id,id,...] [--skills-dir <dir>] [--memory agentdb] [--no-memory] [--no-hooks] [--install-driver] [--force]
|
|
@@ -1399,7 +1568,7 @@ dz feature-adr-setup [--plan] [--from-spec <f>] [--apply] # guided project onb
|
|
|
1399
1568
|
dz challenge --plan <plan.md> [--json] [--context-only] [--author <model>] # adversarial plan-gate (behind the `challenge-panel` skill): assemble a WIDE context pack (plan + vision + testing + map + degradations) + the fixed C1-C8 "break it" brief for a FRESH adversary (≠ plan author); advisory, never blocks
|
|
1400
1569
|
dz routing [--stage <s>] [--json] # inspect the learned cost-optimal routing store: what `args.models.<stage>='auto-cost'` believes per (stage, complexity-tier, model) — gated attempts/successes/rate (feeds feature-adr model selection)
|
|
1401
1570
|
dz bto-optimize --split|--plan|--select|--scope-check|--diff [--json] # deterministic engine behind /bto-optimize: hold-out split + hard-capped budget + no-regress-on-holdout winner selection (defeats judge-gaming); prose-only, diff-confirmed, never auto-writes
|
|
1402
|
-
dz discrimination-check --test <f[,f]> [--base <ref>] [--name <filter>] [--runner <cmd>] [--json] # §42 test-discrimination gate for feature-adr Step-8: run the ADR's property test in an isolated git worktree at pre-feature base — it MUST go red without the fix
|
|
1571
|
+
dz discrimination-check --test <f[,f]> [--base <ref>] [--name <filter>] [--runner <cmd>] [--timeout <ms>] [--json] # §42 test-discrimination gate for feature-adr Step-8: run the ADR's property test in an isolated git worktree at pre-feature base — it MUST go red without the fix. SEVEN verdicts, each gated on EXECUTION evidence: DISCRIMINATES · DISCRIMINATES_VIA_ERROR · NON_DISCRIMINATING (false green) · TEST_FILE_ABSENT · LOAD_ERROR_AT_BOTH_REVS · FAILS_AT_TIP · CANNOT_ISOLATE (+ typed reason). Advisory, never auto-aborts
|
|
1403
1572
|
dz mutation-gate [--package <dir>] [--registry <file>] [--test-cmd "<cmd>"] [--only <id[,id]>] [--timeout <ms>] [--rebaseline per-entry|final] [--keep-scratch] [--json] # the mutation gate: for each NAMED protection in a declarative registry, copy the package to a scratch dir (shadow-repo layout, node_modules symlinked, git-initialized), verify the baseline is green, apply the entry's exact {find, replace} mutation, run the suite, REQUIRE red, restore — and require the red to be ATTRIBUTABLE to the protection: a mutated file that no longer parses is MUTATION_UNPARSEABLE, a failing count far above the entry's bound (maxFailing, default from observed) is OVER_FAILING, and a restored tree that does not reproduce green makes the entry INCONCLUSIVE (flaky suite). A mutation that does not apply, a green suite, or an inconclusive run is a FAILURE — never a skip. exit 0 all proven / 1 gate failed / 2 setup error
|
|
1404
1573
|
dz delivery-check --slug <slug> [--context-only] [--findings <f.json>] [--strict] [--author <model>] [--json] # portable Step-10 Delivery Gate: the `manual` form that travels to every shell target — prints the 4-plane review brief (regressions ‖ security ‖ code-quality ‖ product-honesty) + artifact probes; --findings classifies a fed-back review into a fail-closed ready|blocked hand-off (only cross-validated BLOCKER/HIGH count) and writes features/<slug>/10_delivery_review.md; --strict exits 1 on blocked
|
|
1405
1574
|
dz skills-verify [--dir <project>] [--expect a,b] [--static] [--strict] [--timeout <s>] [--json] # does .claude/skills/ actually REGISTER? --static = instant layout scan (CI-safe, no session): flags dirs that can never register; default also starts a real session and reads the authoritative system/init listing. exit 0 pass / 1 fail / 2 inconclusive — an unobservable registration is NEVER a pass
|
|
@@ -1422,10 +1591,12 @@ dz release [--filter <name>] [--affected] [--audit-dev] [--tag] [--pub
|
|
|
1422
1591
|
dz auto-canonicalize --source <github-url> --pack <skills-pack>
|
|
1423
1592
|
dz sync-upstream [--package <dir>] [--list] [--all]
|
|
1424
1593
|
dz drift-check [--all] [--json] [--project <dir>] # CI gate: exit 1 on NEW shared-skill drift (baseline: .dz/drift-allowlist.json; --all incl .claude dogfood)
|
|
1594
|
+
dz agents-sync [--check] [--json] [--project <dir>] # sync anchored bearing rules into the root AGENTS.md policy fence; exit 0 sync / 1 drift / 3 inconclusive
|
|
1595
|
+
dz hooks-sync --target codex [--check] [--remove] [--json] # install + ARM the dz veto/recall hooks in $CODEX_HOME/hooks.json; exit 0 armed+trusted / 1 not armed / 3 inconclusive
|
|
1425
1596
|
dz sync-canonical <skill> [--check] [--from <dir>] [--auto] [--project <dir>] # heal every copy from skills-meta/<skill> or --from; no canonical + --check = compare copies to each other (exit 1 on drift); no canonical + write = refuse unless --auto (LOUD, picks most-complete copy); --check writes nothing
|
|
1426
1597
|
dz scout [--topics <list>] [--since <date>] [--deep] [--output <file>] [--diff] [--report]
|
|
1427
1598
|
dz workflow init --name <n> [--pattern pipeline|barrier|fanout|gate] [--o <plan.json>] | validate <plan.json> [--json] | render <plan.json> --o <script.js> [--check] [--force] | blobs [--check] # loop-plan/1 authoring (the ADR-005 templates are retired)
|
|
1428
|
-
dz workflow-lint <script.js> [--plan <plan.json>] [--require-plan|--legacy] [--json] #
|
|
1599
|
+
dz workflow-lint <script.js> [--plan <plan.json>] [--require-plan|--legacy] [--json] # 18-rule deterministic gate; exit 0/1/3 — inconclusive is never a pass
|
|
1429
1600
|
dz workflow-trace <runDir|--slug <s>|--run <id>> [--invariants <plan.json>] [--html <out.html>] [--json] # timeline + SEQ invariant runner over the loop's own trace.jsonl
|
|
1430
1601
|
dz workflow-trace export <run> --o <file> [--include-pairs --yes] [--strict] # one run's telemetry as ONE movable file
|
|
1431
1602
|
dz workflow-trace import <bundle> --into <root> [--force] [--with-pairs] # reconstruct that run; fail-closed against clobbering
|
|
@@ -1440,6 +1611,44 @@ dz import-ecc [--local-path <dir>] [--select id,id,...] [--limit N] [--out
|
|
|
1440
1611
|
dz help
|
|
1441
1612
|
```
|
|
1442
1613
|
|
|
1614
|
+
## Global: `dz --version` / `-v` / `dz version`
|
|
1615
|
+
|
|
1616
|
+
```bash
|
|
1617
|
+
dz --version # 0.4.8
|
|
1618
|
+
dz --version --json # {"name":"dz","version":"0.4.8","node":"v22.22.0","schemas":{"loopPlan":"loop-plan/1"}}
|
|
1619
|
+
```
|
|
1620
|
+
|
|
1621
|
+
One line, exit 0. Unresolvable ⇒ the literal `unknown` and exit **1** — never a fabricated number,
|
|
1622
|
+
and never a zero exit for "I could not tell you".
|
|
1623
|
+
|
|
1624
|
+
This is a pre-dispatch GLOBAL FLAG, not a 67th command: the count above is unchanged, and a test
|
|
1625
|
+
derives it from the rendered `dz --help` command list so a reformat cannot move it silently.
|
|
1626
|
+
|
|
1627
|
+
**Why it exists.** `dz --version` used to print the entire USAGE manual and exit 0 (MEASURED
|
|
1628
|
+
2026-08-17 on 0.4.5 — reproducer: `node dist/bin.js --version` before this change). Any wrapper
|
|
1629
|
+
guarding a version range — `@dzhechkov/loop-designer-plugin` is the first — would read exit 0 as "it
|
|
1630
|
+
answered me" while finding no version to parse, and then call a possibly-stale binary. Recognised
|
|
1631
|
+
only as the FIRST argument, so a later positional `-v` still belongs to its subcommand.
|
|
1632
|
+
|
|
1633
|
+
## `dz skills-verify` also sees SLASH COMMANDS now
|
|
1634
|
+
|
|
1635
|
+
```bash
|
|
1636
|
+
# does a plugin's skill AND its five commands actually register?
|
|
1637
|
+
dz skills-verify --dir /tmp/probe --plugin-dir packages/@dzhechkov/loop-designer-plugin \
|
|
1638
|
+
--expect loop-designer:loop-plan-author \
|
|
1639
|
+
--expect-commands loop-designer:init,loop-designer:validate,loop-designer:render,loop-designer:lint,loop-designer:trace
|
|
1640
|
+
```
|
|
1641
|
+
|
|
1642
|
+
- `--plugin-dir <dir>` loads a plugin into the probe session (session-scoped, no marketplace). With
|
|
1643
|
+
no `--expect-commands`, the expectation DEFAULTS to the manifest's own `commands[]`; an unreadable
|
|
1644
|
+
manifest is refused rather than defaulted to an empty (vacuously passing) expectation.
|
|
1645
|
+
- `--expect-commands a,b` names the slash commands that must appear in the authoritative listing.
|
|
1646
|
+
- An **absent** `slash_commands` key is `inconclusive`, never an empty list — schema drift and "your
|
|
1647
|
+
commands did not load" are different facts and must not be collapsed.
|
|
1648
|
+
- `--static` now also PRINTS its advisories. A `.claude-plugin/plugin.json` under `.claude/skills/`
|
|
1649
|
+
previously produced `no layout problems found` and nothing else; the shape most likely to be a
|
|
1650
|
+
silent non-registration was invisible in the mode CI runs. It is reported, and still never fatal.
|
|
1651
|
+
|
|
1443
1652
|
### Grounding: three tiers + the token trade-off (`dz brain ground` / `dz brain expand`)
|
|
1444
1653
|
|
|
1445
1654
|
The `dz brain ground` hook fires on **every turn**, so what it injects is a token trade-off. There are
|
|
@@ -2011,6 +2220,78 @@ dz sync-upstream --package packages/@dzhechkov/skills-devops # check one packag
|
|
|
2011
2220
|
|
|
2012
2221
|
Discovers all skill packs with `sources.json`, fetches SKILL.md from origin repos, reports which skills have upstream changes.
|
|
2013
2222
|
|
|
2223
|
+
### dz agents-sync — Codex starts with the repository's bearing rules
|
|
2224
|
+
|
|
2225
|
+
Use this after changing an anchored policy clause in `CLAUDE.md` or `.claude/rules/*.md`, and run
|
|
2226
|
+
the check form in CI. It updates only the `dz:policies` fence in the root `AGENTS.md`; authored
|
|
2227
|
+
content and the independent `dz:skills` fence remain untouched.
|
|
2228
|
+
|
|
2229
|
+
```console
|
|
2230
|
+
$ dz agents-sync
|
|
2231
|
+
dz agents-sync: wrote — 9 policy section(s), 8097 bytes (24.71% of 32768)
|
|
2232
|
+
|
|
2233
|
+
$ dz agents-sync --check
|
|
2234
|
+
dz agents-sync: in sync — 9 policy section(s), 8097 bytes (24.71% of 32768)
|
|
2235
|
+
```
|
|
2236
|
+
|
|
2237
|
+
Exit codes are **0** for synchronized, **1** for drift and **3** when fixed source evidence is
|
|
2238
|
+
missing or unreadable. `--check` never writes. Each section carries a 12-hex hash recomputed from
|
|
2239
|
+
its source anchor; this proves synchronization only — not that Codex read or obeyed the rule. The
|
|
2240
|
+
separate cold-start acceptance probe establishes runtime visibility.
|
|
2241
|
+
|
|
2242
|
+
### dz hooks-sync — Codex runs the same veto and recall hooks Claude Code does
|
|
2243
|
+
|
|
2244
|
+
**When to use it.** Once per machine, after `npm i -g @dzhechkov/harness-cli`, if you drive Codex as
|
|
2245
|
+
well as Claude Code. It installs two hooks into the **user-global** `$CODEX_HOME/hooks.json`
|
|
2246
|
+
(default `~/.codex/hooks.json`) and **arms** them — Codex hooks are trust-gated, and an untrusted
|
|
2247
|
+
entry is silently never run. Re-run it after a dz upgrade; it is byte-idempotent, so an unchanged
|
|
2248
|
+
install rewrites nothing and the hook keeps its trust.
|
|
2249
|
+
|
|
2250
|
+
```console
|
|
2251
|
+
$ dz hooks-sync --target codex
|
|
2252
|
+
dz hooks-sync: codex hooks installed and ARMED (trust: trusted) — ready
|
|
2253
|
+
|
|
2254
|
+
$ dz hooks-sync --target codex --check
|
|
2255
|
+
dz hooks-sync: codex hooks installed and ARMED (trust: trusted) — ready
|
|
2256
|
+
|
|
2257
|
+
$ dz hooks-sync --target codex --remove
|
|
2258
|
+
dz hooks-sync: removed 2 managed entr(ies) from /root/.codex/hooks.json
|
|
2259
|
+
```
|
|
2260
|
+
|
|
2261
|
+
Exit codes are **0** for armed **and** trusted, **1** for not-armed / drift / a refusal, and **3**
|
|
2262
|
+
when the answer is inconclusive (including "no `codex` binary on PATH", where dz writes **nothing**).
|
|
2263
|
+
`--check` writes nothing and is **silent** in a home that never opted in.
|
|
2264
|
+
|
|
2265
|
+
**What the two hooks do.**
|
|
2266
|
+
|
|
2267
|
+
| Hook | Event | Behaviour |
|
|
2268
|
+
|---|---|---|
|
|
2269
|
+
| `dz-codex-veto.cjs` | `PreToolUse` | judges the shell command against one rule, `ssh-explicit-auth-weakening` |
|
|
2270
|
+
| `dz-codex-recall.cjs` | `UserPromptSubmit` | injects matching learned lessons and records the use with `runtime: "codex"` |
|
|
2271
|
+
|
|
2272
|
+
**The veto WARNS by default and never blocks.** A hit prints `DZ-VETO-WARN:` and exits 0. Enforcement
|
|
2273
|
+
is opt-in **per project**:
|
|
2274
|
+
|
|
2275
|
+
```console
|
|
2276
|
+
$ cat .dz/config.json
|
|
2277
|
+
{"hooks": {"shellVeto": "block"}} # off | warn (default) | block
|
|
2278
|
+
```
|
|
2279
|
+
|
|
2280
|
+
Only then does a hit exit 2 and stop the command. The rule fires only on tokens by which the command
|
|
2281
|
+
*explicitly* asks for weaker ssh authentication — `sshpass`, `-o PasswordAuthentication=yes`,
|
|
2282
|
+
`-o PubkeyAuthentication=no`, `-o PreferredAuthentications=…password…`. A bare `ssh myhost` whose
|
|
2283
|
+
identity comes from `~/.ssh/config` or `ssh-agent` is **allowed**: this guard is user-global, so a
|
|
2284
|
+
rule that blocks the normal secure case is not a guard, it is an outage.
|
|
2285
|
+
|
|
2286
|
+
**Radius.** Both helpers are INERT outside an opted-in dz project — the activation marker is a `.dz`
|
|
2287
|
+
directory, not `.git`. In a plain git checkout they take no decision, print nothing, and create
|
|
2288
|
+
nothing.
|
|
2289
|
+
|
|
2290
|
+
**Removal is conservative.** `--remove` deletes only entries whose command hash is recorded in dz's
|
|
2291
|
+
own manifest. An entry that merely *looks* like dz's is kept and reported — dz never deletes what it
|
|
2292
|
+
cannot prove it wrote. Foreign entries are preserved byte-for-byte by every operation, and a
|
|
2293
|
+
`hooks.json.bak-<ISO>` copy (newest 3 kept) is taken before each modifying write.
|
|
2294
|
+
|
|
2014
2295
|
### dz drift-check / dz sync-canonical — intra-monorepo skill-drift guard
|
|
2015
2296
|
|
|
2016
2297
|
**What.** The same skill is physically duplicated across many packages (`packages/@dzhechkov/*/<skill>/` + `.claude/skills/<skill>/`). These two commands make that duplication safe:
|
|
@@ -2684,23 +2965,56 @@ feature-adr Step-8 asserts the ADR's load-bearing safety property **has** a test
|
|
|
2684
2965
|
false green — it may never exercise the property, so it would stay green even if the property regressed. The
|
|
2685
2966
|
`§42` gate (learned from rUv's `cve-bench/evaluate.mjs`) proves the test **discriminates**: it runs the property
|
|
2686
2967
|
test in a throwaway git worktree at the pre-feature base (no fix) and requires it to go **red**.
|
|
2968
|
+
|
|
2969
|
+
**Use it when** you are about to accept "the property has a test" as evidence — in Step-8 QE, in a review of
|
|
2970
|
+
someone else's fix, or before trusting a regression test you did not write. Run it against `HEAD` while your
|
|
2971
|
+
change is still uncommitted; that is what makes `HEAD` the pre-feature base.
|
|
2972
|
+
|
|
2687
2973
|
```bash
|
|
2688
2974
|
# the Step-7 feature diff is uncommitted mid-pipeline, so HEAD is the pre-feature base
|
|
2689
2975
|
dz discrimination-check --test packages/x/test/auth-property.test.ts --base HEAD --json
|
|
2976
|
+
|
|
2977
|
+
# human output, a longer suite, and a runner that is not vitest
|
|
2978
|
+
dz discrimination-check --test packages/x/test/auth-property.test.ts \
|
|
2979
|
+
--base HEAD --runner "node --test" --timeout 600000
|
|
2690
2980
|
```
|
|
2691
2981
|
```
|
|
2692
2982
|
discrimination-check @ HEAD — verdict: NON_DISCRIMINATING
|
|
2693
2983
|
✗ packages/x/test/auth-property.test.ts: NON_DISCRIMINATING
|
|
2984
|
+
measurementValid: true · primaryAction: strengthen-test
|
|
2694
2985
|
|
|
2695
2986
|
[high] non-discriminating property test (false green)
|
|
2696
|
-
1 property test(s) PASS at pre-feature base — they do not exercise the ADR safety
|
|
2987
|
+
1 property test(s) PASS at pre-feature base WITH execution evidence — they do not exercise the ADR safety
|
|
2988
|
+
property and would stay green if the fix regressed … Action: strengthen-test. (Advisory — the pipeline
|
|
2989
|
+
continues; the owner decides.)
|
|
2697
2990
|
```
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2991
|
+
|
|
2992
|
+
**Every verdict is gated on EXECUTION evidence.** The gate reads the runner's own output shape (vitest /
|
|
2993
|
+
node --test) and requires it to demonstrate that the *named* test actually ran. An outcome nobody can prove
|
|
2994
|
+
degrades loudly instead of minting trust — MEASURED before this change, `--runner false` (a command that
|
|
2995
|
+
executes nothing and prints nothing) returned `DISCRIMINATES`; it now returns `CANNOT_ISOLATE` with
|
|
2996
|
+
reason `unrecognised-runner-output`.
|
|
2997
|
+
|
|
2998
|
+
| Verdict | Means | ✓/✗ | Action |
|
|
2999
|
+
|---|---|---|---|
|
|
3000
|
+
| `DISCRIMINATES` | assertion-red at base, execution-evidenced | ✓ | none |
|
|
3001
|
+
| `DISCRIMINATES_VIA_ERROR` | evidenced load error at base **and** an evidenced pass at TIP | ✓ | none (inference — note it) |
|
|
3002
|
+
| `NON_DISCRIMINATING` | evidenced pass at base — a proven false green | ✗ | `strengthen-test` |
|
|
3003
|
+
| `TEST_FILE_ABSENT` | the named check is not a regular file (stat+isFile, before any worktree) | ✗ | `create-missing-test` |
|
|
3004
|
+
| `LOAD_ERROR_AT_BOTH_REVS` | could not execute at EITHER rev — zero signal | ✗ | `fix-runner-invocation` |
|
|
3005
|
+
| `FAILS_AT_TIP` | the feature's own test is red **with** the feature present | ✗ | `fix-red-feature-test` |
|
|
3006
|
+
| `CANNOT_ISOLATE` | no established observation; the row carries a typed `reason` | ✗ | `map-a-test` / `fix-runner-invocation` |
|
|
3007
|
+
|
|
3008
|
+
`--json` carries the full reading: `perTest[]` (verdict + `reason`), the per-run `evidence` rows, `findings[]`
|
|
3009
|
+
(**one per distinct non-clean verdict** — the scalar `aggregate` can only name the worst), `measurementValid`
|
|
3010
|
+
(`true | false | 'partial'` — did the instrument measure at all), `primaryAction`, and `tipTree` (the live
|
|
3011
|
+
tree's HEAD + dirty-file count when a tip control ran). The singular `finding` is a **deprecated** alias for
|
|
3012
|
+
`findings[0]`; read `findings[]`. `--timeout <ms>` (default 300000) bounds each run — a timed-out run is
|
|
3013
|
+
`CANNOT_ISOLATE` reason `timeout`, never a pass.
|
|
3014
|
+
|
|
3015
|
+
It **never auto-aborts** (dz's rule: a false gate kills trust) — exit 0 on any verdict, exit 2 only on a
|
|
3016
|
+
usage/setup error. Base ref, paths, name filter, and runner are all injection-checked, and the worktree is
|
|
3017
|
+
always removed. Step-8 runs this on the ADR Confirmation's `Required automated check` automatically.
|
|
2704
3018
|
|
|
2705
3019
|
### `dz guard` — when a self-mutating operation should be refused, not regretted
|
|
2706
3020
|
|
|
@@ -3434,7 +3748,20 @@ npx @dzhechkov/p-replicator init
|
|
|
3434
3748
|
|
|
3435
3749
|
## Status
|
|
3436
3750
|
|
|
3437
|
-
`v0.4.
|
|
3751
|
+
`v0.4.8` — staged (not yet published). Also available as [Claude Plugin](#claude-plugin). Part of [DZ Harness Hub](https://github.com/djd1m/dz-harness-hub).
|
|
3752
|
+
|
|
3753
|
+
New in 0.4.8 (feature `crossrt-1-agents-md`): `dz agents-sync` ports the fixed registry of bearing
|
|
3754
|
+
rules into an early root-`AGENTS.md` fence, `--check` exposes source drift to CI, and both surfaces
|
|
3755
|
+
report the measured Codex project-doc byte budget. A live cold-start probe, not file presence,
|
|
3756
|
+
remains the runtime acceptance gate.
|
|
3757
|
+
|
|
3758
|
+
New in this change (feature `dz-cli-defects`, slice A — three defects confirmed by RUNNING the CLI, then fixed):
|
|
3759
|
+
|
|
3760
|
+
- **`dz list` skips and collects** — one unparseable `SKILL.md` no longer hides the rest; the broken files are named on stderr and the exit code stays 1. Same for `dz init` / `dz install` / `dz sync`. [Details](#dz-list--one-broken-skill-never-hides-the-rest)
|
|
3761
|
+
- **`--target` aliases + did-you-mean** — `--target claude` (and `cc`, `agents`, `gpt`/`openai`) resolve; typos are suggested, never silently accepted. [Details](#--target-aliases-and-did-you-mean)
|
|
3762
|
+
- **A named refusal instead of a `SyntaxError`** — `dz` now requires `@dzhechkov/harness-core >= 0.4.7` (was `^0.4.0`, which npm could legally resolve to a core too old to link) and says so in words, before anything is imported.
|
|
3763
|
+
|
|
3764
|
+
Previously: the global `dz --version` / `-v` / `dz version` surface (one parseable line), and `dz skills-verify --plugin-dir` / `--expect-commands` so slash-command registration is gate-visible. Both exist for `@dzhechkov/loop-designer-plugin`, which requires `dz` in `^0.4`, verifies it at run time, and falls back to `npx -y @dzhechkov/harness-cli@^0.4` when the `dz` on PATH is stale, unparseable or missing.
|
|
3438
3765
|
|
|
3439
3766
|
## Claude Plugin
|
|
3440
3767
|
|
package/dist/bin.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* `dz` executable entry point.
|
|
4
|
+
*
|
|
5
|
+
* Two phases, and the split is load-bearing (feature dz-cli-defects, D5):
|
|
6
|
+
*
|
|
7
|
+
* phase 1 — ZERO `@dzhechkov/harness-core` imports: probe the installed core version
|
|
8
|
+
* and refuse with a NAMED message if it is below `MIN_CORE`;
|
|
9
|
+
* phase 2 — `await import('./cli.js')`, which is where the ~100-name static graph is
|
|
10
|
+
* linked. A STATIC import here would link that graph before any guard could
|
|
11
|
+
* run, which is exactly how a cached lower core produced a bare
|
|
12
|
+
* `SyntaxError: … does not provide an export named 'GRADE_SUCCESS_FLOOR'`
|
|
13
|
+
* with nothing pointing at the cause.
|
|
4
14
|
*/
|
|
5
15
|
export {};
|
|
6
16
|
//# sourceMappingURL=bin.d.ts.map
|
package/dist/bin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG"}
|
package/dist/bin.js
CHANGED
|
@@ -1,17 +1,50 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* `dz` executable entry point.
|
|
4
|
+
*
|
|
5
|
+
* Two phases, and the split is load-bearing (feature dz-cli-defects, D5):
|
|
6
|
+
*
|
|
7
|
+
* phase 1 — ZERO `@dzhechkov/harness-core` imports: probe the installed core version
|
|
8
|
+
* and refuse with a NAMED message if it is below `MIN_CORE`;
|
|
9
|
+
* phase 2 — `await import('./cli.js')`, which is where the ~100-name static graph is
|
|
10
|
+
* linked. A STATIC import here would link that graph before any guard could
|
|
11
|
+
* run, which is exactly how a cached lower core produced a bare
|
|
12
|
+
* `SyntaxError: … does not provide an export named 'GRADE_SUCCESS_FLOOR'`
|
|
13
|
+
* with nothing pointing at the cause.
|
|
4
14
|
*/
|
|
5
|
-
import {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
import { checkCoreCompat, describeMissingExportError, resolveInstalledCoreVersion, MIN_CORE } from './core-compat.js';
|
|
16
|
+
const foundCore = resolveInstalledCoreVersion(import.meta.url);
|
|
17
|
+
const compat = checkCoreCompat({ found: foundCore, min: MIN_CORE });
|
|
18
|
+
if (!compat.ok) {
|
|
19
|
+
// stderr, and no stack: the user needs one actionable line, not a trace.
|
|
20
|
+
console.error(compat.message);
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
let code;
|
|
25
|
+
try {
|
|
26
|
+
const { runCli } = await import('./cli.js');
|
|
27
|
+
code = await runCli(process.argv.slice(2));
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
// The version probe fails OPEN, so a missing-binding link error can still reach us.
|
|
31
|
+
// Translate exactly that class into the named form; re-throw everything else
|
|
32
|
+
// unchanged so real bugs still surface.
|
|
33
|
+
const named = describeMissingExportError(error, foundCore);
|
|
34
|
+
if (named === null)
|
|
35
|
+
throw error;
|
|
36
|
+
console.error(named);
|
|
37
|
+
code = 1;
|
|
38
|
+
}
|
|
39
|
+
// `process.exit()` here TRUNCATED large output on a pipe, silently and at exactly the
|
|
40
|
+
// pipe buffer size. On a pipe (not a TTY, not a file) Node's stdout is ASYNCHRONOUS, so
|
|
41
|
+
// `process.exit` discards whatever has not flushed yet: `dz recall --all --json > file`
|
|
42
|
+
// wrote 122826 bytes while `dz recall --all --json | jq` got exactly 65536 and a parse
|
|
43
|
+
// error. That is data loss in the documented sharing path, and silent — the exit code
|
|
44
|
+
// was 0 and the JSON simply stopped mid-string.
|
|
45
|
+
//
|
|
46
|
+
// So: set the code and let the process end when the event loop drains, which is what
|
|
47
|
+
// flushes stdout. `process.exitCode` preserves the status without the race.
|
|
48
|
+
process.exitCode = code;
|
|
49
|
+
}
|
|
17
50
|
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEtH,MAAM,SAAS,GAAG,2BAA2B,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/D,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;AAEpE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;IACf,yEAAyE;IACzE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;KAAM,CAAC;IACN,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oFAAoF;QACpF,6EAA6E;QAC7E,wCAAwC;QACxC,MAAM,KAAK,GAAG,0BAA0B,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC3D,IAAI,KAAK,KAAK,IAAI;YAAE,MAAM,KAAK,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,GAAG,CAAC,CAAC;IACX,CAAC;IAED,sFAAsF;IACtF,wFAAwF;IACxF,wFAAwF;IACxF,uFAAuF;IACvF,sFAAsF;IACtF,gDAAgD;IAChD,EAAE;IACF,qFAAqF;IACrF,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
export interface CliIo {
|
|
8
8
|
readonly cwd?: string;
|
|
9
9
|
readonly write?: (line: string) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Diagnostics sink — **stderr**, defaulting to `console.error`.
|
|
12
|
+
*
|
|
13
|
+
* Before feature dz-cli-defects `CliIo` had no stderr seam at all, so every
|
|
14
|
+
* diagnostic (including the top-level error handler) landed on stdout and
|
|
15
|
+
* `dz list > skills.txt` wrote the error INTO the data file. `write` stays "data
|
|
16
|
+
* only"; `writeErr` is "diagnosis only".
|
|
17
|
+
*
|
|
18
|
+
* There is deliberately **no** fall-back to `write`: a test that wants to assert on
|
|
19
|
+
* stderr must inject `writeErr`, or the assertion would be theatre.
|
|
20
|
+
*/
|
|
21
|
+
readonly writeErr?: (line: string) => void;
|
|
10
22
|
/**
|
|
11
23
|
* Pre-read STDIN content (injectable so `dz brain ground`'s hook path is testable without
|
|
12
24
|
* an actual pipe). When omitted, the CLI reads fd 0 synchronously — but only for the one
|
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;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAsdH,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;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAED,yFAAyF;AACzF,MAAM,MAAM,iBAAiB,GAAG,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KACvD;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAilS9E,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,KAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAgM5E"}
|