@dzhechkov/harness-cli 0.3.235 → 0.3.237
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 +10 -42
- package/README.md +72 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +242 -3
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
- package/sbom.json +9 -89
- package/src/cli.ts +241 -2
package/.dz-manifest.json
CHANGED
|
@@ -3,53 +3,21 @@
|
|
|
3
3
|
"version": 1,
|
|
4
4
|
"pack": "harness-cli",
|
|
5
5
|
"files": [
|
|
6
|
-
{
|
|
7
|
-
"path": ".agentic-qe/brain.rvf",
|
|
8
|
-
"sha256": "8136cd4cc145d3dbe6ed3ae4489946bbc26e3e44172f0e5241ac45dde38bfead"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"path": ".agentic-qe/brain.rvf.lock",
|
|
12
|
-
"sha256": "99fa5178a48b6953b8f3a6f1690204a3b5449004b7dd105e7a3155ad3658266c"
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"path": ".agentic-qe/memory.db",
|
|
16
|
-
"sha256": "456372cb9a8c12f98ae6378338b8469d9be6df05cbe03a99b412d83d962b3d11"
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"path": ".agentic-qe/memory.db-shm",
|
|
20
|
-
"sha256": "cab99dd5d4068013a0c5f4f1c2d29dbec07729dc47c1d77adba6a53b773d0026"
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"path": ".agentic-qe/memory.db-wal",
|
|
24
|
-
"sha256": "2cc80ec378c1f9cd2588676588ee1b73bfe4f2f7ef3b96879c295eb86dccd2c2"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"path": ".agentic-qe/patterns.rvf",
|
|
28
|
-
"sha256": "9090b2e6d339eaa183672ac0cf9f625dbd5f9fc76d64afcdb34a3f5871c31c5a"
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"path": ".agentic-qe/patterns.rvf.idmap.json",
|
|
32
|
-
"sha256": "c2693f9a7f47a2d2bffe3004188e70ce08411bf8db47d07c60551d18ff7640c4"
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"path": ".agentic-qe/patterns.rvf.lock",
|
|
36
|
-
"sha256": "84842f3916c558b1f4f2da2a5b0236587f146dda1f6ab4ba4c31ed7b8b17f943"
|
|
37
|
-
},
|
|
38
6
|
{
|
|
39
7
|
"path": "CHANGELOG.md",
|
|
40
8
|
"sha256": "9555ead768fef7963e735b0c6af21a64412811531534108be3df61bc65b51021"
|
|
41
9
|
},
|
|
42
10
|
{
|
|
43
11
|
"path": "README.md",
|
|
44
|
-
"sha256": "
|
|
12
|
+
"sha256": "7e8b772a6fa9ca0f36364cafd5ea996abeb62dc894c2f67f50ea7704a7a8824d"
|
|
45
13
|
},
|
|
46
14
|
{
|
|
47
15
|
"path": "coverage/coverage-final.json",
|
|
48
|
-
"sha256": "
|
|
16
|
+
"sha256": "667bf610bf890a7b93480a4b1045e98dc0c765effd80b78fde4e48538f595b3e"
|
|
49
17
|
},
|
|
50
18
|
{
|
|
51
19
|
"path": "coverage/coverage-summary.json",
|
|
52
|
-
"sha256": "
|
|
20
|
+
"sha256": "593705e81f851c0e65ffa9feaa9bbd396e7a3295b9b21076cfd953ee5a05b93a"
|
|
53
21
|
},
|
|
54
22
|
{
|
|
55
23
|
"path": "dist/bin.d.ts",
|
|
@@ -73,15 +41,15 @@
|
|
|
73
41
|
},
|
|
74
42
|
{
|
|
75
43
|
"path": "dist/cli.d.ts.map",
|
|
76
|
-
"sha256": "
|
|
44
|
+
"sha256": "cf6a3265890a8856ef31e3e7ac58026c15232c3c118ba0fcd1ce0d7590b84dd8"
|
|
77
45
|
},
|
|
78
46
|
{
|
|
79
47
|
"path": "dist/cli.js",
|
|
80
|
-
"sha256": "
|
|
48
|
+
"sha256": "b9af9be1bd31acd60e76275ff1055dd8e9b39b531b0c375467648f142b74d2c4"
|
|
81
49
|
},
|
|
82
50
|
{
|
|
83
51
|
"path": "dist/cli.js.map",
|
|
84
|
-
"sha256": "
|
|
52
|
+
"sha256": "6a51963ede51129e43524d62f3d757255a002dfec3df2c1dfa519af6f235a667"
|
|
85
53
|
},
|
|
86
54
|
{
|
|
87
55
|
"path": "dist/index.d.ts",
|
|
@@ -105,7 +73,7 @@
|
|
|
105
73
|
},
|
|
106
74
|
{
|
|
107
75
|
"path": "package.json",
|
|
108
|
-
"sha256": "
|
|
76
|
+
"sha256": "1e7ef1d6e0796144999ad64d3650aeb4a2ccc7dfc66c5c5a8b705d783a9d0801"
|
|
109
77
|
},
|
|
110
78
|
{
|
|
111
79
|
"path": "src/bin.ts",
|
|
@@ -113,7 +81,7 @@
|
|
|
113
81
|
},
|
|
114
82
|
{
|
|
115
83
|
"path": "src/cli.ts",
|
|
116
|
-
"sha256": "
|
|
84
|
+
"sha256": "5180330ac6612542c80a74ea8e0983f5cd231e95bb3962eccdd65fbdbf6611a8"
|
|
117
85
|
},
|
|
118
86
|
{
|
|
119
87
|
"path": "src/index.ts",
|
|
@@ -121,7 +89,7 @@
|
|
|
121
89
|
},
|
|
122
90
|
{
|
|
123
91
|
"path": "test/cli.test.ts",
|
|
124
|
-
"sha256": "
|
|
92
|
+
"sha256": "461beed08ad6cfde7bbf559701fcbc6978f622c3951c80463c4e4943c538eff5"
|
|
125
93
|
},
|
|
126
94
|
{
|
|
127
95
|
"path": "tsconfig.json",
|
|
@@ -133,5 +101,5 @@
|
|
|
133
101
|
}
|
|
134
102
|
]
|
|
135
103
|
},
|
|
136
|
-
"signature": "
|
|
104
|
+
"signature": "06gdM99WpJhmarOtUFoeMAlGAfAvCboh/QGbCEIBhMAqgLn5rnSCXAb2023QdO+hZsuxrijyGzgBh62l/L+GBQ=="
|
|
137
105
|
}
|
package/README.md
CHANGED
|
@@ -372,6 +372,74 @@ the release job gets a perfectly attested malicious package.
|
|
|
372
372
|
A ready-to-install workflow is at `features/publish-provenance/07_code_changes/publish.yml`; copy it to
|
|
373
373
|
`.github/workflows/` and add an `NPM_TOKEN` secret.
|
|
374
374
|
|
|
375
|
+
### Target parity — `dz parity` (the honest feature × target map)
|
|
376
|
+
|
|
377
|
+
The harness runs on 10 targets, but not every feature runs everywhere: hooks, MCP (Model Context
|
|
378
|
+
Protocol) and the Workflow runtime exist only on some platforms. `dz parity` answers "what do I
|
|
379
|
+
actually get on X?" from a COMPUTED capability model — the matrix is never hand-written (a
|
|
380
|
+
hand-maintained table is a drift surface; the model lives next to the code, under tests that
|
|
381
|
+
refuse an unclassified 11th target).
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
dz parity # the full grid: ✓ full / ◐ manual (via which form) / — absent
|
|
385
|
+
dz parity --target codex # one target in detail: what works, THROUGH what
|
|
386
|
+
dz parity --json # machine contract (targets, capabilities, per-cell level + via)
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Example (real output, trimmed):
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
dz parity — codex (capabilities: shell, skills, mcp)
|
|
393
|
+
✓ dz CLI (all commands) via shell command
|
|
394
|
+
◐ feature-adr pipeline via interactive skill (plain /feature-adr)
|
|
395
|
+
◐ Step-10 Delivery Gate via dz delivery-check (CLI 4-plane hand-off protocol)
|
|
396
|
+
◐ Integrity claim-check via dz claim-check (CLI) + publish gate
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
**When to use:** before promising a workflow to a teammate on Cursor/Codex/Hermes; when choosing
|
|
400
|
+
a target for a project; as the requirements input for porting a feature to more targets.
|
|
401
|
+
|
|
402
|
+
### Portable delivery gate — `dz delivery-check` (Step-10, on every shell target)
|
|
403
|
+
|
|
404
|
+
The feature-adr Step-10 Delivery Gate reviews a landed feature across four orthogonal planes and
|
|
405
|
+
emits a machine-checkable `ready | blocked` hand-off. On Claude-Code the ultracode workflow can run
|
|
406
|
+
it as the **opt-in** Step-10 (`args.deliveryGate: true` — off by default); `dz delivery-check` is
|
|
407
|
+
the **portable `manual` form** that travels to every shell
|
|
408
|
+
target (Cursor/Codex/Gemini/…). The CLI runs the deterministic parts (artifact probes, fail-closed
|
|
409
|
+
hand-off arithmetic, cross-validation bookkeeping) and **dispatches** the semantic review to the
|
|
410
|
+
target's own agent runtime — the `dz challenge` cartridge shape. It never posts anything anywhere
|
|
411
|
+
(findings-only).
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
dz delivery-check --slug my-feature --context-only # print artifact probes + the 4-plane review brief
|
|
415
|
+
dz delivery-check --slug my-feature --findings review.json # classify a fed-back review → writes 10_delivery_review.md, prints ready|blocked
|
|
416
|
+
dz delivery-check --slug my-feature --findings review.json --strict --json # CI gate: exit 1 on blocked, machine-readable result
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Example (trimmed):
|
|
420
|
+
|
|
421
|
+
```
|
|
422
|
+
dz delivery-check — my-feature: blocked
|
|
423
|
+
✓ 0 BLOCKER: PASS
|
|
424
|
+
✗ 0 HIGH: FAIL — 1 confirmed HIGH
|
|
425
|
+
✓ planes complete: PASS
|
|
426
|
+
✓ BLOCKER/HIGH cross-validated: PASS
|
|
427
|
+
✓ required artifacts present: PASS
|
|
428
|
+
↳ wrote features/my-feature/10_delivery_review.md
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
`ready` only off complete, cross-validated, clean evidence: a null/partial plane, a failed required
|
|
432
|
+
probe (the `07_code_changes/` manifest), a confirmed BLOCKER/HIGH, or an **un-cross-validated**
|
|
433
|
+
BLOCKER/HIGH (`cross-validation-incomplete`) all yield `blocked`. Classification reads only numeric
|
|
434
|
+
severity counts, so instruction-like text inside a finding cannot move the verdict.
|
|
435
|
+
|
|
436
|
+
**When to use:** as the final quality hand-off for a landed feature on any non-Claude-Code target;
|
|
437
|
+
as a CI gate (`--strict`) that fails a merge on an unresolved BLOCKER/HIGH.
|
|
438
|
+
|
|
439
|
+
For AGENTS.md-class targets, `dz feature-adr-setup --gates [--target <name>] --apply` emits a
|
|
440
|
+
zero-config `architecture/gates/delivery-check.md` whose runnable-here gate list is computed from
|
|
441
|
+
`dz parity` for that target (create-if-absent, never clobbered).
|
|
442
|
+
|
|
375
443
|
### Verified release — `dz release` (4 HARD gates in front of `dz publish`)
|
|
376
444
|
|
|
377
445
|
`dz publish` gates on guard / claim-check / signatures / provenance / files-whitelist — none of which
|
|
@@ -481,7 +549,7 @@ Get the whole set with `dz init --target claude-code --preset meta`, or pick one
|
|
|
481
549
|
|
|
482
550
|
> **A skill and its npx toolkit are not duplicates — they're a graduation.** Several skills (e.g. `feature-adr`, `design-thinking`) exist BOTH as a skill inside a `dz` preset AND as a standalone `npx` package. The preset's SKILL.md is **fully functional on its own** (the whole methodology — modules + references — travels with it, and it auto-activates by description), and it's the only way to compile that capability to the **non-Claude platforms** (Codex/OpenCode/Hermes/OpenClaude) via `dz`. The npx package adds **project-level runtime governance** around the same skill: a slash command, governance rules, a context shard, and (for feature-adr) reward-learning + `/harvest`. So: pick the **skill/preset** for a working capability across platforms; pick the **npx toolkit** when you want it as a governed, command-driven fixture of one project.
|
|
483
551
|
|
|
484
|
-
## All Commands (
|
|
552
|
+
## All Commands (57)
|
|
485
553
|
|
|
486
554
|
```
|
|
487
555
|
dz setup --target <name> [--preset <name>] [--select id,id,...] [--skills-dir <dir>] [--memory agentdb] [--no-memory] [--no-hooks] [--install-driver] [--force]
|
|
@@ -536,11 +604,13 @@ dz challenge --plan <plan.md> [--json] [--context-only] [--author <model>] # a
|
|
|
536
604
|
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)
|
|
537
605
|
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
|
|
538
606
|
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; a green is a false green (HIGH finding, advisory, never auto-aborts)
|
|
607
|
+
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
|
|
539
608
|
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
|
|
540
609
|
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
|
|
541
610
|
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)
|
|
542
611
|
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
|
|
543
612
|
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)
|
|
613
|
+
dz parity [--target <name>] [--json] # honest feature×target map COMPUTED from the capability model — full / manual (via which form) / absent, per target
|
|
544
614
|
dz release [--filter <name>] [--affected] [--audit-dev] [--tag] [--publish] [--json] [--dry-run] [--no-issue] # VERIFIED release: 4 HARD gates in front of dz publish — package test suites, pnpm audit --prod >=high (--audit-dev widens), node --check of every dist/bin file (unbuilt package with a build script ⇒ MISSING_DIST fail), bin smoke-boot "node <bin> --help" (temp cwd + timeout); --affected narrows to git-touched packages (fail-open); any red gate STOPS the release (exit 1) + best-effort gh issue; green ⇒ re-sign reminder, then the ready dz publish command (never with --yes injected)
|
|
545
615
|
dz auto-canonicalize --source <github-url> --pack <skills-pack>
|
|
546
616
|
dz sync-upstream [--package <dir>] [--list] [--all]
|
|
@@ -2101,7 +2171,7 @@ npx @dzhechkov/p-replicator init
|
|
|
2101
2171
|
|
|
2102
2172
|
## Status
|
|
2103
2173
|
|
|
2104
|
-
`v0.3.
|
|
2174
|
+
`v0.3.236` — published on npm. Also available as [Claude Plugin](#claude-plugin). Part of [DZ Harness Hub](https://github.com/djd1m/dz-harness-hub).
|
|
2105
2175
|
|
|
2106
2176
|
## Claude Plugin
|
|
2107
2177
|
|
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;AAuQH,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;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;CAC5C;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;AAo9K9E,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,KAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAkJ5E"}
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
9
9
|
import { execSync } from 'node:child_process';
|
|
10
10
|
import { homedir, tmpdir } from 'node:os';
|
|
11
11
|
import { createRequire } from 'node:module';
|
|
12
|
-
import { createSkill, getSkillInfo, getWorkflow, isTargetName, listSkills, runDoctor, runInit, benchmarkSkill, benchmarkSkills, scanMcp, reconcileCapabilities, RECONCILE_BANNER, buildRegistry, discoverSkillPackDirs, checkUpstream, compareSkills, checkAllUpstream, sweepSkillDrift, syncCanonicalSkill, checkUpgrades, discoverPackages, discoverSourcePackages, fetchAllDownloads, filterByCategory, pretrain, recommend, generatePlugin, publishPackages, runSetup, runMigrate, searchRegistry, runSync, runVerify, runInitAgentsMd, runInitGeminiMd, TARGET_NAMES, WORKFLOW_NAMES, importEcc, recordPattern, resolveLearningBackend, storeStats, consolidateSessions, pruneNoisePatterns, lessonDeltaReport, removePatternsByIds, snapshotStore, recallHybrid, teachGuard, mirrorPatternsToVector, vectorMirrorEnabled, vectorTierStatus, resolveVectorEngine, reindexVectorStore, harmonizeVectorStore, importRvfCheckpoint, statuslineData, writeFeatureAdrState, computeUsage, deriveUsageCalibration, normalizeClaudeUsageModelKey, readUsageLimits, claimCheck, summarize, queryBookKnowledge, loadStorePatternsSync, patternRecordId, loadStoreRecords, recordToPattern, bundleSkills, brainHome, listBrain, promoteProjectToBrain, updateBrainSource, queryBrain, groundPrompt, expandKu, reindexBrainVectors, buildPrimer, exportBrainSlice, importBrainSlice, registerKusToBrain, RECALL_USAGE_LOG_RELATIVE, RECALL_USAGE_LOG_MAX_BYTES, parseRecallUsageLog, buildRecallUsageReport, buildManifest, buildSbom, resolveTrustRoot, decideVerifyPolicy, generateSigningKeypair, evaluateGuard, resolveRules, auditRecord, guardExitCode, DEFAULT_RULES, decideProvenance, isInsideTree, signManifest, verifyManifest, listSignablePackFiles, assertKeyOutsideTree, decidePublishGate, collectPackageFacts, planReleaseGates, selectAffectedPackages, classifyGateExecutions, buildFailureIssue, buildReleaseNotes, releaseTagName, firstOutputLine, formatPublishError, MANIFEST_NAME, SBOM_NAME, buildArchitectureMap, renderMapHuman, findArchitectureDrift, renderDriftReport, scanWorkspacePackages, loadSubsystemManifest, loadProductVision, checkFeatureAgainstArchitecture, renderArchCheck, planProjectSkills, guidanceForStage, renderInjectionReport, analyzeCorpus, renderRakeReport, renderCriticSection, rakeAsLesson, rakeReward, DEFAULT_RAKE_THRESHOLDS, streamSessionEvents, findLatestTranscript, detectProcessRakes, buildRetro, renderRetro, retroLessonText, PROCESS_SIGNATURES, RETRO_DOMAIN, scanForSetup, buildSetupPlan, scaffoldFromSpec, renderScaffoldPreview, readExistingForScaffold, assembleChallengeContext, buildChallengeBrief, planDiscriminationCheck, classifyDiscrimination, pickAdversaryModel, CHALLENGE_QUESTIONS, loadOutcomes, renderOutcomes, statsForKey, selectAutoCost, recordProvisional, finalizeOutcome, COST_LADDER, splitScenarios, budgetPlan, selectWinner, proseScopeOk, renderProseDiff, readScenarioIds, DEFAULT_MAX_JUDGE_RUNS, } from '@dzhechkov/harness-core';
|
|
12
|
+
import { createSkill, getSkillInfo, getWorkflow, isTargetName, listSkills, runDoctor, runInit, benchmarkSkill, benchmarkSkills, scanMcp, reconcileCapabilities, RECONCILE_BANNER, buildRegistry, discoverSkillPackDirs, checkUpstream, compareSkills, checkAllUpstream, sweepSkillDrift, syncCanonicalSkill, checkUpgrades, discoverPackages, discoverSourcePackages, fetchAllDownloads, filterByCategory, pretrain, recommend, generatePlugin, publishPackages, runSetup, runMigrate, searchRegistry, runSync, runVerify, runInitAgentsMd, runInitGeminiMd, TARGET_NAMES, buildParityMatrix, TARGET_CAPABILITIES, TARGET_SHORT_LABELS, WORKFLOW_NAMES, importEcc, recordPattern, resolveLearningBackend, storeStats, consolidateSessions, pruneNoisePatterns, lessonDeltaReport, removePatternsByIds, snapshotStore, recallHybrid, teachGuard, mirrorPatternsToVector, vectorMirrorEnabled, vectorTierStatus, resolveVectorEngine, reindexVectorStore, harmonizeVectorStore, importRvfCheckpoint, statuslineData, writeFeatureAdrState, computeUsage, deriveUsageCalibration, normalizeClaudeUsageModelKey, readUsageLimits, claimCheck, summarize, queryBookKnowledge, loadStorePatternsSync, patternRecordId, loadStoreRecords, recordToPattern, bundleSkills, brainHome, listBrain, promoteProjectToBrain, updateBrainSource, queryBrain, groundPrompt, expandKu, reindexBrainVectors, buildPrimer, exportBrainSlice, importBrainSlice, registerKusToBrain, RECALL_USAGE_LOG_RELATIVE, RECALL_USAGE_LOG_MAX_BYTES, parseRecallUsageLog, buildRecallUsageReport, buildManifest, buildSbom, resolveTrustRoot, decideVerifyPolicy, generateSigningKeypair, evaluateGuard, resolveRules, auditRecord, guardExitCode, DEFAULT_RULES, decideProvenance, isInsideTree, signManifest, verifyManifest, listSignablePackFiles, assertKeyOutsideTree, decidePublishGate, collectPackageFacts, planReleaseGates, selectAffectedPackages, classifyGateExecutions, buildFailureIssue, buildReleaseNotes, releaseTagName, firstOutputLine, formatPublishError, MANIFEST_NAME, SBOM_NAME, buildArchitectureMap, renderMapHuman, findArchitectureDrift, renderDriftReport, scanWorkspacePackages, loadSubsystemManifest, loadProductVision, checkFeatureAgainstArchitecture, renderArchCheck, planProjectSkills, guidanceForStage, renderInjectionReport, analyzeCorpus, renderRakeReport, renderCriticSection, rakeAsLesson, rakeReward, DEFAULT_RAKE_THRESHOLDS, streamSessionEvents, findLatestTranscript, detectProcessRakes, buildRetro, renderRetro, retroLessonText, PROCESS_SIGNATURES, RETRO_DOMAIN, scanForSetup, buildSetupPlan, scaffoldFromSpec, renderScaffoldPreview, readExistingForScaffold, assembleChallengeContext, buildChallengeBrief, planDiscriminationCheck, classifyDiscrimination, pickAdversaryModel, CHALLENGE_QUESTIONS, loadOutcomes, renderOutcomes, statsForKey, selectAutoCost, recordProvisional, finalizeOutcome, COST_LADDER, splitScenarios, budgetPlan, selectWinner, proseScopeOk, renderProseDiff, readScenarioIds, DEFAULT_MAX_JUDGE_RUNS, collectDeliveryFacts, planDeliveryCheck, renderDeliveryBrief, classifyDelivery, isUsablePlaneResult, renderDeliveryReview, } from '@dzhechkov/harness-core';
|
|
13
13
|
import { getPreset, PRESET_NAMES } from '@dzhechkov/harness-presets';
|
|
14
14
|
import { scanGitHub, analyzeRepo, generateReport, deepAnalyze, scanAllSources, ScoutMemory } from '@dzhechkov/scout';
|
|
15
15
|
const USAGE = `dz - DZ cross-platform harness CLI
|
|
@@ -33,6 +33,8 @@ Usage:
|
|
|
33
33
|
dz verify-pack --pack <dir> [--pubkey <path>] (signature check; fail-closed; key from the repo, never the pack)
|
|
34
34
|
dz publish [--filter <name>] [--bump-only] [--claim-check <off|warn|error>] [--require-signing] [--provenance|--no-provenance] (dry-run by default; pass --yes/--confirm/--no-dry-run to go live; claim-check gate default warn — surfaces README claim findings, never blocks; error fails an offending package)
|
|
35
35
|
dz release [--filter <name>] [--tag] [--publish] [--json] [--dry-run] [--no-issue] (VERIFIED release: 4 HARD gates in FRONT of dz publish — full package test suites, audit >=high, node --check of every dist/bin file, bin smoke-boot via "node <bin> --help" — any red gate STOPS the release (exit 1) + best-effort gh issue; all green ⇒ re-sign reminder, then prints the ready dz publish command (or chains with --publish); never duplicates publish's own gates)
|
|
36
|
+
dz parity [--target <name>] [--json] (the honest feature×target map, COMPUTED from the capability model — which harness feature is full / manual / absent on each of the ${TARGET_NAMES.length} targets, and via which form)
|
|
37
|
+
dz delivery-check --slug <slug> [--context-only] [--findings <f.json>] [--strict] [--author <model>] [--json] (portable Step-10 Delivery Gate: prints the 4-plane review brief + artifact probes; --findings classifies a fed-back review into a fail-closed ready|blocked hand-off and writes features/<slug>/10_delivery_review.md; --strict exits 1 on blocked)
|
|
36
38
|
dz setup --target <name> [--preset <name>] [--select id,id,...] [--skills-dir <dir>] [--project <dir>] [--memory agentdb] [--no-memory] [--no-hooks] [--install-driver] [--force] [--enrich]
|
|
37
39
|
dz teach "<pattern>" [--reward <0-1>] [--domain <name>] [--type rule|success-pattern|lesson-learned] [--project <dir>] [--no-mirror] (--project pins the learned store to <dir>/.dz, not the cwd — pin to a canonical brain)
|
|
38
40
|
dz teach --from-json <file> [--project <dir>] [--no-mirror] (bulk-import a 'dz recall --all --json' export — share a learned store across machines)
|
|
@@ -3262,6 +3264,85 @@ function cmdPublish(options, flags, cwd, write) {
|
|
|
3262
3264
|
return report.errors > 0 ? 1 : 0;
|
|
3263
3265
|
}
|
|
3264
3266
|
/* ------------------------------------------------------------------ */
|
|
3267
|
+
/* dz parity — the honest feature×target map (target-parity-matrix, */
|
|
3268
|
+
/* ADR-001): computed from the declarative model, never hand-written */
|
|
3269
|
+
/* ------------------------------------------------------------------ */
|
|
3270
|
+
function cmdParity(options, flags, write) {
|
|
3271
|
+
const json = flags.has('json');
|
|
3272
|
+
if (flags.has('help')) {
|
|
3273
|
+
write('dz parity [--target <name>] [--json] — the computed feature×target map (never hand-written)');
|
|
3274
|
+
write(` targets: ${TARGET_NAMES.join(', ')}`);
|
|
3275
|
+
return 0;
|
|
3276
|
+
}
|
|
3277
|
+
const allowedFlags = new Set(['json', 'help']);
|
|
3278
|
+
const allowedOptions = new Set(['target']);
|
|
3279
|
+
// A stray positional is a typo'd invocation, not something to silently ignore (Codex QE gap 7).
|
|
3280
|
+
if (options.has('_positional_0')) {
|
|
3281
|
+
write(json ? JSON.stringify({ error: `unexpected argument "${options.get('_positional_0')}"`, exitCode: 1 }) : `dz parity: unexpected argument "${options.get('_positional_0')}"\n allowed: --target <name>, --json`);
|
|
3282
|
+
return 1;
|
|
3283
|
+
}
|
|
3284
|
+
for (const flag of flags) {
|
|
3285
|
+
if (!allowedFlags.has(flag)) {
|
|
3286
|
+
write(json ? JSON.stringify({ error: `unknown option --${flag}`, exitCode: 1 }) : `dz parity: unknown option --${flag}\n allowed: --target <name>, --json`);
|
|
3287
|
+
return 1;
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
for (const key of options.keys()) {
|
|
3291
|
+
if (key.startsWith('_positional_'))
|
|
3292
|
+
continue;
|
|
3293
|
+
if (!allowedOptions.has(key)) {
|
|
3294
|
+
write(json ? JSON.stringify({ error: `unknown option --${key}`, exitCode: 1 }) : `dz parity: unknown option --${key}\n allowed: --target <name>, --json`);
|
|
3295
|
+
return 1;
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
const matrix = buildParityMatrix();
|
|
3299
|
+
const target = options.get('target');
|
|
3300
|
+
if (target !== undefined && !TARGET_NAMES.includes(target)) {
|
|
3301
|
+
if (json)
|
|
3302
|
+
write(JSON.stringify({ error: `unknown target "${target}"`, targets: TARGET_NAMES, exitCode: 1 }, null, 2));
|
|
3303
|
+
else
|
|
3304
|
+
write(`dz parity: unknown target "${target}" — one of: ${TARGET_NAMES.join(', ')}`);
|
|
3305
|
+
return 1;
|
|
3306
|
+
}
|
|
3307
|
+
if (json) {
|
|
3308
|
+
const rows = matrix.map((r) => ({
|
|
3309
|
+
id: r.feature.id,
|
|
3310
|
+
title: r.feature.title,
|
|
3311
|
+
cells: target !== undefined ? { [target]: r.cells[target] } : r.cells,
|
|
3312
|
+
}));
|
|
3313
|
+
// A filtered response stays internally consistent: capabilities are filtered too (Codex QE gap 9).
|
|
3314
|
+
const caps = target !== undefined ? { [target]: TARGET_CAPABILITIES[target] } : TARGET_CAPABILITIES;
|
|
3315
|
+
write(JSON.stringify({ targets: target !== undefined ? [target] : TARGET_NAMES, capabilities: caps, features: rows }, null, 2));
|
|
3316
|
+
return 0;
|
|
3317
|
+
}
|
|
3318
|
+
if (target !== undefined) {
|
|
3319
|
+
const t = target;
|
|
3320
|
+
write(`\ndz parity — ${t} (capabilities: ${TARGET_CAPABILITIES[t].join(', ')})\n`);
|
|
3321
|
+
for (const r of matrix) {
|
|
3322
|
+
const c = r.cells[t];
|
|
3323
|
+
const icon = c.level === 'full' ? '✓' : c.level === 'manual' ? '◐' : '—';
|
|
3324
|
+
write(` ${icon} ${r.feature.title.padEnd(58)} ${c.level === 'none' ? 'not available on this target' : `via ${c.via ?? ''}`}`);
|
|
3325
|
+
}
|
|
3326
|
+
write('\n ✓ full (the complete experience) ◐ manual (works, you drive it by hand) — not available');
|
|
3327
|
+
return 0;
|
|
3328
|
+
}
|
|
3329
|
+
// Grid: one column per target, short header, one row per feature. Computed, never hand-written;
|
|
3330
|
+
// the labels live NEXT TO the model (a local map here would be a second, unchecked registry).
|
|
3331
|
+
const short = TARGET_SHORT_LABELS;
|
|
3332
|
+
write('\ndz parity — feature × target (computed from the model; dz parity --target <name> for detail)\n');
|
|
3333
|
+
write(` ${'feature'.padEnd(52)} ${TARGET_NAMES.map((t) => (short[t] ?? t).padStart(4)).join('')}`);
|
|
3334
|
+
for (const r of matrix) {
|
|
3335
|
+
const cells = TARGET_NAMES.map((t) => {
|
|
3336
|
+
const c = r.cells[t];
|
|
3337
|
+
return (c.level === 'full' ? '✓' : c.level === 'manual' ? '◐' : '—').padStart(4);
|
|
3338
|
+
}).join('');
|
|
3339
|
+
write(` ${r.feature.title.slice(0, 52).padEnd(52)} ${cells}`);
|
|
3340
|
+
}
|
|
3341
|
+
write('\n ✓ full ◐ manual (available, driven by hand) — not available');
|
|
3342
|
+
write(` columns: ${TARGET_NAMES.map((t) => `${short[t] ?? t}=${t}`).join(' ')}`);
|
|
3343
|
+
return 0;
|
|
3344
|
+
}
|
|
3345
|
+
/* ------------------------------------------------------------------ */
|
|
3265
3346
|
/* dz release — verified-release conveyor (feature release-verified, */
|
|
3266
3347
|
/* ADR-001): 4 HARD gates in FRONT of the untouched dz publish. */
|
|
3267
3348
|
/* ------------------------------------------------------------------ */
|
|
@@ -4825,8 +4906,17 @@ function cmdFeatureAdrSetup(options, flags, cwd, write) {
|
|
|
4825
4906
|
write('dz feature-adr-setup: --loc-cap must be a positive finite number');
|
|
4826
4907
|
return 1;
|
|
4827
4908
|
}
|
|
4909
|
+
// portable-gates (direction b): --gates scaffolds the zero-config architecture/gates/delivery-check.md.
|
|
4910
|
+
// Its "runnable here" list is computed for --target (default agents-md, the AGENTS.md-class target class).
|
|
4911
|
+
const wantGates = flags.has('gates');
|
|
4912
|
+
const targetOpt = options.get('target');
|
|
4913
|
+
if (targetOpt !== undefined && !isTargetName(targetOpt)) {
|
|
4914
|
+
write(`dz feature-adr-setup: --target must be one of: ${TARGET_NAMES.join(', ')}`);
|
|
4915
|
+
return 1;
|
|
4916
|
+
}
|
|
4917
|
+
const gatesTarget = isTargetName(targetOpt ?? '') ? targetOpt : 'agents-md';
|
|
4828
4918
|
const specPath = options.get('from-spec');
|
|
4829
|
-
if (specPath === undefined && !wantGuards) {
|
|
4919
|
+
if (specPath === undefined && !wantGuards && !wantGates) {
|
|
4830
4920
|
// default + --plan: the read-only "which documents, and where?" answer.
|
|
4831
4921
|
const plan = buildSetupPlan(scanForSetup(repoRoot));
|
|
4832
4922
|
if (flags.has('json')) {
|
|
@@ -4864,7 +4954,9 @@ function cmdFeatureAdrSetup(options, flags, cwd, write) {
|
|
|
4864
4954
|
}
|
|
4865
4955
|
if (wantGuards)
|
|
4866
4956
|
spec = { ...spec, guards: locCap !== undefined ? { locCap } : true };
|
|
4867
|
-
|
|
4957
|
+
if (wantGates)
|
|
4958
|
+
spec = { ...spec, gates: true };
|
|
4959
|
+
const result = scaffoldFromSpec(spec, readExistingForScaffold(repoRoot), gatesTarget);
|
|
4868
4960
|
if (flags.has('json') && !flags.has('apply')) {
|
|
4869
4961
|
write(JSON.stringify(result, null, 2));
|
|
4870
4962
|
return 0;
|
|
@@ -5102,6 +5194,149 @@ function cmdDiscriminationCheck(options, flags, cwd, write) {
|
|
|
5102
5194
|
function nameFor(t, outcome) {
|
|
5103
5195
|
return t.name !== undefined ? { file: t.file, name: t.name, outcome } : { file: t.file, outcome };
|
|
5104
5196
|
}
|
|
5197
|
+
/**
|
|
5198
|
+
* `dz delivery-check` — the portable Step-10 Delivery Gate (feature portable-gates). The `manual` form that
|
|
5199
|
+
* travels to every `shell` target: the deterministic parts (artifact probes, hand-off arithmetic,
|
|
5200
|
+
* cross-validation bookkeeping) run IN the CLI; the semantic 4-plane review is DISPATCHED to the caller's own
|
|
5201
|
+
* agent runtime — the `dz challenge` cartridge shape. All logic lives in harness-core's pure engine; this is
|
|
5202
|
+
* the executor. Advisory exit codes (0 by default; `--strict` ⇒ 1 on `blocked`).
|
|
5203
|
+
*
|
|
5204
|
+
* --slug <slug> the feature under features/<slug> (required; featureDir derived internally)
|
|
5205
|
+
* --context-only default mode: print artifact probes + the 4-plane review brief (no verdict)
|
|
5206
|
+
* --findings <f.json> classify a fed-back findings array → write 10_delivery_review.md + print ready/blocked
|
|
5207
|
+
* --strict with --findings: exit 1 iff handoff === 'blocked' (CI gate)
|
|
5208
|
+
* --author <model> cosmetic: the reviewer to dispatch, printed alongside the brief
|
|
5209
|
+
* --json machine contract { planesChecked, planesSkipped, findings, handoff, artifact }
|
|
5210
|
+
*/
|
|
5211
|
+
function cmdDeliveryCheck(options, flags, cwd, write) {
|
|
5212
|
+
let repoRoot = cwd;
|
|
5213
|
+
try {
|
|
5214
|
+
repoRoot = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }).trim() || cwd;
|
|
5215
|
+
}
|
|
5216
|
+
catch { /* not git */ }
|
|
5217
|
+
const json = flags.has('json');
|
|
5218
|
+
const errOut = (error) => {
|
|
5219
|
+
if (json)
|
|
5220
|
+
write(JSON.stringify({ error, planesChecked: [], planesSkipped: [], findings: [], handoff: null, artifact: 'not-written' }, null, 2));
|
|
5221
|
+
else {
|
|
5222
|
+
write(`dz delivery-check: ${error}`);
|
|
5223
|
+
write(' allowed: --slug <slug>, --findings <f.json>, --author <model>, --context-only, --strict, --json');
|
|
5224
|
+
}
|
|
5225
|
+
return 1;
|
|
5226
|
+
};
|
|
5227
|
+
// Strict allowlist (delivery finding: a typo'd --findings silently downgraded the --strict CI
|
|
5228
|
+
// gate to a vacuous exit-0 pass — a mistyped option must be an ERROR, never a mode change).
|
|
5229
|
+
const allowedFlags = new Set(['context-only', 'strict', 'json', 'help']);
|
|
5230
|
+
const allowedOptions = new Set(['slug', 'findings', 'author']);
|
|
5231
|
+
for (const flag of flags)
|
|
5232
|
+
if (!allowedFlags.has(flag))
|
|
5233
|
+
return errOut(`unknown option --${flag}`);
|
|
5234
|
+
for (const key of options.keys()) {
|
|
5235
|
+
if (key.startsWith('_positional_'))
|
|
5236
|
+
return errOut(`unexpected argument "${options.get(key)}"`);
|
|
5237
|
+
if (!allowedOptions.has(key))
|
|
5238
|
+
return errOut(`unknown option --${key}`);
|
|
5239
|
+
}
|
|
5240
|
+
const slug = options.get('slug');
|
|
5241
|
+
if (slug === undefined || slug.trim() === '')
|
|
5242
|
+
return errOut('pass --slug <slug> (the feature under features/<slug>)');
|
|
5243
|
+
// Slug convention is a SECURITY boundary here (delivery finding, CONFIRMED traversal reproducer:
|
|
5244
|
+
// --slug '../../outside/evil' wrote 10_delivery_review.md outside the repo). kebab-case Latin,
|
|
5245
|
+
// <=40 chars — the repo's own slug rule as a layer-1 three-line check.
|
|
5246
|
+
const slugTrimmed = slug.trim();
|
|
5247
|
+
if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(slugTrimmed) || slugTrimmed.length > 40) {
|
|
5248
|
+
return errOut(`invalid --slug "${slugTrimmed}" — kebab-case Latin, max 40 chars (a path-like slug would redirect the report write)`);
|
|
5249
|
+
}
|
|
5250
|
+
const featureDir = join(repoRoot, 'features', slugTrimmed);
|
|
5251
|
+
// --context-only is a real mode flag, not decoration: combining it with --findings contradicts
|
|
5252
|
+
// itself (delivery finding — the flag was accepted and silently ignored).
|
|
5253
|
+
if (flags.has('context-only') && options.get('findings') !== undefined) {
|
|
5254
|
+
return errOut('--context-only and --findings are mutually exclusive (context-only prints the brief; findings classifies the verdict)');
|
|
5255
|
+
}
|
|
5256
|
+
// git status --porcelain — CLI layer only (the `no child_process in core` contract); a non-git target
|
|
5257
|
+
// degrades to an empty list, which is honest (AM-10: changed-files is informational, never a required gate).
|
|
5258
|
+
let changedFiles = [];
|
|
5259
|
+
try {
|
|
5260
|
+
const out = execSync('git status --porcelain', { cwd: repoRoot, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
5261
|
+
changedFiles = out.split('\n').map((l) => l.slice(3).trim()).filter((s) => s.length > 0);
|
|
5262
|
+
}
|
|
5263
|
+
catch { /* non-git / unavailable → empty (honest) */ }
|
|
5264
|
+
const facts = collectDeliveryFacts(featureDir, { changedFiles, repoRoot });
|
|
5265
|
+
const plan = planDeliveryCheck(facts);
|
|
5266
|
+
const author = options.get('author');
|
|
5267
|
+
const findingsPath = options.get('findings');
|
|
5268
|
+
if (findingsPath === undefined) {
|
|
5269
|
+
// Default / --context-only: emit the led protocol (probes + brief). No verdict — the CLI has no model.
|
|
5270
|
+
if (json) {
|
|
5271
|
+
write(JSON.stringify({
|
|
5272
|
+
planesChecked: [],
|
|
5273
|
+
planesSkipped: plan.planes.map((p) => p.id),
|
|
5274
|
+
findings: [],
|
|
5275
|
+
handoff: null,
|
|
5276
|
+
artifact: 'not-written',
|
|
5277
|
+
probes: plan.probes,
|
|
5278
|
+
}, null, 2));
|
|
5279
|
+
return 0;
|
|
5280
|
+
}
|
|
5281
|
+
write(`dz delivery-check — ${slug} (portable 4-plane hand-off protocol; you drive the review)`);
|
|
5282
|
+
for (const p of plan.probes) {
|
|
5283
|
+
const mark = p.passed === true ? '✓' : p.passed === false ? '✗' : '○';
|
|
5284
|
+
write(` ${mark} ${p.description}${p.required ? ' [required]' : ' [informational]'}`);
|
|
5285
|
+
}
|
|
5286
|
+
write('');
|
|
5287
|
+
write(renderDeliveryBrief(plan, facts));
|
|
5288
|
+
// The hand-off criterion the verdict will be judged by, shown UP FRONT (this also makes
|
|
5289
|
+
// plan.criterionTemplate a consumed surface, not dead product code — delivery finding).
|
|
5290
|
+
write('\n── hand-off criterion (all must PASS for ready) ──');
|
|
5291
|
+
for (const c of plan.criterionTemplate)
|
|
5292
|
+
write(` ○ ${c.label}`);
|
|
5293
|
+
if (author !== undefined && author.trim() !== '')
|
|
5294
|
+
write(`\n── reviewer to dispatch ──\n${author.trim()}`);
|
|
5295
|
+
write('\n(next: run the four planes, then `dz delivery-check --slug ' + slug + ' --findings findings.json` for the verdict)');
|
|
5296
|
+
return 0;
|
|
5297
|
+
}
|
|
5298
|
+
// --findings mode: parse (malformed/missing ⇒ [], a failed-plane input — fail-closed, never a throw).
|
|
5299
|
+
let reviewResults = [];
|
|
5300
|
+
try {
|
|
5301
|
+
const parsed = JSON.parse(readFileSync(resolve(cwd, findingsPath), 'utf-8'));
|
|
5302
|
+
if (Array.isArray(parsed))
|
|
5303
|
+
reviewResults = parsed;
|
|
5304
|
+
else if (parsed !== null && typeof parsed === 'object' && Array.isArray(parsed.planes))
|
|
5305
|
+
reviewResults = parsed.planes;
|
|
5306
|
+
else
|
|
5307
|
+
reviewResults = [];
|
|
5308
|
+
}
|
|
5309
|
+
catch {
|
|
5310
|
+
reviewResults = [];
|
|
5311
|
+
}
|
|
5312
|
+
const verdict = classifyDelivery(plan, reviewResults);
|
|
5313
|
+
// The SAME predicate as the fail-closed verdict (core-exported) — a local copy was a drift channel.
|
|
5314
|
+
const planesChecked = plan.planes.filter((_, i) => isUsablePlaneResult(reviewResults[i])).map((p) => p.id);
|
|
5315
|
+
const planesSkipped = plan.planes.filter((_, i) => !isUsablePlaneResult(reviewResults[i])).map((p) => p.id);
|
|
5316
|
+
// Write the regenerable report (NOT augment-never-clobber — deliberately overwritten each run).
|
|
5317
|
+
let artifact = 'not-written';
|
|
5318
|
+
try {
|
|
5319
|
+
const reviewPath = join(featureDir, '10_delivery_review.md');
|
|
5320
|
+
mkdirSync(dirname(reviewPath), { recursive: true });
|
|
5321
|
+
writeFileSync(reviewPath, renderDeliveryReview(verdict, facts));
|
|
5322
|
+
artifact = 'written';
|
|
5323
|
+
}
|
|
5324
|
+
catch { /* best-effort — the verdict is still returned */ }
|
|
5325
|
+
if (json) {
|
|
5326
|
+
write(JSON.stringify({ planesChecked, planesSkipped, findings: verdict.findings, handoff: verdict.handoff, artifact }, null, 2));
|
|
5327
|
+
}
|
|
5328
|
+
else {
|
|
5329
|
+
write(`dz delivery-check — ${slug}: ${verdict.handoff}`);
|
|
5330
|
+
for (const c of verdict.criterion) {
|
|
5331
|
+
const mark = c.status === 'PASS' ? '✓' : c.status === 'FAIL' ? '✗' : '○';
|
|
5332
|
+
write(` ${mark} ${c.label}: ${c.status}${c.detail ? ` — ${c.detail}` : ''}`);
|
|
5333
|
+
}
|
|
5334
|
+
write(artifact === 'written' ? `\n↳ wrote features/${slug}/10_delivery_review.md` : '\n↳ 10_delivery_review.md NOT written (verdict above is authoritative)');
|
|
5335
|
+
}
|
|
5336
|
+
if (flags.has('strict') && verdict.handoff === 'blocked')
|
|
5337
|
+
return 1;
|
|
5338
|
+
return 0;
|
|
5339
|
+
}
|
|
5105
5340
|
/**
|
|
5106
5341
|
* `dz routing` — inspect the learned cost-optimal routing outcome store (feature learned-cost-routing). Shows
|
|
5107
5342
|
* what `args.models[stage]='auto-cost'` currently believes per (stage, complexity-tier, model): gated
|
|
@@ -5505,6 +5740,8 @@ export async function runCli(argv, io = {}) {
|
|
|
5505
5740
|
return cmdPublish(options, flags, cwd, write);
|
|
5506
5741
|
case 'release':
|
|
5507
5742
|
return cmdRelease(options, flags, cwd, write, io.releaseRunner);
|
|
5743
|
+
case 'parity':
|
|
5744
|
+
return cmdParity(options, flags, write);
|
|
5508
5745
|
case 'registry':
|
|
5509
5746
|
return cmdRegistry(options, cwd, write);
|
|
5510
5747
|
case 'benchmark':
|
|
@@ -5537,6 +5774,8 @@ export async function runCli(argv, io = {}) {
|
|
|
5537
5774
|
return cmdChallenge(options, flags, cwd, write);
|
|
5538
5775
|
case 'discrimination-check':
|
|
5539
5776
|
return cmdDiscriminationCheck(options, flags, cwd, write);
|
|
5777
|
+
case 'delivery-check':
|
|
5778
|
+
return cmdDeliveryCheck(options, flags, cwd, write);
|
|
5540
5779
|
case 'routing':
|
|
5541
5780
|
return cmdRouting(options, flags, cwd, write);
|
|
5542
5781
|
case 'bto-optimize':
|