@lmzhen/dsh-evolution-commands 0.23.0 → 0.24.0

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.
Files changed (2) hide show
  1. package/lib/index.js +95 -95
  2. package/package.json +6 -6
package/lib/index.js CHANGED
@@ -273,10 +273,10 @@ function presetProfileTarget(ctx) {
273
273
  * @returns the refusal text, or undefined when the base is usable here.
274
274
  */
275
275
  function baseRefusalReason(entry, servicePresent) {
276
- if (typeof entry.unsupported === "string" && entry.unsupported !== "") return `Base "${entry.name}" is registered as UNSUPPORTED: ${entry.unsupported}`;
276
+ if (typeof entry.unsupported === "string" && entry.unsupported !== "") return `基底「${entry.name}」被登记为 UNSUPPORTED(不受支持):${entry.unsupported}`;
277
277
  const service = entry.requires?.service;
278
278
  if (typeof service !== "string" || service === "") return void 0;
279
- return servicePresent(service) ? void 0 : `Base "${entry.name}" requires the "${service}" service, which this deployment does not provide — the generated preset would refuse to mount.`;
279
+ return servicePresent(service) ? void 0 : `基底 "${entry.name}" 需要 "${service}" 服务,而本部署没有提供它 —— 生成的预设会拒绝挂载。`;
280
280
  }
281
281
  /**
282
282
  * Resolve the platform base preset patch one `--base` composes.
@@ -423,7 +423,7 @@ function profilePatchText(profileDir) {
423
423
  function installExclusionTarget(mounted) {
424
424
  if (mounted === void 0 || mounted.dir === "") return {
425
425
  kind: "undecidable",
426
- reason: "no profile is mounted in this process, so the double-mount question cannot be answered here"
426
+ reason: "本进程没有挂载 profile,因此无法在这里回答双挂载问题"
427
427
  };
428
428
  let manifestFailure;
429
429
  const declared = profileBundles(mounted.dir, (error) => {
@@ -432,7 +432,7 @@ function installExclusionTarget(mounted) {
432
432
  const manifestCode = manifestFailure?.code;
433
433
  if (manifestFailure !== void 0 && manifestCode !== "ENOENT") return {
434
434
  kind: "undecidable",
435
- reason: "the mounted profile manifest could not be read"
435
+ reason: "读不出已挂载 profile 的清单"
436
436
  };
437
437
  return {
438
438
  kind: "mounted",
@@ -522,7 +522,7 @@ function presetIssues(presets) {
522
522
  * @returns one readable line per divergence, empty when there is nothing to compare.
523
523
  */
524
524
  function paramDivergences(platform) {
525
- if (platform.configuration === void 0) return ["the platform configuration surface (configEditor.configuration) is not mounted here — parameter divergences were NOT checked"];
525
+ if (platform.configuration === void 0) return ["平台上没有挂载配置面(configEditor.configuration):参数差异没有被检查"];
526
526
  const issues = [];
527
527
  for (const row of platform.configuration) {
528
528
  const override = asMapping(row.override);
@@ -539,7 +539,7 @@ function paramDivergences(platform) {
539
539
  }
540
540
  }
541
541
  if (platform.plugins === void 0) {
542
- issues.push("the platform plugin-row surface (pluginManager.listPlugins) is not mounted here — declared-but-unreachable parameters were NOT checked");
542
+ issues.push("平台上没有挂载插件行面(pluginManager.listPlugins):已声明但不可达的参数没有被检查");
543
543
  return issues;
544
544
  }
545
545
  const live = liveRowTails(platform.plugins);
@@ -921,7 +921,7 @@ async function diagnose(ctx, options = {}) {
921
921
  const conflicts = [];
922
922
  const bundles = collectEvolutionBundles(home, (error, scope) => {
923
923
  const detail = error instanceof Error ? error.message : String(error);
924
- conflicts.push(scope === "profiles-dir" ? `the home profiles directory could not be enumerated (${detail}) — bundle-based install-form and conflict checks are DEGRADED and may miss installed bundles` : `a profile manifest could not be read or parsed (${detail}) — this profile's bundle rows are UNKNOWN, so the install-form and conflict checks are DEGRADED and may miss installed bundles`);
924
+ conflicts.push(scope === "profiles-dir" ? `本 home 的 profiles 目录无法枚举(${detail}):基于 bundle 的安装形态与冲突检查已降级(DEGRADED),可能漏掉已安装的 bundle` : `本 profile 清单读不出来或无法解析(${detail}):本 profile 的 bundle 行为未知,因此安装形态与冲突检查已降级(DEGRADED),可能漏掉已安装的 bundle`);
925
925
  });
926
926
  const has = (name) => ctx.get(name) !== void 0;
927
927
  const capabilityAbsence = absentHostServices(has);
@@ -1079,7 +1079,7 @@ async function probeBounded(work, label) {
1079
1079
  timer = setTimeout(() => {
1080
1080
  resolve({
1081
1081
  ok: false,
1082
- message: `${label} did not answer within ${PROBE_TIMEOUT_MS}ms — the corpus is blocked (a concurrent writer can stall the observation) or the service is wedged; isolate the most recently written session and re-run`
1082
+ message: `${label} 在 ${PROBE_TIMEOUT_MS}ms 内没有应答:语料被阻塞(并发写入方可能拖住观测),或服务卡死。请隔离最近写入的会话后重试。`
1083
1083
  });
1084
1084
  }, PROBE_TIMEOUT_MS);
1085
1085
  });
@@ -1398,7 +1398,7 @@ const COMMAND_ENTRIES = [
1398
1398
  {
1399
1399
  readonly: false,
1400
1400
  usage: "release <id>",
1401
- summary: "把卡在执行中的写入放回待批窗口(先确认效果再批准 or reject)"
1401
+ summary: "把卡在执行中的写入放回待批窗口(先确认效果再批准或驳回)"
1402
1402
  },
1403
1403
  {
1404
1404
  readonly: true,
@@ -1498,12 +1498,12 @@ const COMMAND_ENTRIES = [
1498
1498
  {
1499
1499
  readonly: false,
1500
1500
  usage: "policy set <id> <value> [--expect <revision>]",
1501
- summary: "通过设置服务写入一个你可改的参数 (E3 only; E1/E2 stay in cordis.yml)"
1501
+ summary: "通过设置服务写入一个你可改的参数 (仅 E3;E1/E2 仍留在 cordis.yml)"
1502
1502
  },
1503
1503
  {
1504
1504
  readonly: true,
1505
1505
  usage: "params [--group <name>] [--json]",
1506
- summary: "列出全部参数:分组、档位、生效时机、来源与当前值(--json feeds scripts)"
1506
+ summary: "列出全部参数:分组、档位、生效时机、来源与当前值(--json 便于脚本处理)"
1507
1507
  },
1508
1508
  {
1509
1509
  readonly: false,
@@ -1699,12 +1699,12 @@ function newestRun(registry) {
1699
1699
  /** Sentence F, ONE wording for the three id-less forms (design `10` cell 13): an index that could
1700
1700
  * not be read must never answer as "there is no recent run" (G2/0.20.0). */
1701
1701
  function unreadableIndex(note) {
1702
- return `The home's run index is not readable (${note ?? "unknown reason"}) — this is NOT "there is no recent run".`;
1702
+ return `本 home 的运行索引读不出来(${note ?? "原因未知"}):这不等于「最近没有运行」。`;
1703
1703
  }
1704
1704
  /** The explicit-id twin of {@link unreadableIndex}, worded like `maintain status` so the four
1705
1705
  * readers cannot drift (review P1-1). */
1706
1706
  function unreadableForId(id, note) {
1707
- return `Run ${id} is not in this process's history, and the home's run index is not readable (${note ?? "unknown reason"}) — that is NOT proof the run never happened.`;
1707
+ return `运行 ${id} 不在本进程的历史里,且本 home 的运行索引读不出来(${note ?? "原因未知"}):但这不能证明那次运行没发生过。`;
1708
1708
  }
1709
1709
  /** The reader-facing report path: the `.md` digest beside the run's `.json` result. */
1710
1710
  function reportDigestPath(record) {
@@ -1849,7 +1849,7 @@ function apply(ctx, rawConfig = {}) {
1849
1849
  });
1850
1850
  runs = registry;
1851
1851
  registry.load().then((loaded) => {
1852
- if (!loaded.ok) ctx.logger.warn(`evolution-commands: the run index is not usable — ${loaded.note ?? "unknown reason"}`);
1852
+ if (!loaded.ok) ctx.logger.warn(`evolution-commands: the run index is not usable — ${loaded.note ?? "原因未知"}`);
1853
1853
  else if (loaded.note !== void 0) ctx.logger.warn(`evolution-commands: ${loaded.note}`);
1854
1854
  }).catch((error) => {
1855
1855
  ctx.logger.warn(`evolution-commands: could not read the run index (${error instanceof Error ? error.message : String(error)})`);
@@ -1888,8 +1888,8 @@ function apply(ctx, rawConfig = {}) {
1888
1888
  const listed = [...await approval.list("pending"), ...await approval.list("executing")];
1889
1889
  const pending = [...new Map(listed.map((row) => [row.id, row])).values()];
1890
1890
  const ttlMs = typeof approval.ttlMs === "number" && Number.isFinite(approval.ttlMs) ? approval.ttlMs : 0;
1891
- const ttlNote = ttlMs > 0 ? `\n(staged writes expire after ${ttlMs} ms: an expired write is closed as REJECTED and is never executed — stage it again if it is still wanted)` : "\n(staged writes never expire — the window waits for a decision; set the evolution-approval row pendingTtlMs to bound it)";
1892
- if (pending.length === 0) return ok("No pending evolution writes." + ttlNote);
1891
+ const ttlNote = ttlMs > 0 ? `\n(暂存写入 ${ttlMs} 毫秒后过期:过期即关闭为 REJECTED,且永不执行。若仍需要,请重新暂存。)` : "\n(staged writes never expire — the window waits for a decision; set the evolution-approval row pendingTtlMs to bound it)";
1892
+ if (pending.length === 0) return ok("没有待批准的自进化写入。" + ttlNote);
1893
1893
  const detailed = pendingParsed.flags.get("detail") === true;
1894
1894
  const nowMs = Date.now();
1895
1895
  const attribution = (p) => {
@@ -1931,22 +1931,22 @@ function apply(ctx, rawConfig = {}) {
1931
1931
  const curator = ctx.get("evolutionCurator");
1932
1932
  if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
1933
1933
  const result = await curator.run({ ignoreGates: true });
1934
- if (result.skipped !== void 0) return ok(`Curator run skipped (${result.skipped}): no curation pass was executed.\nrunId=${result.report.runId}`);
1935
- return ok(`Curator run complete: ${result.stale.length} stale, ${result.archived.length} archived, ${result.errors.length} failed.\nrunId=${result.report.runId}${result.report.snapshotPath ? `\nsnapshot=${result.report.snapshotPath}` : ""}`);
1934
+ if (result.skipped !== void 0) return ok(`策展轮已跳过(${result.skipped}):未执行策展过程。\nrunId=${result.report.runId}`);
1935
+ return ok(`策展轮完成:${result.stale.length} 项过期,${result.archived.length} 项已归档,${result.errors.length} 项失败。\nrunId=${result.report.runId}${result.report.snapshotPath ? `\nsnapshot=${result.report.snapshotPath}` : ""}`);
1936
1936
  }
1937
1937
  if (input === "curator pause" || input === "curator resume") {
1938
1938
  const curator = ctx.get("evolutionCurator");
1939
1939
  if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
1940
1940
  const paused = input === "curator pause";
1941
1941
  await curator.setPaused(paused);
1942
- const notPersisted = ctx.get("evolutionState") !== void 0 ? "" : "\nNOTE: no evolution state service is mounted — this setting is NOT persisted and will not survive this process.";
1943
- return ok((paused ? "Curator automatic curation paused. Manual /evolution curator run is unaffected; resume with /evolution curator resume." : "Curator automatic curation resumed. The next scheduled pass waits one interval (first-run defer semantics).") + notPersisted);
1942
+ const notPersisted = ctx.get("evolutionState") !== void 0 ? "" : "\n注意:没有挂载 evolution 状态服务 —— 该设置不会被持久化,也不会在此进程之后保留。";
1943
+ return ok((paused ? "策展自动轮已暂停。手动 /evolution curator run 不受影响;用 /evolution curator resume 恢复。" : "策展自动轮已恢复。下一次定时轮要等一个间隔(首轮延后语义)。") + notPersisted);
1944
1944
  }
1945
1945
  if (input === "curator status") {
1946
1946
  const curator = ctx.get("evolutionCurator");
1947
1947
  if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
1948
1948
  const state = await curator.status();
1949
- if (!state) return ok("No curator state yet: the first automatic pass is deferred until the interval elapses.");
1949
+ if (!state) return ok("还没有策展状态:首个自动轮次要等间隔到达后才会执行。");
1950
1950
  const lastRun = typeof state.lastRunAt === "number" && Number.isFinite(state.lastRunAt) && state.lastRunAt > 0 ? new Date(state.lastRunAt).toISOString() : "unknown";
1951
1951
  return ok([
1952
1952
  `paused=${state.paused}`,
@@ -1960,9 +1960,9 @@ function apply(ctx, rawConfig = {}) {
1960
1960
  if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
1961
1961
  const records = await curator.skills.listMutations();
1962
1962
  const usable = Array.isArray(records) ? records.filter((row) => typeof row === "object" && row !== null && typeof row.at === "string" && typeof row.skillName === "string" && typeof row.action === "string" && typeof row.summary === "string") : [];
1963
- if (usable.length === 0) return ok("No mutation records yet.");
1963
+ if (usable.length === 0) return ok("还没有写入记录。");
1964
1964
  const recent = usable.slice(-5).reverse().map((record) => `${record.at.slice(0, 19)} ${record.skillName} ${record.action} ${record.summary}`);
1965
- return ok(`Mutations: ${usable.length} recorded (recent 5):\n${recent.join("\n")}`);
1965
+ return ok(`写入记录:已记录 ${usable.length} 条(最近 5 条):\n${recent.join("\n")}`);
1966
1966
  }
1967
1967
  if (input === "curator scope") {
1968
1968
  const curator = ctx.get("evolutionCurator");
@@ -1982,8 +1982,8 @@ function apply(ctx, rawConfig = {}) {
1982
1982
  const curator = ctx.get("evolutionCurator");
1983
1983
  if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
1984
1984
  const report = await curator.latestReport();
1985
- if (!report) return ok("No curator report available.");
1986
- if (typeof report !== "object" || typeof report.runId !== "string" || typeof report.startedAt !== "string" || !Array.isArray(report.archived) || !Array.isArray(report.failed)) return err("Report file unreadable.");
1985
+ if (!report) return ok("暂无策展报告。");
1986
+ if (typeof report !== "object" || typeof report.runId !== "string" || typeof report.startedAt !== "string" || !Array.isArray(report.archived) || !Array.isArray(report.failed)) return err("报告文件读不出来。");
1987
1987
  const reportAny = report;
1988
1988
  const nameOf = (item) => typeof item === "object" && item !== null && typeof item.name === "string" ? item.name : "?";
1989
1989
  const reasonOf = (item) => typeof item === "object" && item !== null && typeof item.reason === "string" ? item.reason : "?";
@@ -2000,7 +2000,7 @@ function apply(ctx, rawConfig = {}) {
2000
2000
  }
2001
2001
  if (input === "restore" || input.startsWith("restore ")) {
2002
2002
  const tail = input.slice(7).trim();
2003
- if (tail !== "") return err(`\`restore\` takes no arguments (got "${tail}"). Use \`restore\` for a whole-tree rollback, or \`skill restore <name>\` for one skill.`);
2003
+ if (tail !== "") return err(`\`restore\` 不接受参数(收到 "${tail}")。\`restore\` 做整树回滚,\`skill restore <name>\` 恢复单个技能。`);
2004
2004
  const restoreRefusal = unreplayableWriteRefusal("restore");
2005
2005
  if (restoreRefusal) return restoreRefusal;
2006
2006
  const curator = ctx.get("evolutionCurator");
@@ -2016,7 +2016,7 @@ function apply(ctx, rawConfig = {}) {
2016
2016
  const planTail = /\s--plan\s+(\S+)\s*$/.exec(input) ?? null;
2017
2017
  const planRunId = planTail?.[1] ?? void 0;
2018
2018
  const [target, ...sources] = (planTail ? input.slice(0, planTail.index) : input).slice(12).trim().split(/\s+/).filter(Boolean);
2019
- if (!target || sources.length === 0) return err("Usage: /evolution consolidate <target> <source...>");
2019
+ if (!target || sources.length === 0) return err("用法:/evolution consolidate <target> <source...>");
2020
2020
  const curator = ctx.get("evolutionCurator");
2021
2021
  const result = curator ? await curator.consolidate(target, sources) : {
2022
2022
  ok: false,
@@ -2027,7 +2027,7 @@ function apply(ctx, rawConfig = {}) {
2027
2027
  }
2028
2028
  if (input.startsWith("skill restore ")) {
2029
2029
  const name = input.slice(14).trim();
2030
- if (!name) return err("Usage: /evolution skill restore <name>");
2030
+ if (!name) return err("用法:/evolution skill restore <name>");
2031
2031
  const skillRestoreRefusal = unreplayableWriteRefusal("skill restore");
2032
2032
  if (skillRestoreRefusal) return skillRestoreRefusal;
2033
2033
  const curator = ctx.get("evolutionCurator");
@@ -2039,22 +2039,22 @@ function apply(ctx, rawConfig = {}) {
2039
2039
  }
2040
2040
  if (input.startsWith("skill history ")) {
2041
2041
  const name = input.slice(14).trim();
2042
- if (!name) return err("Usage: /evolution skill history <name>");
2042
+ if (!name) return err("用法:/evolution skill history <name>");
2043
2043
  const curator = ctx.get("evolutionCurator");
2044
2044
  if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
2045
2045
  const versions = await curator.history(name);
2046
- if (versions.length === 0) return ok(`No content versions are recorded for "${name}" yet — they appear after the next write through skill_manage.`);
2046
+ if (versions.length === 0) return ok(`技能 "${name}" 还没有内容版本:下一次经 skill_manage 写入后才会出现。`);
2047
2047
  const groups = partitionVersions(versions);
2048
2048
  const row = (entry) => `v${entry.v}\t${entry.at}\t${entry.action}\t${entry.chars} chars\t${entry.hash.slice(0, 12)}`;
2049
- const lines = [`Content versions for "${name}" (oldest first, ${groups.content.length} of at most the retained count):`, ...groups.content.map(row)];
2050
- if (groups.support.length > 0) lines.push("Support-file versions (history only — undo restores SKILL.md, not these bytes):", ...groups.support.map(row));
2049
+ const lines = [`技能 "${name}" 的内容版本(由旧到新,${groups.content.length} 条,最多保留这么多):`, ...groups.content.map(row)];
2050
+ if (groups.support.length > 0) lines.push("支撑文件版本(仅在历史里 —— 撤销恢复的是 SKILL.md,不是这些字节):", ...groups.support.map(row));
2051
2051
  return ok(lines.join("\n"));
2052
2052
  }
2053
2053
  if (input.startsWith("skill undo ")) {
2054
2054
  const rest = input.slice(11).trim();
2055
2055
  const toMatch = /--to\s+v?(\d+)\s*$/.exec(rest);
2056
2056
  const name = (toMatch?.index === void 0 ? rest : rest.slice(0, toMatch.index)).trim();
2057
- if (!name) return err("Usage: /evolution skill undo <name> [--to v<N>]");
2057
+ if (!name) return err("用法:/evolution skill undo <name> [--to v<N>]");
2058
2058
  const skillUndoRefusal = unreplayableWriteRefusal("skill undo");
2059
2059
  if (skillUndoRefusal) return skillUndoRefusal;
2060
2060
  const curator = ctx.get("evolutionCurator");
@@ -2068,9 +2068,9 @@ function apply(ctx, rawConfig = {}) {
2068
2068
  if (input === "skill pin" || input.startsWith("skill pin ") || input === "skill unpin" || input.startsWith("skill unpin ")) {
2069
2069
  const pinned = !input.startsWith("skill unpin");
2070
2070
  const name = input.slice(pinned ? 10 : 12).trim();
2071
- if (!name) return err(`Usage: /evolution skill ${pinned ? "pin" : "unpin"} <name>`);
2071
+ if (!name) return err(`用法:/evolution skill ${pinned ? "pin" : "unpin"} <name>`);
2072
2072
  const ioRegistry = ctx.get("evolutionIo");
2073
- if (!ioRegistry) return err("Evolution IO registry not mounted — skill pinning unavailable.");
2073
+ if (!ioRegistry) return err("未挂载 evolution-io 注册表:无法固定或取消固定技能。");
2074
2074
  const result = await newSkillLibrary({
2075
2075
  config: { root: skillsRootValue },
2076
2076
  io: preferProvider(ioRegistry, ["fs"]),
@@ -2086,14 +2086,14 @@ function apply(ctx, rawConfig = {}) {
2086
2086
  const curator = ctx.get("evolutionCurator");
2087
2087
  if (!curator) return err(errorText("e-302-curator-service-not-mounted"));
2088
2088
  const [rows, observed] = await Promise.all([curator.healthView(), curator.usageObserved()]);
2089
- const banner = observed ? "" : "Usage observation not yet established — churn (write-ghost) rows are suppressed.";
2089
+ const banner = observed ? "" : "使用观测尚未建立 —— 频繁变动(写入幽灵)行已被抑制。";
2090
2090
  const line = (row) => `${row.verdict.padEnd(18)} ${row.name}${row.reasons.length > 0 ? ` — ${row.reasons.join("; ")}` : ""}`;
2091
2091
  if (rows.length === 0) return ok(banner ? `Structure health: all skills healthy. ${banner}` : "Structure health: all skills healthy.");
2092
2092
  return ok([banner ? `Structure health (${rows.length} degraded): ${banner}` : `Structure health (${rows.length} degraded):`, ...rows.map(line)].join("\n"));
2093
2093
  }
2094
2094
  if (input === "skills refresh") {
2095
2095
  ctx.emit("evolution/skills-refresh");
2096
- return ok("Skill catalog refresh requested: caches dropped, catalog re-read on next lookup.");
2096
+ return ok("已请求重读技能目录:缓存已丢弃,下次查询时重新读取。");
2097
2097
  }
2098
2098
  if (input === "learn" || input.startsWith("learn ")) {
2099
2099
  const request = rawInputTrimmed === "learn" ? "" : rawInputTrimmed.slice(6).trim();
@@ -2125,12 +2125,12 @@ function apply(ctx, rawConfig = {}) {
2125
2125
  }).catch((error) => {
2126
2126
  ctx.logger.warn(`evolution-commands: failed to record learn event: ${String(error)}`);
2127
2127
  });
2128
- return woke ? ok("Learning request sent to this session. Follow it now.") : ok("Learning request queued for this session — this host exposes no wake-up channel, so it is read on your next message.");
2128
+ return woke ? ok("已向本会话发送学习请求,请现在执行。") : ok("学习请求已排入本会话队列:本宿主没有唤醒通道,会在你下一条消息时读取。");
2129
2129
  }
2130
2130
  const factsParsed = parseSubcommand(input);
2131
2131
  if (!isParseFailure(factsParsed) && factsParsed.name === "maintain" && factsParsed.flags.get("facts") === true && factsParsed.positionals.length === 0) {
2132
2132
  const ioRegistry = ctx.get("evolutionIo");
2133
- if (!ioRegistry) return err("Evolution IO registry not mounted — maintenance facts unavailable.");
2133
+ if (!ioRegistry) return err("未挂载 evolution-io 注册表:维护事实不可用。");
2134
2134
  const library = newSkillLibrary({
2135
2135
  config: { root: skillsRootValue },
2136
2136
  io: preferProvider(ioRegistry, ["fs"])
@@ -2144,31 +2144,31 @@ function apply(ctx, rawConfig = {}) {
2144
2144
  ctx.logger.warn(`evolution-maintenance: skipping unreadable skill "${name}": ${error instanceof Error ? error.message : String(error)}`);
2145
2145
  }
2146
2146
  });
2147
- if (snapshots.length === 0 && readFailures.length > 0) return err(`maintenance scan could not read ${readFailures.length} listed skill(s) (${readFailures.slice(0, 10).join(", ")}${readFailures.length > 10 ? ", …" : ""}) and read no skill at all — the library was NOT audited; fix the unreadable skills (or their directory names) and run the scan again`);
2148
- if (snapshots.length === 0 && skillsRootValue !== "" && !await preferProvider(ioRegistry, ["fs"]).exists(skillsRootValue)) return err(`maintenance scan found an empty skill library, but the configured skill root does not exist (${skillsRootValue}) — point the skillsRoot config at a real directory (a literal \`~\` is not expanded) and run the scan again`);
2149
- if (snapshots.length === 0) return ok("Maintenance scan: empty skill library. Nothing to do.");
2147
+ if (snapshots.length === 0 && readFailures.length > 0) return err(`维护扫描读不出 ${readFailures.length} 个已登记技能(${readFailures.slice(0, 10).join(", ")}${readFailures.length > 10 ? ", …" : ""}),且一个技能都没读到:技能库未被审计。请修好读不出的技能(或它们的目录名)后重新扫描`);
2148
+ if (snapshots.length === 0 && skillsRootValue !== "" && !await preferProvider(ioRegistry, ["fs"]).exists(skillsRootValue)) return err(`维护扫描发现技能库为空,但配置的技能根目录不存在(${skillsRootValue}):请把 skillsRoot 指向真实目录(字面量 \`~\` 不会被展开),然后重新扫描`);
2149
+ if (snapshots.length === 0) return ok("维护扫描:技能库为空,无需处理。");
2150
2150
  const { facts } = buildMaintainFacts(snapshots, enrichment.usageObservedValue, void 0);
2151
- return ok(`Maintenance facts (0-token preview):\n${facts}`);
2151
+ return ok(`维护事实(零 token 预览):\n${facts}`);
2152
2152
  }
2153
2153
  const maintainParsed = parseSubcommand(input);
2154
2154
  const maintainFlagsDeclared = [...isParseFailure(maintainParsed) ? [] : maintainParsed.flags.keys()].every((flag) => flagsOf("maintain").includes("--" + flag));
2155
2155
  if (!isParseFailure(maintainParsed) && maintainParsed.name === "maintain" && maintainParsed.positionals.length === 0 && maintainFlagsDeclared) {
2156
2156
  const timeoutFlag = maintainParsed.flags.get("timeout");
2157
2157
  const runTimeoutMs = typeof timeoutFlag === "string" ? Number(timeoutFlag) : config.maintainTimeoutMs ?? 6e5;
2158
- if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs > MAX_TIMER_DELAY_MS) return err(timeoutFlag !== void 0 ? `Invalid --timeout value: expected a positive integer number of milliseconds up to ${MAX_TIMER_DELAY_MS} (e.g. /evolution maintain --timeout 600000).` : `The maintainTimeoutMs config is invalid: expected a positive integer number of milliseconds up to ${MAX_TIMER_DELAY_MS}. Fix the evolution-commands row config (maintainTimeoutMs), then retry.`);
2158
+ if (!Number.isSafeInteger(runTimeoutMs) || runTimeoutMs <= 0 || runTimeoutMs > MAX_TIMER_DELAY_MS) return err(timeoutFlag !== void 0 ? `--timeout 值不合法:应为不超过 ${MAX_TIMER_DELAY_MS} 的正整数毫秒(例如 /evolution maintain --timeout 600000)。` : `maintainTimeoutMs 配置不合法:应为不超过 ${MAX_TIMER_DELAY_MS} 的正整数毫秒。请修正 evolution-commands 行的配置(maintainTimeoutMs)后重试。`);
2159
2159
  const registry = runs;
2160
- if (!registry) return err("Evolution IO registry not mounted — maintenance scan unavailable.");
2160
+ if (!registry) return err("未挂载 evolution-io 注册表:维护扫描不可用。");
2161
2161
  const synced = await syncRuns(registry);
2162
2162
  if (!synced.ok) ctx.logger.warn(`evolution-commands: ${synced.note ?? "run index unreadable"} — the in-flight guard cannot see other processes' runs`);
2163
2163
  else if (synced.note !== void 0) ctx.logger.warn(`evolution-commands: ${synced.note}`);
2164
2164
  const ioRegistry = ctx.get("evolutionIo");
2165
2165
  const subagents = ctx.get("subagents");
2166
- if (!ioRegistry) return err("Evolution IO registry not mounted — maintenance scan unavailable.");
2167
- if (!subagents) return err("Subagents service not mounted — maintenance scan unavailable.");
2166
+ if (!ioRegistry) return err("未挂载 evolution-io 注册表:维护扫描不可用。");
2167
+ if (!subagents) return err("未挂载子智能体服务:维护扫描不可用。");
2168
2168
  const running = registry.inFlight();
2169
2169
  if (running) {
2170
2170
  const elapsed = Math.max(1, Math.round((Date.now() - running.startedAt) / 1e3));
2171
- return err(`Maintenance run ${running.id} is already running (started ~${elapsed}s ago) — re-submitting now would start a second scan. Status: /evolution maintain status ${running.id}; stop it: /evolution maintain cancel ${running.id}.`);
2171
+ return err(`维护运行 ${running.id} 已经在进行中(约 ${elapsed}s 前启动):现在重交会再开一次扫描。查看状态:/evolution maintain status ${running.id};停止它:/evolution maintain cancel ${running.id}。`);
2172
2172
  }
2173
2173
  const cooldownMs = clampedNumber(config.maintainCooldownMs, 3e4, { min: 0 });
2174
2174
  const lastSettled = registry.lastSettledAt();
@@ -2176,7 +2176,7 @@ function apply(ctx, rawConfig = {}) {
2176
2176
  if (cooldownMs > 0 && sinceLast < cooldownMs) {
2177
2177
  const remaining = Math.ceil((cooldownMs - sinceLast) / 1e3);
2178
2178
  const latest = registry.runs().find((record) => record.state !== "running");
2179
- return err(`Maintenance cooldown active (${remaining}s)${latest === void 0 ? "" : ` — latest run ${latest.id}`}; re-running now would spend another model call.`);
2179
+ return err(`维护冷却中(${remaining}s)${latest === void 0 ? "" : `,最近一次运行 ${latest.id}`}:现在重跑会再消耗一次模型调用。`);
2180
2180
  }
2181
2181
  const runHome = evolutionHome();
2182
2182
  const runRoot = evolutionRoot();
@@ -2267,7 +2267,7 @@ function apply(ctx, rawConfig = {}) {
2267
2267
  } catch (error) {
2268
2268
  ctx.logger.warn(`evolution-commands: automatic report handoff failed (${String(error)})`);
2269
2269
  }
2270
- } else ctx.logger.warn(`evolution-commands: maintenance run ${handle.id} produced no plan (${outcome.error ?? "unknown reason"})`);
2270
+ } else ctx.logger.warn(`evolution-commands: maintenance run ${handle.id} produced no plan (${outcome.error ?? "原因未知"})`);
2271
2271
  } catch (error) {
2272
2272
  const aborted = handle.signal.aborted;
2273
2273
  const failure = aborted ? "cancelled: the scan was stopped before it settled" : `Maintenance scan failed: ${error instanceof Error ? error.message : String(error)}`;
@@ -2288,20 +2288,20 @@ function apply(ctx, rawConfig = {}) {
2288
2288
  const maintainStatus = subcommandOf(input, "maintain", "status", flagsOf("maintain"));
2289
2289
  if (maintainStatus !== null) {
2290
2290
  const registry = runs;
2291
- if (!registry) return err("Evolution IO registry not mounted — run status unavailable.");
2291
+ if (!registry) return err("未挂载 evolution-io 注册表:无法查看运行状态。");
2292
2292
  const synced = await syncRuns(registry);
2293
2293
  const wanted = maintainStatus.positionals[1];
2294
2294
  if (wanted !== void 0) {
2295
2295
  const record = registry.find(wanted);
2296
2296
  if (!record) {
2297
- if (!synced.ok) return err(`Run ${wanted} is not in this process's history, and the home's run index is not readable (${synced.note ?? "unknown reason"}) — that is NOT proof the run never happened.`);
2298
- return err(`No run ${wanted} in this home — /evolution maintain status lists the recent ones.`);
2297
+ if (!synced.ok) return err(`运行 ${wanted} 不在本进程的历史里,且本 home 的运行索引读不出来(${synced.note ?? "原因未知"}):但这不能证明那次运行没发生过。`);
2298
+ return err(`本 home 里没有 ${wanted} 这次运行:用 /evolution maintain status 查看最近的几次。`);
2299
2299
  }
2300
- return ok(synced.ok ? renderRunRecord(record) : `${renderRunRecord(record)}\n(index not readable: ${synced.note ?? "unknown reason"} — only this process's view is shown)`);
2300
+ return ok(synced.ok ? renderRunRecord(record) : `${renderRunRecord(record)}\n(运行索引读不出来:${synced.note ?? "原因未知"} — only this process's view is shown)`);
2301
2301
  }
2302
- if (!synced.ok) return err(`The run history of this home is not readable (${synced.note ?? "unknown reason"}) — this is NOT "no runs". Fix or remove <evolutionHome>/runs.json to start a clean history.`);
2302
+ if (!synced.ok) return err(`本 home 的运行历史读不出来(${synced.note ?? "原因未知"}):这「不是」没有运行。要开始干净的历史,请修好或删除 <evolutionHome>/runs.json。`);
2303
2303
  const all = registry.runs();
2304
- if (all.length === 0) return ok("No maintenance run recorded in this home yet — /evolution maintain starts one.");
2304
+ if (all.length === 0) return ok("本 home 还没有维护运行记录:用 /evolution maintain 启动一次。");
2305
2305
  const live = all.filter((record) => record.state === "running");
2306
2306
  const recent = all.filter((record) => record.state !== "running").slice(0, 5);
2307
2307
  return ok([live.length === 0 ? "No maintenance run in flight." : `In flight:\n${live.map(renderRunRecord).join("\n")}`, recent.length === 0 ? "" : `Recent:\n${recent.map(renderRunRecord).join("\n")}`].filter((part) => part !== "").join("\n"));
@@ -2309,7 +2309,7 @@ function apply(ctx, rawConfig = {}) {
2309
2309
  const maintainReport = subcommandOf(input, "maintain", "report", flagsOf("maintain"));
2310
2310
  if (maintainReport !== null) {
2311
2311
  const registry = runs;
2312
- if (!registry) return err("Evolution IO registry not mounted — run results unavailable.");
2312
+ if (!registry) return err("未挂载 evolution-io 注册表:无法查看运行结果。");
2313
2313
  const synced = await syncRuns(registry);
2314
2314
  const wanted = maintainReport.positionals[1];
2315
2315
  if (wanted === void 0 && !synced.ok) return err(unreadableIndex(synced.note));
@@ -2317,22 +2317,22 @@ function apply(ctx, rawConfig = {}) {
2317
2317
  if (!record) {
2318
2318
  if (wanted !== void 0) {
2319
2319
  if (!synced.ok) return err(unreadableForId(wanted, synced.note));
2320
- return err(`No run ${wanted} in this home — /evolution maintain status lists the recent ones.`);
2320
+ return err(`本 home 里没有 ${wanted} 这次运行:用 /evolution maintain status 查看最近的几次。`);
2321
2321
  }
2322
- return err("No maintenance run recorded in this home yet — /evolution maintain starts one.");
2322
+ return err("本 home 还没有维护运行记录:用 /evolution maintain 启动一次。");
2323
2323
  }
2324
- if (wanted === void 0 && record.state === "running") return err(`The newest run ${record.id} is still running — its report appears when it settles; /evolution maintain status ${record.id} shows where it is.`);
2324
+ if (wanted === void 0 && record.state === "running") return err(`最新一次运行 ${record.id} 仍在进行:它结束后才会出报告;用 /evolution maintain status ${record.id} 查看进度。`);
2325
2325
  const ioRegistry = ctx.get("evolutionIo");
2326
- if (!ioRegistry) return err("Evolution IO registry not mounted — run results unavailable.");
2326
+ if (!ioRegistry) return err("未挂载 evolution-io 注册表:无法查看运行结果。");
2327
2327
  const probed = await readRunReport(preferProvider(ioRegistry, ["fs"]), record);
2328
- if (probed.kind === "missing") return err(`Run ${record.id} (${record.state}) has NO result: no report was written${record.failure === void 0 ? "" : ` (${record.failure})`}.`);
2329
- if (probed.kind === "unknown") return err(`Run ${record.id} has a report that could not be read (${probed.reason}) — this is not "no result".`);
2328
+ if (probed.kind === "missing") return err(`运行 ${record.id}(${record.state})没有结果:没有写出报告${record.failure === void 0 ? "" : `(${record.failure})`}。`);
2329
+ if (probed.kind === "unknown") return err(`运行 ${record.id} 有报告但读不出来(${probed.reason}):这「不是」没有结果。`);
2330
2330
  return ok(probed.text);
2331
2331
  }
2332
2332
  const maintainCancel = subcommandOf(input, "maintain", "cancel", flagsOf("maintain"));
2333
2333
  if (maintainCancel !== null) {
2334
2334
  const registry = runs;
2335
- if (!registry) return err("Evolution IO registry not mounted — run cancellation unavailable.");
2335
+ if (!registry) return err("未挂载 evolution-io 注册表:无法取消运行。");
2336
2336
  const synced = await syncRuns(registry);
2337
2337
  const wanted = maintainCancel.positionals[1];
2338
2338
  if (wanted === void 0 && !synced.ok) return err(unreadableIndex(synced.note));
@@ -2340,21 +2340,21 @@ function apply(ctx, rawConfig = {}) {
2340
2340
  if (!record) {
2341
2341
  if (wanted !== void 0) {
2342
2342
  if (!synced.ok) return err(unreadableForId(wanted, synced.note));
2343
- return err(`No run ${wanted} in this home — /evolution maintain status lists the recent ones.`);
2343
+ return err(`本 home 里没有 ${wanted} 这次运行:用 /evolution maintain status 查看最近的几次。`);
2344
2344
  }
2345
- return err("No maintenance run recorded in this home yet — /evolution maintain starts one.");
2345
+ return err("本 home 还没有维护运行记录:用 /evolution maintain 启动一次。");
2346
2346
  }
2347
- const idlessHint = wanted === void 0 ? " Pass an id to cancel a specific run: /evolution maintain status lists them." : "";
2347
+ const idlessHint = wanted === void 0 ? " 要取消某次运行请带上 id:/evolution maintain status 会列出它们。" : "";
2348
2348
  if (!registry.cancel(record.id)) {
2349
- if (record.state === "running") return err(`Run ${record.id} is running in ANOTHER process sharing this home — it can only be cancelled there.`);
2350
- return err(`Run ${record.id} is already ${record.state} — nothing to cancel.${idlessHint}`);
2349
+ if (record.state === "running") return err(`运行 ${record.id} 正在共享本 home 的另一个进程里运行:只能在那里取消。`);
2350
+ return err(`运行 ${record.id} 已经是 ${record.state}:没有可取消的东西。${idlessHint}`);
2351
2351
  }
2352
- return ok(`Maintenance run ${record.id} cancelled — the scan stops at its next checkpoint. /evolution maintain status ${record.id} shows the terminal state.`);
2352
+ return ok(`维护运行 ${record.id} 已取消:扫描会在下一个检查点停止。用 /evolution maintain status ${record.id} 查看终态。`);
2353
2353
  }
2354
2354
  const maintainHandoff = subcommandOf(input, "maintain", "handoff", flagsOf("maintain"));
2355
2355
  if (maintainHandoff !== null) {
2356
2356
  const registry = runs;
2357
- if (!registry) return err("Evolution IO registry not mounted — the report cannot be handed over.");
2357
+ if (!registry) return err("未挂载 evolution-io 注册表:无法交付报告。");
2358
2358
  const synced = await syncRuns(registry);
2359
2359
  const wanted = maintainHandoff.positionals[1];
2360
2360
  if (wanted === void 0 && !synced.ok) return err(unreadableIndex(synced.note));
@@ -2362,16 +2362,16 @@ function apply(ctx, rawConfig = {}) {
2362
2362
  if (!record) {
2363
2363
  if (wanted !== void 0) {
2364
2364
  if (!synced.ok) return err(unreadableForId(wanted, synced.note));
2365
- return err(`No run ${wanted} in this home — /evolution maintain status lists the recent ones.`);
2365
+ return err(`本 home 里没有 ${wanted} 这次运行:用 /evolution maintain status 查看最近的几次。`);
2366
2366
  }
2367
- return err("No maintenance run recorded in this home yet — /evolution maintain starts one.");
2367
+ return err("本 home 还没有维护运行记录:用 /evolution maintain 启动一次。");
2368
2368
  }
2369
- if (wanted === void 0 && record.state === "running") return err(`The newest run ${record.id} is still running — its report appears when it settles; /evolution maintain status ${record.id} shows where it is.`);
2369
+ if (wanted === void 0 && record.state === "running") return err(`最新一次运行 ${record.id} 仍在进行:它结束后才会出报告;用 /evolution maintain status ${record.id} 查看进度。`);
2370
2370
  const ioRegistry = ctx.get("evolutionIo");
2371
- if (!ioRegistry) return err("Evolution IO registry not mounted — the report cannot be handed over.");
2371
+ if (!ioRegistry) return err("未挂载 evolution-io 注册表:无法交付报告。");
2372
2372
  const probed = await readRunReport(preferProvider(ioRegistry, ["fs"]), record);
2373
- if (probed.kind === "missing") return err(`Run ${record.id} (${record.state}) has NO result: no report was written${record.failure === void 0 ? "" : ` (${record.failure})`}.`);
2374
- if (probed.kind === "unknown") return err(`Run ${record.id} has a report that could not be read (${probed.reason}) — this is not "no result".`);
2373
+ if (probed.kind === "missing") return err(`运行 ${record.id}(${record.state})没有结果:没有写出报告${record.failure === void 0 ? "" : `(${record.failure})`}。`);
2374
+ if (probed.kind === "unknown") return err(`运行 ${record.id} 有报告但读不出来(${probed.reason}):这「不是」没有结果。`);
2375
2375
  const missingAgent = agentMissing("handoff");
2376
2376
  if (missingAgent) return missingAgent;
2377
2377
  const woke = deliverHandoff(invocationAgent, createUserMessage({
@@ -2392,9 +2392,9 @@ function apply(ctx, rawConfig = {}) {
2392
2392
  }
2393
2393
  }));
2394
2394
  if (woke === void 0) return err(errorText("e-305-the-invocation-agent-exposes", { a1: "this maintenance handoff" }));
2395
- return ok(woke ? `Handed run ${record.id} to the model — report: ${reportDigestPath(record)}. It will read the file and follow the action lines.` : `Handed run ${record.id} to the model, queued — this host exposes no wake-up channel, so it is read on your next message.`);
2395
+ return ok(woke ? `已把运行 ${record.id} 交给模型 —— 报告:${reportDigestPath(record)}。它会读取该文件并执行其中的行动项。` : `已把运行 ${record.id} 交给模型并排队 —— 本宿主没有唤醒通道,因此会在你下一条消息时被读取。`);
2396
2396
  }
2397
- if (/^maintain\b/.test(input)) return err("Unknown maintain arguments: expected `maintain`, `maintain --timeout <ms>` / `maintain --timeout=<ms>`, `maintain status [<id>]`, `maintain report [<id>]`, `maintain handoff [<id>]` or `maintain cancel [<id>]`. Got: " + input);
2397
+ if (/^maintain\b/.test(input)) return err("未知的 maintain 参数:应为 `maintain`、`maintain --timeout <ms>` / `maintain --timeout=<ms>`、`maintain status [<id>]`、`maintain report [<id>]`、`maintain handoff [<id>]` 或 `maintain cancel [<id>]`。实际收到:" + input);
2398
2398
  const presetParsed = parseSubcommand(input);
2399
2399
  const presetInstall = isParseFailure(presetParsed) || presetParsed.name !== "preset" ? null : presetParsed.positionals[0] === "install" && presetParsed.positionals.length === 1 && [...presetParsed.flags.keys()].every((flag) => flagsOf("preset").includes("--" + flag)) ? presetParsed : false;
2400
2400
  if (presetInstall !== null && presetInstall !== false) {
@@ -2405,11 +2405,11 @@ function apply(ctx, rawConfig = {}) {
2405
2405
  dir: mounted.profileDir,
2406
2406
  bundles: mounted.bundles
2407
2407
  });
2408
- if (exclusion.kind === "undecidable") return err(`Refusing to install the layered Evolution preset: ${exclusion.reason} — the all/preset double-mount check could not run. Resolve access to this profile and retry, or install via the layered installer, which enforces the same exclusion up front.`);
2408
+ if (exclusion.kind === "undecidable") return err(`拒绝安装分层 Evolution 预设:${exclusion.reason}:all/preset 双重挂载检查无法执行。请解决该 profile 的访问权限后重试,或改用分层安装器——它会在安装前就执行同一套排除检查。`);
2409
2409
  const installedBundles = exclusion.bundles;
2410
2410
  const allBundle = installedBundles.find((name) => name === "dsh-evolution-all" || name.endsWith("/dsh-evolution-all"));
2411
2411
  const presetBundle = installedBundles.find((name) => name === "dsh-evolution-preset" || name.endsWith("/dsh-evolution-preset"));
2412
- if (allBundle || presetBundle) return err(`Refusing to install the layered Evolution preset: "${allBundle ?? presetBundle}" is installed in this profile — its model rows (tool-memory / tool-skill-manage / tool-session-query / skill-catalog) would double-mount with the preset's and the profile fails loud at startup. Keep ONE: remove the ${allBundle ? "evolution-all bundle" : "evolution-preset bundle"} before installing the layered preset (see /evolution doctor).`);
2412
+ if (allBundle || presetBundle) return err(`拒绝安装分层 Evolution 预设:本 profile 里已安装「${allBundle ?? presetBundle}」:它的模型行(tool-memory / tool-skill-manage / tool-session-query / skill-catalog)会与预设的重复挂载,profile 启动时会直接报错。只保留一个:安装分层预设前先移除 ${allBundle ? "evolution-all bundle" : "evolution-preset bundle"}(见 /evolution doctor)。`);
2413
2413
  }
2414
2414
  try {
2415
2415
  const source = resolveAgentPresetDir(import.meta.url);
@@ -2417,17 +2417,17 @@ function apply(ctx, rawConfig = {}) {
2417
2417
  const baseFlag = presetInstall.flags.get("base");
2418
2418
  const requestedRaw = typeof baseFlag === "string" ? baseFlag : table.defaultBase;
2419
2419
  const requested = [...new Set(requestedRaw.split(",").map((part) => part.trim()).filter((part) => part !== ""))];
2420
- if (requested.length === 0) return err(`No agent-preset base named — ${join(source, "bases.json")} lists ${table.entries.map((entry) => entry.name).join(", ")}`);
2420
+ if (requested.length === 0) return err(`没有指定 agent-preset 基名:${join(source, "bases.json")} 里列出的是 ${table.entries.map((entry) => entry.name).join(", ")}`);
2421
2421
  const selected = [];
2422
2422
  for (const name of requested) {
2423
2423
  const entry = table.entries.find((candidate) => candidate.name === name);
2424
- if (entry === void 0) return err(`Unknown agent-preset base "${name}" — ${join(source, "bases.json")} lists ${table.entries.map((candidate) => candidate.name).join(", ")}`);
2424
+ if (entry === void 0) return err(`未知的 agent-preset 基名「${name}」:${join(source, "bases.json")} 里列出的是 ${table.entries.map((candidate) => candidate.name).join(", ")}`);
2425
2425
  selected.push(entry);
2426
2426
  }
2427
2427
  const deltaPath = join(source, "agent.cordis.yml");
2428
- if (!existsSync(deltaPath)) return err(`Preset file missing from ${source} — is the dsh-evolution-agent-preset package installed?`);
2428
+ if (!existsSync(deltaPath)) return err(`预设文件在 ${source} 里缺失:是否装了 dsh-evolution-agent-preset 包?`);
2429
2429
  const profile = presetProfileTarget(ctx);
2430
- if (profile === void 0) return err("No profile is mounted in this process, so there is no profile patch to write the preset row into — run the command in a session started by `dsh --profile <name>`.");
2430
+ if (profile === void 0) return err("本进程没有挂载任何 profile,因此没有可写入预设行的 profile 补丁:请在由 `dsh --profile <name>` 启动的会话里执行该命令。");
2431
2431
  const delta = readFileSync(deltaPath, "utf8");
2432
2432
  const hmr = ctx.get("hmr");
2433
2433
  const commit = () => {
@@ -2456,33 +2456,33 @@ function apply(ctx, rawConfig = {}) {
2456
2456
  }], void 0, (message) => {
2457
2457
  ctx.logger.warn(message);
2458
2458
  });
2459
- return ok(`Evolution agent preset row installed (${written.join("; ")}). Restart the session switcher to select it.`);
2459
+ return ok(`已写入 evolution agent preset 行(${written.join("; ")})。重启会话切换器后即可选中它。`);
2460
2460
  };
2461
2461
  const runExclusive = hmr?.runExclusive;
2462
2462
  if (runExclusive === void 0) return commit();
2463
2463
  return await runExclusive.call(hmr, commit);
2464
2464
  } catch (error) {
2465
- return err(`Preset install failed: ${error instanceof Error ? error.message : String(error)}`);
2465
+ return err(`预设安装失败:${error instanceof Error ? error.message : String(error)}`);
2466
2466
  }
2467
2467
  }
2468
2468
  if (input.startsWith("restructure ")) {
2469
2469
  const restParsed = parseSubcommand(rawInputTrimmed);
2470
- if (isParseFailure(restParsed) || restParsed.name !== "restructure") return err("Usage: /evolution restructure <name> \"<## heading>\" <to_file>");
2470
+ if (isParseFailure(restParsed) || restParsed.name !== "restructure") return err("用法:/evolution restructure <name> \"<## heading>\" <to_file>");
2471
2471
  const name = restParsed.positionals[0] ?? "";
2472
2472
  const heading = restParsed.positionals[1] ?? "";
2473
2473
  const toFile = restParsed.positionals[2] ?? "";
2474
- if (name === "" || heading === "" || toFile === "") return err("Usage: /evolution restructure <name> \"<## heading>\" <to_file>");
2474
+ if (name === "" || heading === "" || toFile === "") return err("用法:/evolution restructure <name> \"<## heading>\" <to_file>");
2475
2475
  const planFlag = restParsed.flags.get("plan");
2476
2476
  const planRunId = typeof planFlag === "string" ? planFlag : void 0;
2477
- if (!toFile.startsWith("references/")) return err("to_file must live under references/ (log/detail destination).");
2477
+ if (!toFile.startsWith("references/")) return err("to_file 必须位于 references/ 之下(日志或明细的落地位置)。");
2478
2478
  const ioRegistry = ctx.get("evolutionIo");
2479
- if (!ioRegistry) return err("Evolution IO registry not mounted — restructure unavailable.");
2479
+ if (!ioRegistry) return err("未挂载 evolution-io 注册表:无法重构。");
2480
2480
  if (approval) {
2481
2481
  const session = invocationAgent?.session;
2482
2482
  const sessionPolicy = effectiveSessionPolicy(ctx, session);
2483
2483
  const stagesForeground = approval.isEnabled !== false && sessionPolicy !== "never" && approval.stageForeground !== false;
2484
2484
  if (stagesForeground && session === void 0) return err(errorText("e-306-this-deployment-stages-foreground-2"));
2485
- if (stagesForeground && !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.");
2485
+ if (stagesForeground && !approval.hasRunner("skill")) return err("无法暂存重构:没有注册技能回放运行器:请挂载 tool-skill-manage 行(evolution-agent 预设或 evolution-all),或禁用 evolution-approval。");
2486
2486
  const decision = await approval.request({
2487
2487
  kind: "skill",
2488
2488
  summary: `/evolution restructure ${name}${planRunId ? ` (plan ${planRunId})` : ""}`,
@@ -2556,7 +2556,7 @@ function apply(ctx, rawConfig = {}) {
2556
2556
  return ok(renderParamRows(selected, { providerMounted: provider !== void 0 }));
2557
2557
  }
2558
2558
  const policyParsed = parseSubcommand(input);
2559
- if (isParseFailure(policyParsed) && policyParsed.name === "policy" && policyParsed.kind === "missing-value") return err("/evolution policy set needs a value after --" + (policyParsed.flag ?? "") + "; usage: policy set <id> <value> [--expect <revision>]");
2559
+ if (isParseFailure(policyParsed) && policyParsed.name === "policy" && policyParsed.kind === "missing-value") return err("/evolution policy set 需要在 --" + (policyParsed.flag ?? "") + ";用法:policy set <id> <value> [--expect <revision>]");
2560
2560
  if (!isParseFailure(policyParsed) && policyParsed.name === "policy" && policyParsed.positionals[0] === "set") {
2561
2561
  const provider = ctx.get("settings");
2562
2562
  if (provider?.update === void 0 || provider.describe === void 0) return err(errorText("e-311-no-settings-service-is"));
@@ -2651,7 +2651,7 @@ function apply(ctx, rawConfig = {}) {
2651
2651
  return ok(renderDoctorText(report));
2652
2652
  }
2653
2653
  if (input === "" || input === "help") return ok(`自进化:记忆、技能、会话回顾、技能整理——状态、待批准写入与维护。\n${renderHelpText()}`);
2654
- return err(`/evolution ${input} is not a subcommand this build answers (a known subcommand whose argument is missing lands here too).\n${renderHint()}`);
2654
+ return err(`/evolution ${input} 不是本构建能应答的子命令(已知子命令但缺参数也会落到这里)。\n${renderHint()}`);
2655
2655
  } };
2656
2656
  /** The registered definition: declared members only (A46). */
2657
2657
  const evolutionCommand = {
@@ -2660,7 +2660,7 @@ function apply(ctx, rawConfig = {}) {
2660
2660
  input: { hint: renderHint() },
2661
2661
  handler: (invocation) => commandBody.run(invocation).catch((error) => ({
2662
2662
  kind: "error",
2663
- text: `evolution: command failed: ${error instanceof Error ? error.message : String(error)}\nRun /evolution doctor to inspect services and state files; a corrupted state file is quarantined as <file>.corrupt for inspection.`
2663
+ text: `evolution:命令失败:${error instanceof Error ? error.message : String(error)}\n请运行 /evolution doctor 检查服务与状态文件;损坏的状态文件会被隔离为 <file> 以便检查。`
2664
2664
  }))
2665
2665
  };
2666
2666
  commandCtx.effect(() => commands.register(evolutionCommand));
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.23.0",
4
+ "version": "0.24.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,18 +27,18 @@
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@deepseek-ai/schemastery": "^3.18.4",
30
- "@lmzhen/dsh-evolution-approval": "^0.23.0",
31
- "@lmzhen/dsh-evolution-core": "^0.23.0",
32
- "@lmzhen/dsh-evolution-maintenance": "^0.23.0"
30
+ "@lmzhen/dsh-evolution-approval": "^0.24.0",
31
+ "@lmzhen/dsh-evolution-core": "^0.24.0",
32
+ "@lmzhen/dsh-evolution-maintenance": "^0.24.0"
33
33
  },
34
34
  "optionalDependencies": {
35
- "@lmzhen/dsh-evolution-agent-preset": "^0.23.0"
35
+ "@lmzhen/dsh-evolution-agent-preset": "^0.24.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@deepseek-ai/cordis": "^4.0.1",
39
39
  "@deepseek-ai/dsh-commands": "^0.2.0-rc.1",
40
40
  "@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
41
- "@lmzhen/dsh-evolution-io": "^0.23.0"
41
+ "@lmzhen/dsh-evolution-io": "^0.24.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@deepseek-ai/dsh-commands": "^0.2.0-rc.1"