@lmzhen/dsh-evolution-commands 0.3.57 → 0.3.59

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 CHANGED
@@ -12,7 +12,9 @@ Human commands for the evolution family
12
12
 
13
13
  #### Token effect
14
14
 
15
- Zero direct token effect from this package; consumers add any model-visible tokens.
15
+ P2-22 (v11) correction: this package's **only** direct model-visible token is the
16
+ `/evolution learn` injection — the full learning guidance is injected as a user
17
+ message in this session. Everything else adds no tokens; consumers add their own.
16
18
 
17
19
  #### KV Cache effect
18
20
 
package/lib/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import z from "@deepseek-ai/schemastery";
2
3
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
3
4
  import { SkillLibrary, appendEvolutionEvent, buildLearnPrompt, clampedNumber, composePresetComposition, eventsFile, evolutionRoot, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
4
5
  import { buildEnrichment, buildMaintainFacts, runMaintain, snapshotFromLibrary } from "@lmzhen/dsh-evolution-maintenance";
@@ -96,7 +97,7 @@ async function diagnose(ctx, options = {}) {
96
97
  function renderDoctorText(report) {
97
98
  const lines = [
98
99
  `Evolution doctor — install form: ${report.installForm}`,
99
- `bundles: ${report.bundles.length > 0 ? report.bundles.join(", ") : "(none)"}`,
100
+ `bundles (all profiles): ${report.bundles.length > 0 ? report.bundles.join(", ") : "(none)"}`,
100
101
  `services: review=${report.services.review} curator=${report.services.curator} approval=${report.services.approval} skillUsage=${report.services.skillUsage} io=${report.services.io}`,
101
102
  `pending: ${report.pendingCount === null ? "unknown" : report.pendingCount}`
102
103
  ];
@@ -189,6 +190,12 @@ function renderHelpText() {
189
190
  */
190
191
  /** Enrichment maps shared by the full scan and the `--facts` preview (v12). */
191
192
  const name = "evolution-commands";
193
+ const Config = z.object({
194
+ skillsRoot: z.string().default(""),
195
+ maintainCooldownMs: z.number().min(0).default(3e4),
196
+ maintainTimeoutMs: z.number().min(1).default(6e5),
197
+ threatExemptLabels: z.array(z.string()).default([])
198
+ });
192
199
  function apply(ctx, rawConfig = {}) {
193
200
  const config = rawConfig;
194
201
  let lastMaintainAt = 0;
@@ -391,7 +398,7 @@ function apply(ctx, rawConfig = {}) {
391
398
  const maintainArgs = /^maintain(?:\s+--timeout[ =](\d+))?\s*$/.exec(input);
392
399
  if (maintainArgs) {
393
400
  const runTimeoutMs = maintainArgs[1] ? Number(maintainArgs[1]) : config.maintainTimeoutMs ?? 6e5;
394
- if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs > 4294967295) return err("Invalid --timeout value: expected a positive integer number of milliseconds up to 4294967295 (e.g. /evolution maintain --timeout 600000).");
401
+ if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs > 4294967295) return err(maintainArgs[1] ? "Invalid --timeout value: expected a positive integer number of milliseconds up to 4294967295 (e.g. /evolution maintain --timeout 600000)." : "The maintainTimeoutMs config is invalid: expected a positive integer number of milliseconds up to 4294967295. Fix the evolution-commands row config (maintainTimeoutMs), then retry.");
395
402
  if (maintainInFlightSince > 0) return err(`Maintenance scan is already running (since ~${Math.max(1, Math.round((Date.now() - maintainInFlightSince) / 1e3))}s ago) — re-submitting now would cancel it. Wait for it to settle; the result appears when it finishes.`);
396
403
  const cooldownMs = clampedNumber(config.maintainCooldownMs, 3e4, { min: 0 });
397
404
  const sinceLast = Date.now() - lastMaintainAt;
@@ -422,7 +429,7 @@ function apply(ctx, rawConfig = {}) {
422
429
  catalogInvalid: () => enrichment.catalogInvalid,
423
430
  usageObserved: () => enrichment.usageObservedValue
424
431
  });
425
- lastMaintainRunId = outcome.runId ?? "";
432
+ if (outcome.ok) lastMaintainRunId = outcome.runId ?? "";
426
433
  if (!outcome.ok) return err(outcome.error ?? "Maintenance scan failed.");
427
434
  appendEvolutionEvent(ioRegistry.provider(), eventsFile(evolutionRoot()), {
428
435
  type: "maintain",
@@ -459,7 +466,9 @@ function apply(ctx, rawConfig = {}) {
459
466
  }, {
460
467
  name: "preset.yml",
461
468
  content: readFileSync(presetPath)
462
- }]);
469
+ }], void 0, (message) => {
470
+ ctx.logger.warn(message);
471
+ });
463
472
  return ok(`Evolution agent preset installed to ${target} (runtime standard + delta). Restart the session switcher to select it.`);
464
473
  } catch (error) {
465
474
  return err(`Preset install failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -565,7 +574,7 @@ const defaultFs = {
565
574
  * source (and mtime when available) so the caller knows the generation it
566
575
  * restored from.
567
576
  */
568
- function atomicWriteFiles(targetDir, writes, fs = defaultFs) {
577
+ function atomicWriteFiles(targetDir, writes, fs = defaultFs, logger = console.warn) {
569
578
  const stage = (name) => join(targetDir, `${name}.tmp`);
570
579
  const dupes = [...new Set(writes.map((write) => write.name).filter((name, index, all) => all.indexOf(name) !== index))];
571
580
  if (dupes.length > 0) throw new Error(`atomicWriteFiles: duplicate input names: ${dupes.join(", ")}`);
@@ -615,7 +624,7 @@ function atomicWriteFiles(targetDir, writes, fs = defaultFs) {
615
624
  try {
616
625
  if (fs.existsSync(finalPath)) fs.copyFileSync(finalPath, join(targetDir, `${name}.bak`));
617
626
  } catch (refreshError) {
618
- console.warn(`atomicWriteFiles: committed "${name}" but failed to refresh its .bak (${refreshError instanceof Error ? refreshError.message : String(refreshError)}); a later failed commit will recover to an OLDER generation`);
627
+ logger(`atomicWriteFiles: committed "${name}" but failed to refresh its .bak (${refreshError instanceof Error ? refreshError.message : String(refreshError)}); a later failed commit will recover to an OLDER generation`);
619
628
  }
620
629
  }
621
630
  } catch (error) {
@@ -642,4 +651,4 @@ function safeStagedArgs(args) {
642
651
  }
643
652
  }
644
653
  //#endregion
645
- export { apply, atomicWriteFiles, name };
654
+ export { Config, apply, atomicWriteFiles, name };
@@ -1,5 +1,10 @@
1
1
  export interface DoctorReport {
2
2
  installForm: 'full' | 'host' | 'preset' | 'layered' | 'none';
3
+ /** Aggregated across ALL profiles under `home` (N13, v12): doctor answers
4
+ * "is any profile carrying an evolution bundle / which install forms exist"
5
+ * — not "what this runtime mounted". `services.review` is the runtime-side
6
+ * counterpart (inferred from the install form, P0-1) and may disagree on a
7
+ * multi-profile machine; the render marks the aggregation explicitly. */
3
8
  bundles: string[];
4
9
  conflicts: string[];
5
10
  envIssues: string[];
@@ -3,6 +3,7 @@
3
3
  * @module @lmzhen/dsh-evolution-commands
4
4
  */
5
5
  import type { Context } from '@deepseek-ai/cordis';
6
+ import z from '@deepseek-ai/schemastery';
6
7
  export declare const name = "evolution-commands";
7
8
  export interface Config {
8
9
  /** Skill-tree root for maintain/restructure; empty uses skillsRoot().
@@ -32,6 +33,17 @@ export interface Config {
32
33
  * widens them. */
33
34
  threatExemptLabels?: string[] | undefined;
34
35
  }
36
+ export declare const Config: z<Schemastery.ObjectS<{
37
+ skillsRoot: z<string, string>;
38
+ maintainCooldownMs: z<number, number>;
39
+ maintainTimeoutMs: z<number, number>;
40
+ threatExemptLabels: z<string[], string[]>;
41
+ }>, Schemastery.ObjectT<{
42
+ skillsRoot: z<string, string>;
43
+ maintainCooldownMs: z<number, number>;
44
+ maintainTimeoutMs: z<number, number>;
45
+ threatExemptLabels: z<string[], string[]>;
46
+ }>>;
35
47
  export declare function apply(ctx: Context, rawConfig?: Config): void;
36
48
  /** F-211: the fs surface atomicWriteFiles uses — injectable so the commit-phase
37
49
  * rename-failure path is deterministically testable. Defaults to node:fs.
@@ -73,6 +85,6 @@ interface FsOps {
73
85
  export declare function atomicWriteFiles(targetDir: string, writes: Array<{
74
86
  name: string;
75
87
  content: string | Uint8Array;
76
- }>, fs?: FsOps): void;
88
+ }>, fs?: FsOps, logger?: (message: string) => void): void;
77
89
  export {};
78
90
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-commands",
3
3
  "description": "Human commands for the evolution family (/evolution pending|curator|maintain|doctor) (community build)",
4
- "version": "0.3.57",
4
+ "version": "0.3.59",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -30,12 +30,13 @@
30
30
  ],
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@lmzhen/dsh-evolution-approval": "^0.3.57",
34
- "@lmzhen/dsh-evolution-core": "^0.3.57",
35
- "@lmzhen/dsh-evolution-maintenance": "^0.3.57"
33
+ "@deepseek-ai/schemastery": "^3.18.1",
34
+ "@lmzhen/dsh-evolution-approval": "^0.3.59",
35
+ "@lmzhen/dsh-evolution-core": "^0.3.59",
36
+ "@lmzhen/dsh-evolution-maintenance": "^0.3.59"
36
37
  },
37
38
  "optionalDependencies": {
38
- "@lmzhen/dsh-evolution-agent-preset": "^0.3.57"
39
+ "@lmzhen/dsh-evolution-agent-preset": "^0.3.59"
39
40
  },
40
41
  "peerDependencies": {
41
42
  "@deepseek-ai/cordis": "^4.0.1",