@lmzhen/dsh-evolution-commands 0.3.64 → 0.3.66

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 CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
  import z from "@deepseek-ai/schemastery";
3
+ import { effectiveSessionPolicy } from "@lmzhen/dsh-evolution-approval";
3
4
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
4
5
  import { SkillLibrary, appendEvolutionEvent, buildLearnPrompt, clampedNumber, composePresetComposition, eventsFile, evolutionRoot, resolveRootConfig, resolveSkillsRoot } from "@lmzhen/dsh-evolution-core";
5
6
  import { buildEnrichment, buildMaintainFacts, runMaintain, snapshotFromLibrary } from "@lmzhen/dsh-evolution-maintenance";
@@ -76,12 +77,16 @@ async function diagnose(ctx, options = {}) {
76
77
  io: has("evolutionIo")
77
78
  };
78
79
  let pendingCount = null;
80
+ let executingCount = null;
79
81
  const approvalService = ctx.get("evolutionApproval");
80
82
  if (approvalService?.list) try {
81
83
  const rows = await approvalService.list("pending");
82
84
  pendingCount = Array.isArray(rows) ? rows.length : null;
85
+ const executing = await approvalService.list("executing");
86
+ executingCount = Array.isArray(executing) ? executing.length : null;
83
87
  } catch {
84
88
  pendingCount = null;
89
+ executingCount = null;
85
90
  }
86
91
  const installForm = full ? "full" : preset ? "preset" : layered ? "layered" : host ? "host" : "none";
87
92
  const actions = [];
@@ -92,6 +97,7 @@ async function diagnose(ctx, options = {}) {
92
97
  if (env.length > 0) actions.push("Fix the DSH_EVOLUTION_* variable listed above.");
93
98
  if (services.review && !services.curator) actions.push("Curator service is not mounted — automatic curation is off; verify the host/all bundle row set is complete.");
94
99
  if (pendingCount === null && services.approval) actions.push("Approval service is mounted but pending listing failed — check the evolution state service.");
100
+ if ((executingCount ?? 0) > 0) actions.push(`${executingCount} staged write(s) are stuck EXECUTING (the approving run crashed) — inspect with /evolution pending and reject them after verifying the write effect.`);
95
101
  return {
96
102
  installForm,
97
103
  bundles,
@@ -99,6 +105,7 @@ async function diagnose(ctx, options = {}) {
99
105
  envIssues: env,
100
106
  services,
101
107
  pendingCount,
108
+ executingCount,
102
109
  actions
103
110
  };
104
111
  }
@@ -107,7 +114,8 @@ function renderDoctorText(report) {
107
114
  `Evolution doctor — install form: ${report.installForm}`,
108
115
  `bundles (all profiles): ${report.bundles.length > 0 ? report.bundles.join(", ") : "(none)"}`,
109
116
  `services: review=${report.services.review} curator=${report.services.curator} approval=${report.services.approval} skillUsage=${report.services.skillUsage} io=${report.services.io}`,
110
- `pending: ${report.pendingCount === null ? "unknown" : report.pendingCount}`
117
+ `pending: ${report.pendingCount === null ? "unknown" : report.pendingCount}`,
118
+ `executing: ${report.executingCount === null ? "unknown" : report.executingCount}`
111
119
  ];
112
120
  if (report.conflicts.length > 0) lines.push("conflicts:", ...report.conflicts.map((line) => ` ! ${line}`));
113
121
  if (report.envIssues.length > 0) lines.push("env:", ...report.envIssues.map((line) => ` ! ${line}`));
@@ -327,6 +335,8 @@ function apply(ctx, rawConfig = {}) {
327
335
  ].join("\n"));
328
336
  }
