@lmzhen/dsh-evolution-maintenance 0.3.23 → 0.3.25
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/lib/index.js +39 -23
- package/lib/tools.js +3 -2
- package/lib/types/orchestrate.d.ts +9 -1
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -110,7 +110,11 @@ function validateAndNormalizeMaintainPlan(raw, report, validSignals) {
|
|
|
110
110
|
const errors = [];
|
|
111
111
|
const forcedHuman = [];
|
|
112
112
|
const protectedNames = /* @__PURE__ */ new Set();
|
|
113
|
-
|
|
113
|
+
const factNames = /* @__PURE__ */ new Set();
|
|
114
|
+
for (const skill of report.skills) {
|
|
115
|
+
if (skill.protected) protectedNames.add(skill.name);
|
|
116
|
+
factNames.add(skill.name);
|
|
117
|
+
}
|
|
114
118
|
if (!isRecord(raw)) return {
|
|
115
119
|
ok: false,
|
|
116
120
|
errors: ["plan root: must be an object"],
|
|
@@ -137,7 +141,10 @@ function validateAndNormalizeMaintainPlan(raw, report, validSignals) {
|
|
|
137
141
|
}
|
|
138
142
|
if (typeof item.kind !== "string" || !KINDS.has(item.kind)) errors.push(`${path}.kind: invalid`);
|
|
139
143
|
if (!Array.isArray(item.names) || item.names.length === 0 || !item.names.every(isNonEmptyString)) errors.push(`${path}.names: non-empty string array required`);
|
|
140
|
-
else if (item.names.some((nm) =>
|
|
144
|
+
else if (item.names.some((nm) => !factNames.has(nm))) {
|
|
145
|
+
const missing = item.names.find((nm) => !factNames.has(nm));
|
|
146
|
+
errors.push(`${path}.names: references skill "${String(missing)}" not in the facts report — names must come from the scanned skill set`);
|
|
147
|
+
} else if (item.names.some((nm) => protectedNames.has(nm))) {
|
|
141
148
|
const hit = item.names.find((nm) => protectedNames.has(nm));
|
|
142
149
|
errors.push(`${path}.names: references protected skill "${String(hit)}" — §7 forbids recommendations for bundled/hub-installed/pinned skills`);
|
|
143
150
|
}
|
|
@@ -348,7 +355,7 @@ async function runMaintain(runtime, options = {}) {
|
|
|
348
355
|
abortSignal = signal;
|
|
349
356
|
const agentOptions = { model: options.model ?? runtime.evolutionPolicy?.get()?.curatorModel ?? "deepseek-v4-pro" };
|
|
350
357
|
if (options.provider) agentOptions.provider = options.provider;
|
|
351
|
-
const
|
|
358
|
+
const run = await runtime.subagents.start("spawn", {
|
|
352
359
|
label: "dsh-evolution-maintain",
|
|
353
360
|
prompt: [{
|
|
354
361
|
type: "text",
|
|
@@ -430,31 +437,40 @@ async function runMaintain(runtime, options = {}) {
|
|
|
430
437
|
}
|
|
431
438
|
}
|
|
432
439
|
}
|
|
433
|
-
})
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
440
|
+
});
|
|
441
|
+
try {
|
|
442
|
+
const runResult = await run.result;
|
|
443
|
+
const raw = runResult?.structured;
|
|
444
|
+
if (raw === void 0) {
|
|
445
|
+
if (runResult?.stopReason === "aborted") return {
|
|
446
|
+
ok: false,
|
|
447
|
+
error: "Maintenance scan was aborted (the run was cancelled before the subagent produced a plan) — retry when the session is idle; concurrent re-submission cancels the previous scan."
|
|
448
|
+
};
|
|
449
|
+
return {
|
|
450
|
+
ok: false,
|
|
451
|
+
error: "Maintain subagent returned no structured plan (the model did not emit the structured plan, or the run ended without one) — retry; if it repeats, raise --timeout or check the model output shape."
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
const validated = validateAndNormalizeMaintainPlan(raw, report, existingSignalIds(report));
|
|
455
|
+
if (!validated.ok) return {
|
|
437
456
|
ok: false,
|
|
438
|
-
error:
|
|
457
|
+
error: `Maintain plan rejected by validator: ${validated.errors.slice(0, 5).join("; ")}`
|
|
439
458
|
};
|
|
459
|
+
const runId = randomUUID();
|
|
440
460
|
return {
|
|
441
|
-
ok:
|
|
442
|
-
|
|
461
|
+
ok: true,
|
|
462
|
+
runId,
|
|
463
|
+
verdict: validated.plan.verdict,
|
|
464
|
+
forcedHuman: validated.forcedHuman,
|
|
465
|
+
text: formatPlan(validated, runId)
|
|
443
466
|
};
|
|
467
|
+
} finally {
|
|
468
|
+
try {
|
|
469
|
+
await run.dispose?.();
|
|
470
|
+
} catch (disposeError) {
|
|
471
|
+
runtime.logger?.warn(`dsh-evolution-maintenance: subagent dispose failed: ${disposeError instanceof Error ? disposeError.message : String(disposeError)}`);
|
|
472
|
+
}
|
|
444
473
|
}
|
|
445
|
-
const validated = validateAndNormalizeMaintainPlan(raw, report, existingSignalIds(report));
|
|
446
|
-
if (!validated.ok) return {
|
|
447
|
-
ok: false,
|
|
448
|
-
error: `Maintain plan rejected by validator: ${validated.errors.slice(0, 5).join("; ")}`
|
|
449
|
-
};
|
|
450
|
-
const runId = randomUUID();
|
|
451
|
-
return {
|
|
452
|
-
ok: true,
|
|
453
|
-
runId,
|
|
454
|
-
verdict: validated.plan.verdict,
|
|
455
|
-
forcedHuman: validated.forcedHuman,
|
|
456
|
-
text: formatPlan(validated, runId)
|
|
457
|
-
};
|
|
458
474
|
} catch (error) {
|
|
459
475
|
const name = typeof error === "object" && error !== null ? error.name : void 0;
|
|
460
476
|
const message = error instanceof Error ? error.message : String(error);
|
package/lib/tools.js
CHANGED
|
@@ -16,7 +16,8 @@ const name = "evolution-maintenance-tools";
|
|
|
16
16
|
function apply(ctx, rawConfig = {}) {
|
|
17
17
|
const config = rawConfig;
|
|
18
18
|
ctx.inject(["tools"], (toolCtx) => {
|
|
19
|
-
toolCtx.get("tools")
|
|
19
|
+
const tools = toolCtx.get("tools");
|
|
20
|
+
toolCtx.effect(() => tools.register(defineTool({
|
|
20
21
|
name: "maintenance_probe",
|
|
21
22
|
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
23
|
parameters: {
|
|
@@ -74,7 +75,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
74
75
|
detail: redacted.split("\n")
|
|
75
76
|
};
|
|
76
77
|
}
|
|
77
|
-
}));
|
|
78
|
+
})), "evolution-maintenance.tools");
|
|
78
79
|
});
|
|
79
80
|
}
|
|
80
81
|
//#endregion
|
|
@@ -9,14 +9,22 @@ import { type SkillLibraryLike } from './drift-scan.ts';
|
|
|
9
9
|
export interface MaintainRuntime {
|
|
10
10
|
/** SkillLibrary-like reader for snapshot assembly. */
|
|
11
11
|
library: SkillLibraryLike;
|
|
12
|
-
/** Subagent spawner (platform `subagents` service — minimal shape for injection).
|
|
12
|
+
/** Subagent spawner (platform `subagents` service — minimal shape for injection).
|
|
13
|
+
* `dispose` is optional: not every provider exposes it, so the run is only
|
|
14
|
+
* disposed when the platform provides the handle (rc.42 P1-3 parity with review). */
|
|
13
15
|
subagents: {
|
|
14
16
|
start(kind: string, options: unknown): Promise<{
|
|
15
17
|
result: Promise<unknown>;
|
|
18
|
+
dispose?: () => Promise<void>;
|
|
16
19
|
}>;
|
|
17
20
|
};
|
|
18
21
|
/** Parent agent/session handle passed through to the subagent, when available. */
|
|
19
22
|
parent?: unknown;
|
|
23
|
+
/** Optional logger for dispose-failure traces; when absent the failure is
|
|
24
|
+
* swallowed without surfacing (the orchestrator is a pure function). */
|
|
25
|
+
logger?: {
|
|
26
|
+
warn(message: string): void;
|
|
27
|
+
} | undefined;
|
|
20
28
|
/** Evolution-policy reader for model routing (same source as the curator:
|
|
21
29
|
* `policy.get().curatorModel`). Optional — a missing service falls back to
|
|
22
30
|
* the default model (E-55). `get()` may RESOLVE to undefined (a soft probe
|
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.25",
|
|
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.25"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|