@dzhechkov/harness-cli 0.3.224 → 0.3.226
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -8
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +104 -1
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
- package/src/cli.ts +91 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ The **`dz`** CLI — the main entry point to the DZ Harness Hub. Install AI skil
|
|
|
6
6
|
|
|
7
7
|
> **`dz` is a package manager + cross-compiler for your AI agent harness.** Write a skill once in one canonical form; `dz` installs it into any agent's harness, holds it to a quality bar, and lets the harness learn over time.
|
|
8
8
|
|
|
9
|
-
**The problem.** You accumulate ~
|
|
9
|
+
**The problem.** You accumulate ~179 skills (design-thinking, QE, devops, web3, MCP, academic…). Five pains follow:
|
|
10
10
|
|
|
11
11
|
1. **Every agent wants a different layout.** Claude Code reads `.claude/skills/`, Codex `.codex/`, OpenCode/Hermes/OpenClaude their own. Hand-maintaining N copies is sync hell.
|
|
12
12
|
2. **Skills arrive from many upstream repos** — they must be *canonicalized* (brought to one form) and kept in sync without losing provenance.
|
|
@@ -147,9 +147,9 @@ dz help # see all commands
|
|
|
147
147
|
dz pretrain # analyze project files → recommend by tech stack
|
|
148
148
|
dz recommend "build API and deploy to K8s" # keyword match → skills + toolkits
|
|
149
149
|
dz recommend "work on this project" # generic? → auto-runs pretrain → recommends by stack
|
|
150
|
-
dz stats #
|
|
150
|
+
dz stats # 46 packages, 179 skills, 10 targets, 14 presets
|
|
151
151
|
dz dashboard # visual panel — packages, adapters, skill packs
|
|
152
|
-
dz registry # browse all
|
|
152
|
+
dz registry # browse all 179 skills by category
|
|
153
153
|
dz registry search kubernetes # find specific skills
|
|
154
154
|
dz registry --category devops # filter by domain
|
|
155
155
|
dz downloads # npm weekly download stats
|
|
@@ -355,7 +355,7 @@ the release job gets a perfectly attested malicious package.
|
|
|
355
355
|
A ready-to-install workflow is at `features/publish-provenance/07_code_changes/publish.yml`; copy it to
|
|
356
356
|
`.github/workflows/` and add an `NPM_TOKEN` secret.
|
|
357
357
|
|
|
358
|
-
### Skill Packs (
|
|
358
|
+
### Skill Packs (23 packs · 179 skills)
|
|
359
359
|
|
|
360
360
|
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`.
|
|
361
361
|
|
|
@@ -365,6 +365,7 @@ Each pack is an npm package — click through for the **full per-skill documenta
|
|
|
365
365
|
| [@dzhechkov/skills-mcp](https://www.npmjs.com/package/@dzhechkov/skills-mcp) | 16 | MCP-server integrations — search, git/GitLab, Google Workspace, Notion, AgentDB memory |
|
|
366
366
|
| [@dzhechkov/skills-web3](https://www.npmjs.com/package/@dzhechkov/skills-web3) | 12 | On-chain / DeFi — wallets, swaps, bridges, ENS, agent identity (ERC-8004) |
|
|
367
367
|
| [@dzhechkov/skills-qe](https://www.npmjs.com/package/@dzhechkov/skills-qe) | 20 | Quality engineering — test-gen, coverage, chaos, defect intelligence, QCSD swarms |
|
|
368
|
+
| [@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 |
|
|
368
369
|
| [@dzhechkov/skills-ecc](https://www.npmjs.com/package/@dzhechkov/skills-ecc) | 20 | Claude-Code engineering craft — agent architecture, autonomous loops, framework patterns |
|
|
369
370
|
| [@dzhechkov/skills-meta](https://www.npmjs.com/package/@dzhechkov/skills-meta) | 18 | Dev-process meta skills — explore, feature-adr, design-thinking, audit, skill-advisor |
|
|
370
371
|
| [@dzhechkov/skills-academic](https://www.npmjs.com/package/@dzhechkov/skills-academic) | 5 | Thesis-defense toolkit — dissertation review, questions, doc-check, defense eval |
|
|
@@ -389,6 +390,7 @@ Each pack is an npm package — click through for the **full per-skill documenta
|
|
|
389
390
|
| `keysarium` | 9 | Full research toolkit (feature-adr, presentation, reverse-eng) |
|
|
390
391
|
| `p-replicator` | 10 | AI product development (/replicate, SPARC PRD, pipeline-forge) |
|
|
391
392
|
| `feature-adr` | 5 | Feature pipeline (feature-adr, explore, frontend-design) |
|
|
393
|
+
| `reasoning` | 4 | Generic reasoning & code-quality (investigate, solid, karpathy-guidelines, agents-md-creator) — stack-neutral, zero coupling |
|
|
392
394
|
| `devops` | 30 | DevOps skills (terraform, kubernetes, c4-architecture, incident-response, problem-management, risk-assessment, ...) |
|
|
393
395
|
| `web3` | 12 | Web3/DeFi (quicknode, zerion, symbiosis, bankr, veil, neynar, ...) |
|
|
394
396
|
| `mcp` | 16 | MCP servers (agentdb, brave-search, gmail, gitlab, comfyui, notion, ...) |
|
|
@@ -431,7 +433,7 @@ Get the whole set with `dz init --target claude-code --preset meta`, or pick one
|
|
|
431
433
|
|
|
432
434
|
> **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.
|
|
433
435
|
|
|
434
|
-
## All Commands (
|
|
436
|
+
## All Commands (51)
|
|
435
437
|
|
|
436
438
|
```
|
|
437
439
|
dz setup --target <name> [--preset <name>] [--select id,id,...] [--skills-dir <dir>] [--memory agentdb] [--no-memory] [--no-hooks] [--install-driver] [--force]
|
|
@@ -484,6 +486,7 @@ dz retro [transcript] [--json] [--threshold N] [--no-teach] [--insta
|
|
|
484
486
|
dz feature-adr-setup [--plan] [--from-spec <f>] [--apply] # guided project onboarding engine (behind the `configure-feature-adr` skill): --plan shows which docs exist/missing; --from-spec scaffolds vision/map/testing/project-skills (propose; --apply writes; augment-never-clobber)
|
|
485
487
|
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
|
|
486
488
|
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)
|
|
489
|
+
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
|
|
487
490
|
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)
|
|
488
491
|
dz auto-canonicalize --source <github-url> --pack <skills-pack>
|
|
489
492
|
dz sync-upstream [--package <dir>] [--list] [--all]
|
|
@@ -809,7 +812,7 @@ dz scout --since 2026-05-01 # only recent repos
|
|
|
809
812
|
**Radar mode** (`dz scout`) scans **11 sources** in parallel (GitHub + npm + HN + MCP Registry + Glama + OSSInsight + Smithery + Semantic Scholar + arXiv + ECC + AgentBox):
|
|
810
813
|
1. **Detects skill format** — SKILL.md, plugin.json, .claude/skills/, .claude-plugin/, MCP manifests
|
|
811
814
|
2. **Scores relevance** — format (40%) + stars (30%) + recency (20%) + novelty (10%)
|
|
812
|
-
3. **Compares against our
|
|
815
|
+
3. **Compares against our 46 packages** — finds skills we don't have
|
|
813
816
|
4. **Recommends** — integrate (score ≥70) / monitor (40-69 + ≥50 stars) / skip
|
|
814
817
|
|
|
815
818
|
**Deep analyst mode** (`dz scout --deep`) goes further for top-scored repos:
|
|
@@ -931,7 +934,7 @@ Compares installed skills with canonical source, reports which need `dz init --f
|
|
|
931
934
|
### dz downloads — npm weekly download stats
|
|
932
935
|
|
|
933
936
|
```bash
|
|
934
|
-
dz downloads # fetch weekly downloads for all
|
|
937
|
+
dz downloads # fetch weekly downloads for all 46 packages
|
|
935
938
|
```
|
|
936
939
|
|
|
937
940
|
### dz benchmark — L0 quality gate
|
|
@@ -981,7 +984,7 @@ Scans a GitHub repo for SKILL.md files, generates `dz create-skill` commands.
|
|
|
981
984
|
### dz registry — searchable skill index
|
|
982
985
|
|
|
983
986
|
```bash
|
|
984
|
-
dz registry # visual panel:
|
|
987
|
+
dz registry # visual panel: 179 skills in 11 categories
|
|
985
988
|
dz registry search security # fuzzy search
|
|
986
989
|
dz registry --category mcp # filter by category
|
|
987
990
|
```
|
|
@@ -1490,6 +1493,30 @@ the coder** (a model never self-QEs), and the whole thing is **opt-in** — with
|
|
|
1490
1493
|
pipeline is byte-identical and the store is never touched. Layered under the usage-adaptive override (a session
|
|
1491
1494
|
near its limit still switches to Codex first). Storage is a plain JSON file — zero native deps.
|
|
1492
1495
|
|
|
1496
|
+
### `dz bto-optimize` — when you want to improve a skill WITHOUT gaming its own benchmark
|
|
1497
|
+
|
|
1498
|
+
The BTO pack already grades a skill (`/bto`) and can evolve it (`/bto-optimize`) — but the evolutionary loop
|
|
1499
|
+
picks the highest score on the **same** eval it tuned on, so a variant that flatters the LLM judge panel
|
|
1500
|
+
(verbosity, buzzwords) can win even if it doesn't help real users (**Goodhart's law**). `dz bto-optimize` is the
|
|
1501
|
+
deterministic engine the `/bto-optimize` skill delegates to so acceptance is gated on **unseen** scenarios:
|
|
1502
|
+
```bash
|
|
1503
|
+
dz bto-optimize --split --scenarios @scenarios.json --holdout 0.34 # deterministic tune/holdout split
|
|
1504
|
+
dz bto-optimize --plan --candidates 5 --rounds 1 --tune 4 --holdout 2 --max 24 # budget plan (trims to the cap)
|
|
1505
|
+
dz bto-optimize --select --baseline @baseline.json --candidates @cands.json # accept only on holdout no-regress
|
|
1506
|
+
```
|
|
1507
|
+
```
|
|
1508
|
+
budget plan: 5 candidates × 1 round(s) → 20 tune + 4 holdout = 24 judge run(s) (cap 24, within cap)
|
|
1509
|
+
✓ winner: real — accepted on holdout: CORRECTNESS +2.00, aggregate +0.40, no regression
|
|
1510
|
+
✗ no winner — gamer: lifted CORRECTNESS but regressed DEPTH on holdout
|
|
1511
|
+
```
|
|
1512
|
+
A candidate is accepted **only** if it lifts the weakest dimension (METHODOLOGY/DEPTH/CORRECTNESS/USABILITY/
|
|
1513
|
+
ROBUSTNESS) on the **held-out** scenarios **without regressing** the others — a variant that wins on the tuning
|
|
1514
|
+
set but regresses on the holdout is rejected. Three guarantees: only the **directive prose** is mutated
|
|
1515
|
+
(frontmatter + headings are off-limits, `--scope-check`), the budget has a **hard cap** (the plan trims to fit
|
|
1516
|
+
and never lies about the run count), and the engine **never auto-writes** — it renders a diff you confirm.
|
|
1517
|
+
Grounded in dspy.ts's MIPROv2 (propose → tune → validate-on-held-out). In the skill: **"прогони bto-optimize с
|
|
1518
|
+
hold-out"** / **"optimize this skill with hold-out validation"**.
|
|
1519
|
+
|
|
1493
1520
|
## Recipes & FAQ
|
|
1494
1521
|
|
|
1495
1522
|
Scenario → exact command → how to verify → gotcha. **Three gotchas worth calling out up front:**
|
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;AAyOH,2EAA2E;AAC3E,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAmhJD,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,KAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAsI5E"}
|
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 } 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, decideProvenance, isInsideTree, signManifest, verifyManifest, assertKeyOutsideTree, decidePublishGate, 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, pickAdversaryModel, CHALLENGE_QUESTIONS, loadOutcomes, renderOutcomes, statsForKey, selectAutoCost, recordProvisional, finalizeOutcome, COST_LADDER, } 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, 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, decideProvenance, isInsideTree, signManifest, verifyManifest, assertKeyOutsideTree, decidePublishGate, 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, 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';
|
|
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
|
|
@@ -4316,6 +4316,107 @@ function cmdRouting(options, flags, cwd, write) {
|
|
|
4316
4316
|
write(renderOutcomes(store, stage));
|
|
4317
4317
|
return 0;
|
|
4318
4318
|
}
|
|
4319
|
+
/**
|
|
4320
|
+
* `dz bto-optimize` — the deterministic engine BEHIND the `/bto-optimize` skill (feature bto-optimize-holdout).
|
|
4321
|
+
* Adds dspy-MIPROv2 rigor the current evolutionary loop lacks: a hold-out split, a hard budget cap, and a
|
|
4322
|
+
* no-regress-on-holdout winner selector. NOT a rival command — the skill delegates these steps; candidate-prose
|
|
4323
|
+
* generation + judge scoring stay skill-side. `--json` on every subcommand.
|
|
4324
|
+
* --split --scenarios <csv|@file> [--holdout <r>] deterministic tune/holdout split
|
|
4325
|
+
* --plan --candidates K --rounds R --tune N --holdout M [--max C] budget plan (trims to the cap)
|
|
4326
|
+
* --select --baseline <@json> --candidates <@json> [--tolerance t] accept only on holdout no-regress
|
|
4327
|
+
* --scope-check --original <f> --candidate <f> prose-only guard
|
|
4328
|
+
* --diff --original <f> --candidate <f> the prose diff to confirm
|
|
4329
|
+
*/
|
|
4330
|
+
function cmdBtoOptimize(options, flags, cwd, write) {
|
|
4331
|
+
const json = flags.has('json');
|
|
4332
|
+
const emit = (o) => { write(JSON.stringify(o, null, json ? 2 : 0)); return 0; };
|
|
4333
|
+
const readContained = (rel) => {
|
|
4334
|
+
// Containment (QE #traversal): an @file must stay under cwd — `@../../etc/passwd` must not read outside.
|
|
4335
|
+
const rootAbs = resolve(cwd);
|
|
4336
|
+
const abs = resolve(rootAbs, rel);
|
|
4337
|
+
if (abs !== rootAbs && !abs.startsWith(rootAbs + sep))
|
|
4338
|
+
throw new Error(`path escapes the working directory: ${rel}`);
|
|
4339
|
+
return readFileSync(abs, 'utf-8');
|
|
4340
|
+
};
|
|
4341
|
+
const readJson = (spec) => {
|
|
4342
|
+
if (spec === undefined)
|
|
4343
|
+
return undefined;
|
|
4344
|
+
const raw = spec.startsWith('@') ? readContained(spec.slice(1)) : spec;
|
|
4345
|
+
return JSON.parse(raw);
|
|
4346
|
+
};
|
|
4347
|
+
try {
|
|
4348
|
+
if (flags.has('split')) {
|
|
4349
|
+
const sc = options.get('scenarios');
|
|
4350
|
+
if (sc === undefined) {
|
|
4351
|
+
write('dz bto-optimize --split needs --scenarios <csv|@file>');
|
|
4352
|
+
return 1;
|
|
4353
|
+
}
|
|
4354
|
+
const ids = sc.startsWith('@') ? readScenarioIds(resolve(cwd, sc.slice(1))) : sc.split(',').map((s) => s.trim()).filter(Boolean);
|
|
4355
|
+
const ratio = Number.parseFloat(options.get('holdout') ?? '');
|
|
4356
|
+
const split = splitScenarios(ids, Number.isFinite(ratio) ? ratio : undefined);
|
|
4357
|
+
if (json)
|
|
4358
|
+
return emit(split);
|
|
4359
|
+
write(`tune (${split.tune.length}): ${split.tune.join(', ')}`);
|
|
4360
|
+
write(`holdout (${split.holdout.length}): ${split.holdout.join(', ')}`);
|
|
4361
|
+
return 0;
|
|
4362
|
+
}
|
|
4363
|
+
if (flags.has('plan')) {
|
|
4364
|
+
const n = (k, d) => { const v = Number.parseInt(options.get(k) ?? '', 10); return Number.isFinite(v) ? v : d; };
|
|
4365
|
+
const max = Number.parseInt(options.get('max') ?? '', 10);
|
|
4366
|
+
const plan = budgetPlan({ candidates: n('candidates', 5), rounds: n('rounds', 1), tuneCount: n('tune', 3), holdoutCount: n('holdout', 2) }, Number.isFinite(max) ? max : DEFAULT_MAX_JUDGE_RUNS);
|
|
4367
|
+
if (json)
|
|
4368
|
+
return emit(plan);
|
|
4369
|
+
write(`budget plan: ${plan.candidates} candidates × ${plan.rounds} round(s) → ${plan.tuneRuns} tune + ${plan.holdoutRuns} holdout = ${plan.totalRuns} judge run(s) (cap ${plan.cap}, ${plan.withinCap ? 'within cap' : 'OVER CAP'})`);
|
|
4370
|
+
if (plan.trimmed)
|
|
4371
|
+
write(` trimmed to fit: ${plan.trimmed}`);
|
|
4372
|
+
return 0;
|
|
4373
|
+
}
|
|
4374
|
+
if (flags.has('select')) {
|
|
4375
|
+
const baseline = readJson(options.get('baseline'));
|
|
4376
|
+
const candidates = readJson(options.get('candidates'));
|
|
4377
|
+
if (!baseline || !Array.isArray(candidates)) {
|
|
4378
|
+
write('dz bto-optimize --select needs --baseline <@json {holdout}> and --candidates <@json [..]>');
|
|
4379
|
+
return 1;
|
|
4380
|
+
}
|
|
4381
|
+
const tol = Number.parseFloat(options.get('tolerance') ?? '');
|
|
4382
|
+
const result = selectWinner(baseline, candidates, Number.isFinite(tol) ? { tolerance: tol } : {});
|
|
4383
|
+
if (json)
|
|
4384
|
+
return emit(result);
|
|
4385
|
+
write(result.winner ? `✓ winner: ${result.winner} — ${result.reason}` : `✗ no winner — ${result.reason}`);
|
|
4386
|
+
return 0;
|
|
4387
|
+
}
|
|
4388
|
+
if (flags.has('scope-check') || flags.has('diff')) {
|
|
4389
|
+
const o = options.get('original');
|
|
4390
|
+
const c = options.get('candidate');
|
|
4391
|
+
if (o === undefined || c === undefined) {
|
|
4392
|
+
write('needs --original <file> and --candidate <file>');
|
|
4393
|
+
return 1;
|
|
4394
|
+
}
|
|
4395
|
+
const origText = readContained(o);
|
|
4396
|
+
const candText = readContained(c);
|
|
4397
|
+
if (flags.has('scope-check')) {
|
|
4398
|
+
const r = proseScopeOk(origText, candText);
|
|
4399
|
+
if (json)
|
|
4400
|
+
return emit(r);
|
|
4401
|
+
write(r.ok ? `✓ prose-only: ${r.reason}` : `✗ out of scope: ${r.reason}`);
|
|
4402
|
+
return r.ok ? 0 : 1;
|
|
4403
|
+
}
|
|
4404
|
+
write(renderProseDiff(origText, candText));
|
|
4405
|
+
return 0;
|
|
4406
|
+
}
|
|
4407
|
+
write('dz bto-optimize: pass --split | --plan | --select | --scope-check | --diff (see docs)');
|
|
4408
|
+
return 1;
|
|
4409
|
+
}
|
|
4410
|
+
catch (e) {
|
|
4411
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
4412
|
+
if (json) {
|
|
4413
|
+
write(JSON.stringify({ error: msg }));
|
|
4414
|
+
return 1;
|
|
4415
|
+
}
|
|
4416
|
+
write(`dz bto-optimize: ${msg}`);
|
|
4417
|
+
return 1;
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4319
4420
|
function cmdStats(cwd, write) {
|
|
4320
4421
|
const baseDir = join(cwd, 'packages', '@dzhechkov');
|
|
4321
4422
|
if (!existsSync(baseDir)) {
|
|
@@ -4577,6 +4678,8 @@ export async function runCli(argv, io = {}) {
|
|
|
4577
4678
|
return cmdChallenge(options, flags, cwd, write);
|
|
4578
4679
|
case 'routing':
|
|
4579
4680
|
return cmdRouting(options, flags, cwd, write);
|
|
4681
|
+
case 'bto-optimize':
|
|
4682
|
+
return cmdBtoOptimize(options, flags, cwd, write);
|
|
4580
4683
|
case 'dashboard':
|
|
4581
4684
|
return cmdDashboard(cwd, write);
|
|
4582
4685
|
case 'roam':
|