@lmzhen/dsh-evolution-maintenance 0.3.17 → 0.3.18
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HEALTH_STAMP_RE, computeDedupGroups, computePrefixClusters, duplicateHeadings, frontmatterYamlUnsafeValues, missingSupportPointers, narrowNameMatches, overlongLines, parseFrontmatter, usageObserved } from "@lmzhen/dsh-evolution-core";
|
|
1
|
+
import { HEALTH_STAMP_RE, MIN_STAMP_BODY_CHARS, computeDedupGroups, computePrefixClusters, duplicateHeadings, frontmatterYamlUnsafeValues, missingSupportPointers, narrowNameMatches, overlongLines, parseFrontmatter, usageObserved } from "@lmzhen/dsh-evolution-core";
|
|
2
2
|
//#region lib/types/drift-scan.js
|
|
3
3
|
/**
|
|
4
4
|
* Skill-library snapshot assembly for drift scanning.
|
|
@@ -26,7 +26,8 @@ async function snapshotFromLibrary(library, options = {}) {
|
|
|
26
26
|
supportFiles: options.supportFiles?.get(entry.name),
|
|
27
27
|
quality: options.quality?.get(entry.name),
|
|
28
28
|
...options.protected?.get(entry.name) !== void 0 ? { protected: options.protected.get(entry.name) } : {},
|
|
29
|
-
...options.catalogInvalid?.get(entry.name) === true ? { catalogInvalid: true } : {}
|
|
29
|
+
...options.catalogInvalid?.get(entry.name) === true ? { catalogInvalid: true } : {},
|
|
30
|
+
...options.usageObserved !== void 0 ? { usageObserved: options.usageObserved } : {}
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
33
|
return snapshots;
|
|
@@ -76,13 +77,17 @@ function computeProbe(signal, target, snapshots) {
|
|
|
76
77
|
if (!PROBE_SIGNALS.includes(signal)) return result(signal, [`unknown-signal '${signal}' (allowed: ${PROBE_SIGNALS.join(", ")})`], target);
|
|
77
78
|
if (signal === "dedup_group") return result(signal, computeDedupGroups({ contents: new Map(snapshots.map((snapshot) => [snapshot.name, snapshot.body])) }).map((group) => group.join(" ~ ")));
|
|
78
79
|
if (signal === "prefix_cluster") return result(signal, computePrefixClusters(snapshots.map((snapshot) => snapshot.name)).map((cluster) => `${cluster.key}: ${cluster.members.join(", ")}`));
|
|
79
|
-
if (signal === "usage_observed")
|
|
80
|
+
if (signal === "usage_observed") {
|
|
81
|
+
if (!(snapshots.length > 0 && snapshots.every((snapshot) => snapshot.usageObserved !== null && snapshot.usageObserved !== void 0))) return result(signal, ["usage_observed=unknown"]);
|
|
82
|
+
return result(signal, [`usage_observed=${snapshots.every((snapshot) => snapshot.usageObserved === true) ? "observed" : "unobserved"}`]);
|
|
83
|
+
}
|
|
80
84
|
if (!target) return result(signal, ["skill-level signal requires a target skill name"]);
|
|
81
85
|
const snapshot = findSnapshot(snapshots, target);
|
|
82
86
|
if (!snapshot) return result(signal, [`skill '${target}' not found in snapshot`], target);
|
|
83
87
|
const body = snapshot.body;
|
|
84
88
|
switch (signal) {
|
|
85
89
|
case "stamp_density": {
|
|
90
|
+
if (body.length < MIN_STAMP_BODY_CHARS) return result(signal, ["stamp_density=below-min-body", `body=${body.length} chars below MIN_STAMP_BODY_CHARS=${MIN_STAMP_BODY_CHARS}`], target);
|
|
86
91
|
const kb = Math.max(1, body.length / 1024);
|
|
87
92
|
const stamps = body.match(HEALTH_STAMP_RE) ?? [];
|
|
88
93
|
return result(signal, [`stamp_density=${(stamps.length / kb).toFixed(2)}/KB (${stamps.length} stamps / ${Math.round(kb)}KB)`, ...stamps.slice(0, 10).map((stamp) => `stamp: ${stamp}`)], target);
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as snapshotFromLibrary, n as PROBE_SIGNALS, r as computeProbe, t as buildEnrichment } from "./enrichment-
|
|
2
|
-
import { AUTHORING_DESCRIPTION_BAR, DEFAULT_HEALTH_THRESHOLDS, DRIFT_MAX_LINE_CHARS, DRIFT_SIGNALS_VERSION, DRIFT_SIGNAL_NOUNS, LOW_QUALITY_THRESHOLD, MAINTAIN_PROMPT, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, computeDriftSignals, findDriftSignal, redactSecrets, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
|
|
1
|
+
import { i as snapshotFromLibrary, n as PROBE_SIGNALS, r as computeProbe, t as buildEnrichment } from "./enrichment-Di8Y4kev.js";
|
|
2
|
+
import { AUTHORING_DESCRIPTION_BAR, DEFAULT_HEALTH_THRESHOLDS, DRIFT_MAX_LINE_CHARS, DRIFT_SIGNALS_VERSION, DRIFT_SIGNAL_NOUNS, LOW_QUALITY_THRESHOLD, MAINTAIN_PROMPT, MIN_STAMP_BODY_CHARS, PROMPT_BUNDLE, PROMPT_BUNDLE_ID, computeDriftSignals, findDriftSignal, redactSecrets, verifyPromptBundle } from "@lmzhen/dsh-evolution-core";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
//#region lib/types/render-facts.js
|
|
5
5
|
/**
|
|
@@ -148,7 +148,9 @@ function validateAndNormalizeMaintainPlan(raw, report, validSignals) {
|
|
|
148
148
|
if (typeof item.impact !== "string" || !IMPACTS.has(item.impact)) errors.push(`${path}.impact: invalid`);
|
|
149
149
|
if (!isNonEmptyString(item.impact_reason)) errors.push(`${path}.impact_reason: required`);
|
|
150
150
|
if (typeof item.reversibility !== "string" || !REVERSIBILITIES.has(item.reversibility)) errors.push(`${path}.reversibility: invalid`);
|
|
151
|
-
|
|
151
|
+
let normalizedUndoPath;
|
|
152
|
+
if (isNonEmptyString(item.undo_path)) normalizedUndoPath = item.undo_path;
|
|
153
|
+
else if (item.reversibility === "none") normalizedUndoPath = "n/a";
|
|
152
154
|
else {
|
|
153
155
|
const rev = typeof item.reversibility === "string" ? item.reversibility : "missing";
|
|
154
156
|
errors.push(`${path}.undo_path: required (reversibility=${rev})`);
|
|
@@ -169,7 +171,7 @@ function validateAndNormalizeMaintainPlan(raw, report, validSignals) {
|
|
|
169
171
|
impact: isNonEmptyString(item.impact) ? item.impact : "neutral",
|
|
170
172
|
impact_reason: str(item.impact_reason, ""),
|
|
171
173
|
reversibility: isNonEmptyString(item.reversibility) ? item.reversibility : "none",
|
|
172
|
-
undo_path: str(item.undo_path, ""),
|
|
174
|
+
undo_path: normalizedUndoPath ?? str(item.undo_path, ""),
|
|
173
175
|
confidence: typeof item.confidence === "number" ? item.confidence : 0,
|
|
174
176
|
needs_human: item.needs_human === true,
|
|
175
177
|
is_override: item.is_override === true,
|
|
@@ -253,7 +255,7 @@ function jointSignature(template, signalsVersion) {
|
|
|
253
255
|
nouns: DRIFT_SIGNAL_NOUNS,
|
|
254
256
|
thresholds: {
|
|
255
257
|
stampDensityPerKb: DEFAULT_HEALTH_THRESHOLDS.stampDensityPerKb,
|
|
256
|
-
minStampBodyChars:
|
|
258
|
+
minStampBodyChars: MIN_STAMP_BODY_CHARS,
|
|
257
259
|
softBodyChars: DEFAULT_HEALTH_THRESHOLDS.softBodyChars,
|
|
258
260
|
descriptionChars: AUTHORING_DESCRIPTION_BAR,
|
|
259
261
|
qualityLow: LOW_QUALITY_THRESHOLD,
|
|
@@ -321,12 +323,14 @@ async function runMaintain(runtime, options = {}) {
|
|
|
321
323
|
ok: false,
|
|
322
324
|
error: "dsh-evolution prompt bundle integrity check failed; refusing to run maintain"
|
|
323
325
|
};
|
|
326
|
+
const usageObserved = options.usageObserved ? options.usageObserved() : void 0;
|
|
324
327
|
const snapshots = await snapshotFromLibrary(runtime.library, {
|
|
325
328
|
supportFiles: options.supportFiles ? options.supportFiles() : void 0,
|
|
326
329
|
descriptions: options.descriptions ? options.descriptions() : void 0,
|
|
327
330
|
quality: options.quality ? options.quality() : void 0,
|
|
328
331
|
protected: options.protected ? options.protected() : void 0,
|
|
329
|
-
catalogInvalid: options.catalogInvalid ? options.catalogInvalid() : void 0
|
|
332
|
+
catalogInvalid: options.catalogInvalid ? options.catalogInvalid() : void 0,
|
|
333
|
+
usageObserved
|
|
330
334
|
});
|
|
331
335
|
if (snapshots.length === 0) return {
|
|
332
336
|
ok: true,
|
|
@@ -334,7 +338,7 @@ async function runMaintain(runtime, options = {}) {
|
|
|
334
338
|
verdict: "no_issues",
|
|
335
339
|
text: "Maintenance scan: empty skill library. Nothing to do."
|
|
336
340
|
};
|
|
337
|
-
const { facts, report, signalsVersion, signature } = buildMaintainFacts(snapshots,
|
|
341
|
+
const { facts, report, signalsVersion, signature } = buildMaintainFacts(snapshots, usageObserved, options.redact);
|
|
338
342
|
const template = renderMaintainTemplate(MAINTAIN_PROMPT, PROMPT_BUNDLE_ID, signalsVersion, signature);
|
|
339
343
|
const prompt = `${facts}
|
|
340
344
|
|
|
@@ -342,7 +346,7 @@ async function runMaintain(runtime, options = {}) {
|
|
|
342
346
|
const timeoutMs = options.timeoutMs ?? 6e5;
|
|
343
347
|
const signal = AbortSignal.timeout(timeoutMs);
|
|
344
348
|
abortSignal = signal;
|
|
345
|
-
const agentOptions = { model: options.model ?? "deepseek-v4-pro" };
|
|
349
|
+
const agentOptions = { model: options.model ?? runtime.evolutionPolicy?.get()?.curatorModel ?? "deepseek-v4-pro" };
|
|
346
350
|
if (options.provider) agentOptions.provider = options.provider;
|
|
347
351
|
const runResult = await (await runtime.subagents.start("spawn", {
|
|
348
352
|
label: "dsh-evolution-maintain",
|
|
@@ -359,6 +363,11 @@ async function runMaintain(runtime, options = {}) {
|
|
|
359
363
|
outputSchema: {
|
|
360
364
|
type: "object",
|
|
361
365
|
additionalProperties: false,
|
|
366
|
+
required: [
|
|
367
|
+
"verdict",
|
|
368
|
+
"plan",
|
|
369
|
+
"notes"
|
|
370
|
+
],
|
|
362
371
|
properties: {
|
|
363
372
|
verdict: { type: "string" },
|
|
364
373
|
plan: {
|
|
@@ -366,6 +375,22 @@ async function runMaintain(runtime, options = {}) {
|
|
|
366
375
|
items: {
|
|
367
376
|
type: "object",
|
|
368
377
|
additionalProperties: false,
|
|
378
|
+
required: [
|
|
379
|
+
"kind",
|
|
380
|
+
"names",
|
|
381
|
+
"rule",
|
|
382
|
+
"evidence",
|
|
383
|
+
"finding",
|
|
384
|
+
"recommendation",
|
|
385
|
+
"semantic_reasoning",
|
|
386
|
+
"impact",
|
|
387
|
+
"impact_reason",
|
|
388
|
+
"reversibility",
|
|
389
|
+
"undo_path",
|
|
390
|
+
"confidence",
|
|
391
|
+
"needs_human",
|
|
392
|
+
"is_override"
|
|
393
|
+
],
|
|
369
394
|
properties: {
|
|
370
395
|
kind: { type: "string" },
|
|
371
396
|
names: {
|
|
@@ -378,6 +403,7 @@ async function runMaintain(runtime, options = {}) {
|
|
|
378
403
|
items: {
|
|
379
404
|
type: "object",
|
|
380
405
|
additionalProperties: false,
|
|
406
|
+
required: ["signal", "value"],
|
|
381
407
|
properties: {
|
|
382
408
|
signal: { type: "string" },
|
|
383
409
|
value: { type: "string" }
|
package/lib/tools.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as snapshotFromLibrary, n as PROBE_SIGNALS, r as computeProbe, t as buildEnrichment } from "./enrichment-
|
|
1
|
+
import { i as snapshotFromLibrary, n as PROBE_SIGNALS, r as computeProbe, t as buildEnrichment } from "./enrichment-Di8Y4kev.js";
|
|
2
2
|
import { SkillLibrary, redactSecrets } from "@lmzhen/dsh-evolution-core";
|
|
3
3
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
4
4
|
//#region lib/types/tools.js
|
|
@@ -16,7 +16,7 @@ const name = "evolution-maintenance-tools";
|
|
|
16
16
|
function apply(ctx, rawConfig = {}) {
|
|
17
17
|
const config = rawConfig;
|
|
18
18
|
ctx.inject(["tools"], (toolCtx) => {
|
|
19
|
-
toolCtx.tools.register(defineTool({
|
|
19
|
+
toolCtx.get("tools").register(defineTool({
|
|
20
20
|
name: "maintenance_probe",
|
|
21
21
|
description: "Read-only deep-dive into maintenance scan signals: library-level group/cluster membership or per-skill detail (line numbers, pointer gaps, narrow shapes, stamp samples). Machine-derived from the same calculators as the facts block — never introduces new evidence ids. Output is JSON detail.",
|
|
22
22
|
parameters: {
|
|
@@ -65,7 +65,8 @@ function apply(ctx, rawConfig = {}) {
|
|
|
65
65
|
supportFiles: enrichment.supportFiles,
|
|
66
66
|
quality: enrichment.quality,
|
|
67
67
|
protected: enrichment.protected,
|
|
68
|
-
catalogInvalid: enrichment.catalogInvalid
|
|
68
|
+
catalogInvalid: enrichment.catalogInvalid,
|
|
69
|
+
usageObserved: enrichment.usageObservedValue
|
|
69
70
|
}));
|
|
70
71
|
const redacted = redactSecrets(probe.detail.join("\n"));
|
|
71
72
|
return {
|
|
@@ -26,6 +26,11 @@ export interface SnapshotOptions {
|
|
|
26
26
|
protected?: ReadonlyMap<string, string> | undefined;
|
|
27
27
|
/** Skills whose frontmatter the strict-YAML catalog cannot load (0.3.11). */
|
|
28
28
|
catalogInvalid?: ReadonlyMap<string, boolean> | undefined;
|
|
29
|
+
/** Usage observation window status (library-wide, applied to every snapshot
|
|
30
|
+
* — the same value the facts block injects). The probe reads it straight off
|
|
31
|
+
* the snapshot (E-36): without it the probe always answered 'unknown' while
|
|
32
|
+
* the facts block reported the enrichment value. */
|
|
33
|
+
usageObserved?: boolean | undefined;
|
|
29
34
|
}
|
|
30
35
|
/**
|
|
31
36
|
* Assemble drift snapshots from a library reader and optional enrichment.
|
|
@@ -17,6 +17,15 @@ export interface MaintainRuntime {
|
|
|
17
17
|
};
|
|
18
18
|
/** Parent agent/session handle passed through to the subagent, when available. */
|
|
19
19
|
parent?: unknown;
|
|
20
|
+
/** Evolution-policy reader for model routing (same source as the curator:
|
|
21
|
+
* `policy.get().curatorModel`). Optional — a missing service falls back to
|
|
22
|
+
* the default model (E-55). `get()` may RESOLVE to undefined (a soft probe
|
|
23
|
+
* can return nothing), hence the type carries it. */
|
|
24
|
+
evolutionPolicy?: {
|
|
25
|
+
get(): {
|
|
26
|
+
curatorModel?: string | undefined;
|
|
27
|
+
} | undefined;
|
|
28
|
+
} | undefined;
|
|
20
29
|
}
|
|
21
30
|
export interface MaintainOptions {
|
|
22
31
|
timeoutMs?: number;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-maintenance",
|
|
3
3
|
"description": "Deterministic maintenance-scan surface: skill-library snapshot assembly, drift signals and mechanical-facts rendering (design 011) (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.18",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
],
|
|
35
35
|
"license": "MIT",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
37
|
+
"@lmzhen/dsh-evolution-core": "^0.3.18"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
@@ -42,7 +42,6 @@
|
|
|
42
42
|
"@deepseek-ai/dsh-tools": "^0.1.1-rc.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2"
|
|
46
|
-
"@deepseek-ai/schemastery": "^3.18.1"
|
|
45
|
+
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2"
|
|
47
46
|
}
|
|
48
47
|
}
|