329
337
  if (input === "restore" || input.startsWith("restore ")) {
338
+ const tail = input.slice(7).trim();
339
+ if (tail !== "") return err(`\`restore\` takes no arguments (got "${tail}"). Use \`restore\` for a whole-tree rollback, or \`skill restore <name>\` for one skill.`);
330
340
  const curator = ctx.get("evolutionCurator");
331
341
  const result = curator ? await curator.restoreSnapshot() : {
332
342
  ok: false,
@@ -411,7 +421,7 @@ function apply(ctx, rawConfig = {}) {
411
421
  const maintainArgs = /^maintain(?:\s+--timeout[ =](\d+))?\s*$/.exec(input);
412
422
  if (maintainArgs) {
413
423
  const runTimeoutMs = maintainArgs[1] ? Number(maintainArgs[1]) : config.maintainTimeoutMs ?? 6e5;
414
- 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.");
424
+ if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs > 2147483647) return err(maintainArgs[1] ? "Invalid --timeout value: expected a positive integer number of milliseconds up to 2147483647 (e.g. /evolution maintain --timeout 600000)." : "The maintainTimeoutMs config is invalid: expected a positive integer number of milliseconds up to 2147483647. Fix the evolution-commands row config (maintainTimeoutMs), then retry.");
415
425
  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.`);
416
426
  const cooldownMs = clampedNumber(config.maintainCooldownMs, 3e4, { min: 0 });
417
427
  const sinceLast = Date.now() - lastMaintainAt;
@@ -500,6 +510,28 @@ function apply(ctx, rawConfig = {}) {
500
510
  if (!toFile.startsWith("references/")) return err("to_file must live under references/ (log/detail destination).");
501
511
  const ioRegistry = ctx.get("evolutionIo");
502
512
  if (!ioRegistry) return err("Evolution IO registry not mounted — restructure unavailable.");
513
+ if (approval) {
514
+ const sessionPolicy = effectiveSessionPolicy(ctx, void 0);
515
+ if (approval.isEnabled !== false && sessionPolicy !== "never" && approval.stageForeground !== false && !approval.hasRunner("skill")) return err("Restructure cannot be staged: no skill replay runner is registered — mount the tool-skill-manage row (evolution-agent preset, or evolution-all) or disable evolution-approval.");
516
+ const decision = await approval.request({
517
+ kind: "skill",
518
+ summary: `/evolution restructure ${name}${planRunId ? ` (plan ${planRunId})` : ""}`,
519
+ args: {
520
+ operation: {
521
+ action: "restructure",
522
+ name,
523
+ restructure: [{
524
+ heading,
525
+ to_file: toFile
526
+ }]
527
+ },
528
+ origin: "foreground",
529
+ libraryOrigin: "foreground"
530
+ },
531
+ origin: "foreground"
532
+ });
533
+ if (decision.action === "staged") return ok(`${decision.message}${planRunId ? `\n[audit] plan=${planRunId}` : ""}`);
534
+ }
503
535
  const result = await new SkillLibrary(resolveSkillsRoot({ root: skillsRootValue }), ioRegistry.provider(), void 0, (event) => {
504
536
  ctx.emit("evolution/skill-mutated", event);
505
537
  }, void 0, config.threatExemptLabels ?? []).restructure(name, [{
@@ -16,6 +16,9 @@ export interface DoctorReport {
16
16
  io: boolean;
17
17
  };
18
18
  pendingCount: number | null;
19
+ /** v23 (AP-2): claimed-but-crashed records — the only state that needs an
20
+ * operator action (reject) to clear; surfaced separately from pending. */
21
+ executingCount: number | null;
19
22
  actions: string[];
20
23
  }
21
24
  /** Profile bundle rows for evolution-family packages across all profiles. */
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.64",
4
+ "version": "0.3.66",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -31,12 +31,12 @@
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
33
  "@deepseek-ai/schemastery": "^3.18.1",
34
- "@lmzhen/dsh-evolution-approval": "^0.3.64",
35
- "@lmzhen/dsh-evolution-core": "^0.3.64",
36
- "@lmzhen/dsh-evolution-maintenance": "^0.3.64"
34
+ "@lmzhen/dsh-evolution-approval": "^0.3.66",
35
+ "@lmzhen/dsh-evolution-core": "^0.3.66",
36
+ "@lmzhen/dsh-evolution-maintenance": "^0.3.66"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@lmzhen/dsh-evolution-agent-preset": "^0.3.64"
39
+ "@lmzhen/dsh-evolution-agent-preset": "^0.3.66"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@deepseek-ai/cordis": "^4.0.1",