@lmzhen/dsh-evolution-maintenance 0.3.7 → 0.3.9

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,35 @@
1
- import { HEALTH_STAMP_RE, computeDedupGroups, computePrefixClusters, duplicateHeadings, missingSupportPointers, narrowNameMatches, overlongLines } from "@lmzhen/dsh-evolution-core";
1
+ import { HEALTH_STAMP_RE, computeDedupGroups, computePrefixClusters, duplicateHeadings, missingSupportPointers, narrowNameMatches, overlongLines, parseFrontmatter, usageObserved } from "@lmzhen/dsh-evolution-core";
2
+ //#region lib/types/drift-scan.js
3
+ /**
4
+ * Skill-library snapshot assembly for drift scanning.
5
+ *
6
+ * `computeDriftSignals` (evolution-core) is a pure function over a plain
7
+ * snapshot; this module converts a SkillLibrary-like reader into that
8
+ * snapshot. Quality score and usage-window status are caller-provided —
9
+ * when absent they stay `undefined`, which the signal layer reports as
10
+ * `unknown` (never a fabricated verdict).
11
+ */
12
+ /**
13
+ * Assemble drift snapshots from a library reader and optional enrichment.
14
+ * Missing enrichment stays `undefined` → signal layer reports `unknown`.
15
+ */
16
+ async function snapshotFromLibrary(library, options = {}) {
17
+ const entries = await library.list();
18
+ const snapshots = [];
19
+ for (const entry of entries) {
20
+ const body = await library.read(entry.name);
21
+ if (body === void 0 || body === null) continue;
22
+ snapshots.push({
23
+ name: entry.name,
24
+ body,
25
+ description: options.descriptions?.get(entry.name),
26
+ supportFiles: options.supportFiles?.get(entry.name),
27
+ quality: options.quality?.get(entry.name)
28
+ });
29
+ }
30
+ return snapshots;
31
+ }
32
+ //#endregion
2
33
  //#region lib/types/probe.js
3
34
  /**
4
35
  * Probe detail computation (011 Phase 3).
@@ -68,4 +99,38 @@ function computeProbe(signal, target, snapshots) {
68
99
  }
69
100
  }
70
101
  //#endregion
71
- export { computeProbe as n, PROBE_SIGNALS as t };
102
+ //#region lib/types/enrichment.js
103
+ /**
104
+ * Enrichment maps shared by the full maintain scan and the `--facts` preview
105
+ * (v12) AND the maintenance_probe tool (0.3.9): one construction = the probe
106
+ * and the facts block can never disagree about descriptions, support files,
107
+ * or quality (the 0.3.8 review found the probe answering "description=missing"
108
+ * while the facts block measured real lengths — probe snapshots carried no
109
+ * enrichment at all).
110
+ */
111
+ async function buildEnrichment(ctx, library) {
112
+ const skillUsage = ctx.get("skillUsage");
113
+ const usageMap = skillUsage?.report ? await skillUsage.report() : void 0;
114
+ const usageObservedValue = usageMap ? usageObserved(usageMap) : void 0;
115
+ const descriptions = /* @__PURE__ */ new Map();
116
+ const supportFiles = /* @__PURE__ */ new Map();
117
+ const quality = /* @__PURE__ */ new Map();
118
+ for (const entry of await library.list()) {
119
+ const body = await library.read(entry.name);
120
+ if (body === null) continue;
121
+ const description = parseFrontmatter(body)?.frontmatter.description;
122
+ if (typeof description === "string" && description.trim().length > 0) descriptions.set(entry.name, description);
123
+ const files = await library.listSupportFiles(entry.name);
124
+ if (files.length > 0) supportFiles.set(entry.name, files);
125
+ const record = usageMap?.get(entry.name);
126
+ if (typeof record?.quality_score === "number") quality.set(entry.name, record.quality_score);
127
+ }
128
+ return {
129
+ descriptions,
130
+ supportFiles,
131
+ quality,
132
+ usageObservedValue
133
+ };
134
+ }
135
+ //#endregion
136
+ export { snapshotFromLibrary as i, PROBE_SIGNALS as n, computeProbe as r, buildEnrichment as t };
package/lib/index.js CHANGED
@@ -1,37 +1,6 @@
1
- import { n as computeProbe, t as PROBE_SIGNALS } from "./probe-CrVeRJ6b.js";
1
+ import { i as snapshotFromLibrary, n as PROBE_SIGNALS, r as computeProbe, t as buildEnrichment } from "./enrichment-DxCdaJaQ.js";
2
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";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
- //#region lib/types/drift-scan.js
5
- /**
6
- * Skill-library snapshot assembly for drift scanning.
7
- *
8
- * `computeDriftSignals` (evolution-core) is a pure function over a plain
9
- * snapshot; this module converts a SkillLibrary-like reader into that
10
- * snapshot. Quality score and usage-window status are caller-provided —
11
- * when absent they stay `undefined`, which the signal layer reports as
12
- * `unknown` (never a fabricated verdict).
13
- */
14
- /**
15
- * Assemble drift snapshots from a library reader and optional enrichment.
16
- * Missing enrichment stays `undefined` → signal layer reports `unknown`.
17
- */
18
- async function snapshotFromLibrary(library, options = {}) {
19
- const entries = await library.list();
20
- const snapshots = [];
21
- for (const entry of entries) {
22
- const body = await library.read(entry.name);
23
- if (body === void 0 || body === null) continue;
24
- snapshots.push({
25
- name: entry.name,
26
- body,
27
- description: options.descriptions?.get(entry.name),
28
- supportFiles: options.supportFiles?.get(entry.name),
29
- quality: options.quality?.get(entry.name)
30
- });
31
- }
32
- return snapshots;
33
- }
34
- //#endregion
35
4
  //#region lib/types/render-facts.js
