@dzhechkov/harness-cli 0.3.259 → 0.3.260
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 +31 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +41 -5
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
- package/src/cli.ts +43 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dzhechkov/harness-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.260",
|
|
4
4
|
"description": "The dz CLI — install AI skills for Claude Code, Codex, OpenCode, Hermes, OpenClaude, GitHub Copilot. 35 commands, 13 presets, 6 platform targets.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"sbom.json"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@dzhechkov/harness-core": "^0.3.
|
|
44
|
+
"@dzhechkov/harness-core": "^0.3.150",
|
|
45
45
|
"@dzhechkov/harness-presets": "^0.5.0",
|
|
46
46
|
"@dzhechkov/scout": "^0.8.0",
|
|
47
47
|
"@dzhechkov/skills-devops": "^0.3.0",
|
package/src/cli.ts
CHANGED
|
@@ -275,6 +275,10 @@ import {
|
|
|
275
275
|
makeBacklogIO,
|
|
276
276
|
harmonizeBacklog,
|
|
277
277
|
BACKLOG_BACKENDS,
|
|
278
|
+
applyDomainBoost,
|
|
279
|
+
countDisplacedByCut,
|
|
280
|
+
renderDomainBoostNote,
|
|
281
|
+
renderDomainCutNote,
|
|
278
282
|
parseReqeDebt,
|
|
279
283
|
buildReqeBrief,
|
|
280
284
|
settleReqeDebt,
|
|
@@ -333,7 +337,7 @@ Usage:
|
|
|
333
337
|
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)
|
|
334
338
|
dz teach --from-json <file> [--project <dir>] [--no-mirror] (bulk-import a 'dz recall --all --json' export — share a learned store across machines)
|
|
335
339
|
dz consolidate [--sessions-dir <dir>] [--project <dir>] [--no-mirror] [--prune-noise [--apply]] [--prune-quarantine [--apply]] (both prunes: DRY-RUN by default; --apply snapshots then deletes; prune-quarantine = expired unproven lessons ONLY, never coupled to noise)
|
|
336
|
-
dz recall "<query>" [--limit <N>] [--semantic | --no-semantic] [--books [--book <slug>]] [--project <dir>] | dz recall --all [--json] | dz recall --usage [--json] | dz recall --forget <dzId>[,<dzId>] [--apply] | dz recall --promote <dzId>[,<dzId>] [--apply] (forget/promote: dry-run default; forget snapshots before removing; promote lifts lesson-quarantine)
|
|
340
|
+
dz recall "<query>" [--limit <N>] [--domain <name>] [--semantic | --no-semantic] [--books [--book <slug>]] [--project <dir>] | dz recall --all [--json] | dz recall --usage [--json] | dz recall --forget <dzId>[,<dzId>] [--apply] | dz recall --promote <dzId>[,<dzId>] [--apply] (--domain <name> BOOSTS lessons of that domain without dropping foreign ones — a shared store keeps its cross-domain transfers; forget/promote: dry-run default; forget snapshots before removing; promote lifts lesson-quarantine)
|
|
337
341
|
dz vector status [--project <dir>] [--json] (semantic tier: engine, mirrored vs lexical counts, pending queue)
|
|
338
342
|
dz vector reindex [--project <dir>] [--json] (snapshot, re-embed learned-pattern vectors, stamp current model)
|
|
339
343
|
dz vector export <path> [--project <dir>] (portable VECTOR form (.rvf, opt-in RVF engine); patterns ship via recall --all --json)
|
|
@@ -2241,13 +2245,31 @@ async function cmdRecall(options: Map<string, string>, flags: Set<string>, cwd:
|
|
|
2241
2245
|
: flags.has('no-semantic') || flags.has('lexical')
|
|
2242
2246
|
? ('lexical' as const)
|
|
2243
2247
|
: ('hybrid' as const);
|
|
2244
|
-
const
|
|
2248
|
+
const wantedDomain = options.get('domain');
|
|
2249
|
+
// OVER-FETCH before boosting (Codex QE #5): the boost used to run on hits ALREADY
|
|
2250
|
+
// truncated to `limit`, so an exact-domain lesson sitting at rank limit+1 could
|
|
2251
|
+
// never receive its promised lift — the feature was weakest in exactly the case it
|
|
2252
|
+
// exists for (foreign-domain dilution pushing a relevant lesson just past the cut).
|
|
2253
|
+
// Fetch a bounded surplus, re-rank, then trim to the limit the caller asked for.
|
|
2254
|
+
const fetchLimit = wantedDomain !== undefined ? Math.min(limit * 3, limit + 20) : limit;
|
|
2255
|
+
const result = await recallHybrid(projectRoot, query, { limit: fetchLimit, mode });
|
|
2256
|
+
|
|
2245
2257
|
if (mode === 'semantic' && result.vectorEngine === 'none') {
|
|
2246
2258
|
// --semantic is an explicit ask — degrading it silently would be dishonest (FR-3).
|
|
2247
2259
|
write(`dz recall --semantic: ${result.vectorReason ?? 'no vector engine available — run: dz setup --memory agentdb'}`);
|
|
2248
2260
|
return 1;
|
|
2249
2261
|
}
|
|
2250
|
-
|
|
2262
|
+
// Domain-aware re-ranking (health-advisor slice H): `--domain <name>` lifts lessons
|
|
2263
|
+
// tagged with that domain WITHOUT dropping foreign ones — a boost, not a filter, so a
|
|
2264
|
+
// shared store keeps the cross-domain transfers that make it worth more than two stores.
|
|
2265
|
+
const boost = wantedDomain !== undefined ? applyDomainBoost(result.hits, wantedDomain) : null;
|
|
2266
|
+
const hits = (boost ? boost.hits : result.hits).slice(0, limit);
|
|
2267
|
+
// The boost never drops a hit, but the CUT still can: promoting a match into the top
|
|
2268
|
+
// `limit` pushes the last one out, so a lesson visible WITHOUT --domain can vanish
|
|
2269
|
+
// WITH it. Cross-model review called this out as a lie by omission — the note said
|
|
2270
|
+
// "foreign-domain lessons kept" about the pre-cut list while the printed list was
|
|
2271
|
+
// missing one. Count it and say so; the reader can act on it (raise --limit).
|
|
2272
|
+
const displaced = boost !== null ? countDisplacedByCut(result.hits, boost.hits, limit) : 0;
|
|
2251
2273
|
if (asJson) {
|
|
2252
2274
|
// Portable contract UNCHANGED (I-7/AC-6): a plain PatternRecord[] — round-trips through
|
|
2253
2275
|
// `dz teach --from-json` regardless of which backend ranked each hit.
|
|
@@ -2258,6 +2280,10 @@ async function cmdRecall(options: Map<string, string>, flags: Set<string>, cwd:
|
|
|
2258
2280
|
if (hits.length === 0) {
|
|
2259
2281
|
write(`dz recall "${query}"`);
|
|
2260
2282
|
write(` No matching patterns (teach some with \`dz teach\`, or consolidate sessions).`);
|
|
2283
|
+
// The domain note must print here too (Codex QE #10): a --domain run with zero hits
|
|
2284
|
+
// silently said nothing about the domain, so the reader could not tell whether the
|
|
2285
|
+
// boost had been applied and found nothing, or had not run at all.
|
|
2286
|
+
if (boost !== null && wantedDomain !== undefined) write(renderDomainBoostNote(boost, wantedDomain));
|
|
2261
2287
|
return 0;
|
|
2262
2288
|
}
|
|
2263
2289
|
const vectorOn = result.vectorEngine !== 'none' && result.vectorError === undefined && mode !== 'lexical';
|
|
@@ -2269,12 +2295,25 @@ async function cmdRecall(options: Map<string, string>, flags: Set<string>, cwd:
|
|
|
2269
2295
|
const backendTag = vectorOn ? ` ⟨${h.backend}⟩` : '';
|
|
2270
2296
|
const qTag = h.quarantined === true ? ' ⚠q' : '';
|
|
2271
2297
|
if (h.quarantined === true) sawQuarantined = true;
|
|
2272
|
-
|
|
2298
|
+
// ONE line per hit, always. A lesson may contain newlines, and printing them raw
|
|
2299
|
+
// let stored CONTENT forge lines that look like the tool's own output — including
|
|
2300
|
+
// the domain-boost note that learning_bridge.py reads as a capability probe. Any
|
|
2301
|
+
// consumer that parses this output line-wise has the same exposure, so the fix
|
|
2302
|
+
// belongs at the point of rendering rather than in each reader.
|
|
2303
|
+
const oneLine = h.pattern.pattern.replace(/[\r\n]+/g, ' ⏎ ').slice(0, 80);
|
|
2304
|
+
write(` [${h.pattern.reward.toFixed(2)}] (${h.pattern.domain})${backendTag}${qTag} ${oneLine}`);
|
|
2273
2305
|
}
|
|
2274
2306
|
if (sawQuarantined) {
|
|
2275
2307
|
// The loop stays VISIBLE (ADR D2): a quarantined hit is shown, marked, and explained.
|
|
2276
2308
|
write(' ⚠q = quarantined (unproven hypothesis, rank damped) — confirm with dz teach --reinforce, or dz recall --promote <dzId> --apply');
|
|
2277
2309
|
}
|
|
2310
|
+
if (boost !== null && wantedDomain !== undefined) {
|
|
2311
|
+
// Say what the boost did — INCLUDING when it did nothing. A silent reorder would
|
|
2312
|
+
// let the reader believe the ranking was domain-aware when it had no match to work with.
|
|
2313
|
+
write(renderDomainBoostNote(boost, wantedDomain));
|
|
2314
|
+
const cutNote = renderDomainCutNote(displaced, limit);
|
|
2315
|
+
if (cutNote !== '') write(cutNote);
|
|
2316
|
+
}
|
|
2278
2317
|
if (result.vectorError !== undefined && mode !== 'lexical') {
|
|
2279
2318
|
// Engine present but the semantic leg failed/timed out — one honest line, exit 0 (05 §2.3).
|
|
2280
2319
|
write(` ℹ vector search degraded: ${result.vectorError} — showing lexical ranking`);
|