36
5
  /**
37
6
  * Mechanical-facts rendering for the maintenance subagent (011 §6).
@@ -363,7 +332,7 @@ async function runMaintain(runtime, options = {}) {
363
332
  const timeoutMs = options.timeoutMs ?? 12e4;
364
333
  const agentOptions = { model: options.model ?? "deepseek-v4-pro" };
365
334
  if (options.provider) agentOptions.provider = options.provider;
366
- const raw = (await (await runtime.subagents.start("spawn", {
335
+ const runResult = await (await runtime.subagents.start("spawn", {
367
336
  label: "dsh-evolution-maintain",
368
337
  prompt: [{
369
338
  type: "text",
@@ -423,11 +392,18 @@ async function runMaintain(runtime, options = {}) {
423
392
  }
424
393
  }
425
394
  }
426
- })).result)?.structured;
427
- if (raw === void 0) return {
428
- ok: false,
429
- error: "Maintain subagent returned no structured plan."
430
- };
395
+ })).result;
396
+ const raw = runResult?.structured;
397
+ if (raw === void 0) {
398
+ if (runResult?.stopReason === "aborted") return {
399
+ ok: false,
400
+ 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."
401
+ };
402
+ return {
403
+ ok: false,
404
+ 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."
405
+ };
406
+ }
431
407
  const validated = validateAndNormalizeMaintainPlan(raw, report, existingSignalIds(report));
432
408
  if (!validated.ok) return {
433
409
  ok: false,
@@ -446,9 +422,9 @@ async function runMaintain(runtime, options = {}) {
446
422
  const message = error instanceof Error ? error.message : String(error);
447
423
  return {
448
424
  ok: false,
449
- error: name === "AbortError" ? "Maintenance scan was aborted (subagent timeout or cancellation) before a plan was produced — retry, or raise the timeout (evolution-commands maintainTimeoutMs) on a slow/large library." : `Maintenance scan failed: ${message}`
425
+ error: name === "AbortError" || /abort/i.test(`${String(name)} ${message}`) ? "Maintenance scan was aborted (cancellation or timeout) before a plan was produced — retry, or raise the timeout (evolution-commands maintainTimeoutMs) on a slow/large library." : `Maintenance scan failed: ${message}`
450
426
  };
451
427
  }
452
428
  }
453
429
  //#endregion
454
- export { PROBE_SIGNALS, buildMaintainFacts, computeProbe, renderFacts, renderMaintainTemplate, runMaintain, snapshotFromLibrary, summarizeAssessment, validateAndNormalizeMaintainPlan };
430
+ export { PROBE_SIGNALS, buildEnrichment, buildMaintainFacts, computeProbe, renderFacts, renderMaintainTemplate, runMaintain, snapshotFromLibrary, summarizeAssessment, validateAndNormalizeMaintainPlan };
package/lib/tools.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as computeProbe, t as PROBE_SIGNALS } from "./probe-CrVeRJ6b.js";
1
+ import { i as snapshotFromLibrary, n as PROBE_SIGNALS, r as computeProbe, t as buildEnrichment } from "./enrichment-DxCdaJaQ.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
@@ -59,17 +59,12 @@ function apply(ctx, rawConfig = {}) {
59
59
  ...target ? { target } : {}
60
60
  };
61
61
  const library = new SkillLibrary(config.skillsRoot, ioRegistry.provider());
62
- const entries = await library.list();
63
- const snapshots = [];
64
- for (const entry of entries) {
65
- const body = await library.read(entry.name);
66
- if (body === null) continue;
67
- snapshots.push({
68
- name: entry.name,
69
- body
70
- });
71
- }
72
- const probe = computeProbe(signal, target, snapshots);
62
+ const enrichment = await buildEnrichment(ctx, library);
63
+ const probe = computeProbe(signal, target, await snapshotFromLibrary(library, {
64
+ descriptions: enrichment.descriptions,
65
+ supportFiles: enrichment.supportFiles,
66
+ quality: enrichment.quality
67
+ }));
73
68
  const redacted = redactSecrets(probe.detail.join("\n"));
74
69
  return {
75
70
  ...probe,
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Enrichment maps shared by the full maintain scan and the `--facts` preview
3
+ * (v12) AND the maintenance_probe tool (0.3.9): one construction = the probe
4
+ * and the facts block can never disagree about descriptions, support files,
5
+ * or quality (the 0.3.8 review found the probe answering "description=missing"
6
+ * while the facts block measured real lengths — probe snapshots carried no
7
+ * enrichment at all).
8
+ */
9
+ import type { Context } from '@deepseek-ai/cordis';
10
+ import { type SkillLibrary } from '@deepseek-ai/dsh-evolution-core';
11
+ export interface Enrichment {
12
+ descriptions: ReadonlyMap<string, string>;
13
+ supportFiles: ReadonlyMap<string, readonly string[]>;
14
+ quality: ReadonlyMap<string, number>;
15
+ usageObservedValue: boolean | undefined;
16
+ }
17
+ export declare function buildEnrichment(ctx: Context, library: SkillLibrary): Promise<Enrichment>;
18
+ //# sourceMappingURL=enrichment.d.ts.map
@@ -14,4 +14,5 @@ export * from './render-facts.ts';
14
14
  export * from './validate-plan.ts';
15
15
  export * from './orchestrate.ts';
16
16
  export * from './probe.ts';
17
+ export * from './enrichment.ts';
17
18
  //# sourceMappingURL=index.d.ts.map
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.7",
4
+ "version": "0.3.9",
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.7"
37
+ "@lmzhen/dsh-evolution-core": "^0.3.9"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",