@lmzhen/dsh-evolution-core 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.
package/lib/index.js CHANGED
@@ -531,7 +531,7 @@ const PLATFORM_CATALOG_DESCRIPTION_DEFAULT = 500;
531
531
  * be copied into validateFrontmatter AND the patch path, and neither copy named
532
532
  * where the content should go — the upstream cap message names the destination
533
533
  * directories, and that is the part a model actually acts on. */
534
- const CONTENT_SPLIT_HINT = "Consider splitting into a smaller SKILL.md with supporting files in references/ or templates.";
534
+ const CONTENT_SPLIT_HINT = "建议拆成更小的 SKILL.md,把支撑文件放进 references/ 或 templates/。";
535
535
  /** V27 G2.4: the largest millisecond delay a timer accepts. `AbortSignal.timeout`
536
536
  * (and `setTimeout`) coerce anything larger to 1ms after a Node warning, so a
537
537
  * timeout configured above this ceiling silently collapses to "immediately
@@ -1052,16 +1052,16 @@ function shrinksOverLimit(next, current, limit) {
1052
1052
  }
1053
1053
  function validateFrontmatter(content, expectedName, limits = DEFAULT_SKILL_LIMITS, current) {
1054
1054
  const parsed = parseFrontmatter(content);
1055
- if (!parsed) return "SKILL.md must start with a `---` line, close the frontmatter with another exact `---` line (only a trailing `\\r` is tolerated), and include a body below it.";
1055
+ if (!parsed) return "SKILL.md 必须以 `---` 行开头,用另一个完全相同的 `---` 行结束 frontmatter(只容忍结尾的 `\\r`),并在其下包含正文。";
1056
1056
  const unreadable = parsed.platformStringSplit.filter((entry) => entry.kind === "sequence" || entry.kind === "mapping");
1057
- if (unreadable.length > 0) return `Frontmatter field ${unreadable.map((entry) => `"${entry.key}" (a YAML ${entry.kind})`).join(", ")} must be a string: the platform skill catalog reads such a field as absent and ignores the whole file. Write plain text, or wrap the value in double quotes to keep it literally.`;
1058
- if (!parsed.frontmatter.name) return "Frontmatter must include a name field.";
1059
- if (!SKILL_NAME_RE.test(parsed.frontmatter.name)) return `Invalid skill name "${parsed.frontmatter.name}" — use lowercase letters, digits, and hyphens.`;
1060
- if (parsed.frontmatter.name.length > limits.maxNameLength) return `Skill name exceeds ${limits.maxNameLength} characters.`;
1061
- if (expectedName && parsed.frontmatter.name !== expectedName) return `Frontmatter name "${parsed.frontmatter.name}" does not match target skill "${expectedName}".`;
1062
- if (!parsed.frontmatter.description) return "Frontmatter must include a description field.";
1063
- if (parsed.frontmatter.description.length > limits.maxDescriptionLength) return `Description exceeds ${limits.maxDescriptionLength} characters.`;
1064
- if (exceedsContentLimit(content, limits.maxSkillContentChars) && !shrinksOverLimit(content, current, limits.maxSkillContentChars)) return `SKILL.md content exceeds ${limits.maxSkillContentChars} characters. ${CONTENT_SPLIT_HINT}`;
1057
+ if (unreadable.length > 0) return `Frontmatter 字段 ${unreadable.map((entry) => `"${entry.key}" (a YAML ${entry.kind})`).join(", ")} 必须是字符串:平台技能目录会把这种字段当作缺失,并忽略整个文件。请写成纯文本,或用双引号包住取值以保持字面内容。`;
1058
+ if (!parsed.frontmatter.name) return "Frontmatter 必须包含 name 字段。";
1059
+ if (!SKILL_NAME_RE.test(parsed.frontmatter.name)) return `技能名「${parsed.frontmatter.name}」不合法:请只用小写字母、数字和连字符。`;
1060
+ if (parsed.frontmatter.name.length > limits.maxNameLength) return `技能名超过 ${limits.maxNameLength} 个字符。`;
1061
+ if (expectedName && parsed.frontmatter.name !== expectedName) return `Frontmatter 里的 name「${parsed.frontmatter.name}」与目标技能「${expectedName}」不一致。`;
1062
+ if (!parsed.frontmatter.description) return "Frontmatter 必须包含 description 字段。";
1063
+ if (parsed.frontmatter.description.length > limits.maxDescriptionLength) return `description 超过 ${limits.maxDescriptionLength} 个字符。`;
1064
+ if (exceedsContentLimit(content, limits.maxSkillContentChars) && !shrinksOverLimit(content, current, limits.maxSkillContentChars)) return `SKILL.md 内容超过 ${limits.maxSkillContentChars} 个字符。${CONTENT_SPLIT_HINT}`;
1065
1065
  return null;
1066
1066
  }
1067
1067
  /**
@@ -1076,8 +1076,8 @@ function authoringFeedback(frontmatter) {
1076
1076
  const over60 = description.length > 60;
1077
1077
  const hasColon = description.includes(":");
1078
1078
  const lines = [];
1079
- lines.push(over60 ? `Description is ${description.length}/60 characters — exceeds the 60-char authoring bar (Hermes standard; the catalog truncates at the configured platform cap).` : `Description ${description.length}/60 characters — within the authoring bar.`);
1080
- if (hasColon) lines.push("Description contains a colon — wrap the whole value in double quotes.");
1079
+ lines.push(over60 ? `描述为 ${description.length}/60 个字符 —— 超过 60 字符的作者规范上限(Hermes 标准;技能目录会按平台配置的上限截断)。` : `描述为 ${description.length}/60 个字符 —— 在作者规范上限之内。`);
1080
+ if (hasColon) lines.push("描述里含冒号 —— 请用双引号把整个取值包起来。");
1081
1081
  return {
1082
1082
  descriptionChars: description.length,
1083
1083
  over60,
@@ -3102,33 +3102,33 @@ function allowRowCollisions(env = process.env) {
3102
3102
  * @module @lmzhen/dsh-evolution-core
3103
3103
  */
3104
3104
  const EVOLUTION_ERRORS = Object.freeze({
3105
- "e-305-this-invocation-carries-no": "E-305: this invocation carries no agent — `%a1%` needs a session-backed call (run it from a session in the GUI or the CLI).",
3106
- "e-306-this-deployment-stages-foreground": "E-306: this deployment stages foreground writes, but `/evolution %a1%` is not replayable through the skill runner — there is nothing to stage. Run it from a session whose approval policy is 'never', or set `stageForeground: false` on the evolution-approval row, then repeat the command.",
3107
- "e-301-approval-service-not-mounted": "E-301: approval service not mounted — pending writes cannot be listed or replayed. Next: the evolution-approval row ships with evolution-host/evolution-all — run /evolution doctor to see which services are mounted.",
3108
- "e-301-approval-service-not-mounted-2": "E-301: approval service not mounted. Next: the evolution-approval row ships with evolution-host/evolution-all — run /evolution doctor to see which services are mounted.",
3109
- "e-304-the-mounted-approval-service": "E-304: the mounted approval service predates the release capability — reject the record instead.",
3110
- "e-302-curator-service-not-mounted": "E-302: curator service not mounted. Next: mount the evolution-curator row (evolution-host/evolution-all) and run /evolution doctor.",
3111
- "e-305-the-invocation-agent-exposes": "E-305: the invocation agent exposes neither `followup` nor `inject` — %a1% has no delivery channel.",
3112
- "e-306-this-deployment-stages-foreground-2": "E-306: this deployment stages foreground writes, but this invocation carries no agent session — `/evolution restructure` would stage a record with no session attribution. Run it from a session in the GUI or the CLI, or set `stageForeground: false` on the evolution-approval row, then repeat the command.",
3113
- "e-303-replay-service-not-mounted": "E-303: replay service not mounted. Next: mount the evolution-replay row (evolution-host/evolution-all) and run /evolution doctor.",
3114
- "e-307-the-settings-service-could": "E-307: the settings service could not report its sections (%a1%). /evolution params needs the user layer to tell an override from a deployment value; run /evolution doctor to see which services are mounted.",
3115
- "e-308-unknown-parameter-group-group": "E-308: unknown parameter group \"%a1%\" — known groups: %a2%.",
3116
- "e-311-no-settings-service-is": "E-311: no settings service is mounted, so there is no user layer to write. Mount the settings row (packages/settings/settings-file) and retry; this command never edits cordis.yml — a deployment value belongs to the deployment. /evolution doctor lists the mounted services.",
3117
- "e-312-error-instanceof-Error-error": "E-312: %a1% — /evolution params lists the canonical ids.",
3118
- "e-313-unknown-parameter-id-evolution": "E-313: unknown parameter \"%a1%\" — /evolution params lists every registered id with its tier and user layer.",
3119
- "e-314-id-is-a-deployment": "E-314: \"%a1%\" is a deployment parameter (tier %a2%, owner %a3%) — it is written in cordis.yml on its plugin or policy row, not from a session. /evolution params shows who may write each row.",
3120
- "e-315-id-has-no-user": "E-315: \"%a1%\" has no user layer — owner %a2% publishes no settings namespace, so the value stays with the deployment.",
3121
- "e-307-the-settings-service-could-2": "E-307: the settings service could not report its sections (%a1%). /evolution policy set needs the current revision to write safely; run /evolution doctor to see which services are mounted.",
3122
- "e-316-namespace-namespace-is-not": "E-316: namespace \"%a1%\" is not registered — owner %a2% is not mounted in this composition, so its parameters cannot be written from here. /evolution params marks those rows 'unregistered'.",
3123
- "e-309-revision-conflict-you-sent": "E-309: revision conflict — you sent %a1%, the document stands at %a2%. Re-read with /evolution params --json and retry.",
3124
- "e-309-revision-conflict-message-Re": "E-309: revision conflict — %a1%. Re-read with /evolution params --json and retry.",
3125
- "e-310-the-settings-service-refused": "E-310: the settings service refused the write: %a1% — the owning plugin's rule stands (a cross-field pair, or a cap that may only be tightened). /evolution params shows the current value.",
3126
- "e-317-skill-write-not-confirmed": "E-317: skill \"%a1%\" was not %a2% — the confirmation prompt was declined or dismissed, so nothing was written. The prompt appears on every create and bare delete; repeat the call only if the operator asks for it.",
3127
- "e-318-skill-write-without-a-read": "E-318: skill \"%a1%\" was not read in this session, so this write is refused. Read it with the `skill` tool first (a read that failed does not count), then repeat the write.",
3128
- "e-320-the-profile-home-is-not": "E-320: the profile home is not reported by this host, so the legacy settings document cannot be located. /evolution migrate reads `<profile home>/settings.yaml.imported`; run it from a profile-launched session.",
3129
- "e-322-a-parameter-would-break-a": "E-322: %a1% must be at least %a2%, but this write sets it to %a3%. Nothing was written.",
3130
- "e-321-no-io-provider-is": "E-321: no evolution-io provider is mounted, so the legacy settings document cannot be read. Mount the evolution-io row (evolution-host/evolution-all) and retry.",
3131
- "e-319-skill-write-confirm-timed-out": "E-319: skill \"%a1%\" was not %a2% — the confirmation prompt went unanswered for %a3% second(s), so the write was cancelled. Nobody was there to decide: set `skillWriteConfirm` to `auto` to write without a prompt, keep `ask` to wait until someone answers, or raise `skillWriteConfirmTimeoutSeconds`."
3105
+ "e-305-this-invocation-carries-no": "E-305: 本次调用没有携带 agent —— `%a1%` 需要由会话支撑的调用(请在 GUI 或 CLI 的会话里运行)。",
3106
+ "e-306-this-deployment-stages-foreground": "E-306: 本部署会暂存前台写入,但 `/evolution %a1%` 无法通过技能运行器回放 —— 没有可暂存的内容。请在批准策略为 'never' 的会话里运行,或在 evolution-approval 行上设置 `stageForeground: false`,然后重试该命令。",
3107
+ "e-301-approval-service-not-mounted": "E-301: 批准服务未挂载:待批准写入无法列出或回放。挂载 evolution-approval 行(随 evolution-host/evolution-all 提供)后,运行 /evolution doctor 可查看已挂载的服务。",
3108
+ "e-301-approval-service-not-mounted-2": "E-301: 批准服务未挂载。下一步:evolution-approval 行随 evolution-host/evolution-all 一起提供 —— 运行 /evolution doctor 查看已挂载的服务。",
3109
+ "e-304-the-mounted-approval-service": "E-304: 已挂载的批准服务早于本能力发布 —— 请改为驳回该记录。",
3110
+ "e-302-curator-service-not-mounted": "E-302: 策展服务未挂载。下一步:挂载 evolution-curator 行(evolution-host/evolution-all),并运行 /evolution doctor。",
3111
+ "e-305-the-invocation-agent-exposes": "E-305: 调用 agent 既没有暴露 `followup` 也没有 `inject` —— %a1% 没有投递通道。",
3112
+ "e-306-this-deployment-stages-foreground-2": "E-306: 本部署会暂存前台写入,但本次调用没有 agent 会话 —— `/evolution restructure` 会暂存一条没有会话归属的记录。请在 GUI 或 CLI 的会话里运行,或在 `stageForeground: false` 行上设置,然后重试该命令。",
3113
+ "e-303-replay-service-not-mounted": "E-303: 回放服务未挂载。下一步:挂载 evolution-replay 行(evolution-host/evolution-all),并运行 /evolution doctor。",
3114
+ "e-307-the-settings-service-could": "E-307: 设置服务无法报告它的分区(%a1%)。/evolution params 需要用户层来区分覆盖值与部署值;运行 /evolution doctor 查看已挂载的服务。",
3115
+ "e-308-unknown-parameter-group-group": "E-308: 未知的参数分组「%a1%」—— 已知分组:%a2%。",
3116
+ "e-311-no-settings-service-is": "E-311: 没有挂载设置服务,因此没有可写入的用户层。请挂载 settings 行(packages/settings/settings-file)后重试;本命令从不修改 cordis.yml —— 部署值属于部署。/evolution doctor 会列出已挂载的服务。",
3117
+ "e-312-error-instanceof-Error-error": "E-312: %a1% —— /evolution params 会列出规范 id。",
3118
+ "e-313-unknown-parameter-id-evolution": "E-313: 未知参数「%a1%」—— /evolution params 会列出每个已注册 id 及其层级与用户层。",
3119
+ "e-314-id-is-a-deployment": "E-314: 「%a1%」是部署参数(层级 %a2%,归属 %a3%)—— 它写在 cordis.yml 的插件行或策略行上,而不是从会话写入。/evolution params 会显示每一行由谁可写。",
3120
+ "e-315-id-has-no-user": "E-315: 「%a1%」没有用户层 —— 归属 %a2% 没有发布设置命名空间,因此该值留在部署层。",
3121
+ "e-307-the-settings-service-could-2": "E-307: 设置服务无法报告它的分区(%a1%)。/evolution policy set 需要当前修订号才能安全写入;运行 /evolution doctor 查看已挂载的服务。",
3122
+ "e-316-namespace-namespace-is-not": "E-316: namespace \"%a1%\" 未注册 —— 归属 %a2% 在本组合中未挂载,因此无法从这里写入它的参数。 /evolution params 会把那些行标为 'unregistered'.",
3123
+ "e-309-revision-conflict-you-sent": "E-309: 修订冲突 —— 你提交的是 %a1%,文档当前为 %a2%。请用 /evolution params --json 重新读取后重试。",
3124
+ "e-309-revision-conflict-message-Re": "E-309: 修订冲突 —— %a1%。请用 /evolution params --json 重新读取后重试。",
3125
+ "e-310-the-settings-service-refused": "E-310: 设置服务拒绝了这次写入:%a1% —— 归属插件的规则优先(跨字段成对约束,或只能收紧的上限)。/evolution params 会显示当前值。",
3126
+ "e-317-skill-write-not-confirmed": "E-317: 技能 \"%a1%\" 未被%a2% —— 确认提示被拒绝或关闭,因此没有写入任何内容。每次创建与裸删除都会出现该提示;只有操作者要求时才重复调用。",
3127
+ "e-318-skill-write-without-a-read": "E-318: 本会话没有读取技能 \"%a1%\",因此拒绝这次写入。请先用 `skill` 工具读取它(失败的读取不算),然后重复该写入。",
3128
+ "e-320-the-profile-home-is-not": "E-320: 本宿主没有报告 profile home,因此无法定位旧设置文档。/evolution migrate 读取 `<profile home>/settings.yaml.imported`;请在由 profile 启动的会话里运行。",
3129
+ "e-322-a-parameter-would-break-a": "E-322: %a1% 至少应为 %a2%,但这次写入把它设成 %a3%。未写入任何内容。",
3130
+ "e-321-no-io-provider-is": "E-321: 没有挂载 evolution-io 提供方,因此无法读取旧设置文档。请挂载 evolution-io 行(evolution-host/evolution-all)后重试。",
3131
+ "e-319-skill-write-confirm-timed-out": "E-319: 技能 \"%a1%\" 未被%a2% —— 确认提示在 %a3% 秒内无人应答,因此该写入被取消。没有人在场决定:把 `skillWriteConfirm` 设为 `auto` 可免提示直接写入,保留 `ask` 则一直等到有人应答,或提高 `skillWriteConfirmTimeoutSeconds`。"
3132
3132
  });
3133
3133
  /**
3134
3134
  * Render one table entry, substituting its interpolation slots.
@@ -3821,7 +3821,7 @@ var MemoryStore = class {
3821
3821
  const chars = entries.join(ENTRY_DELIMITER).length;
3822
3822
  if (this.failureCount > this.maxFailures) return {
3823
3823
  ok: false,
3824
- message: `Memory consolidation failed ${this.failureCount} times this turn. Stop retrying memory calls and continue with the user's task.${previewEntries(entries)}`,
3824
+ message: `本轮记忆整理已失败 ${this.failureCount} 次。请停止重试记忆调用,继续处理用户的任务。${previewEntries(entries)}`,
3825
3825
  entries,
3826
3826
  chars,
3827
3827
  limit: this.limitFor(target)
@@ -3884,10 +3884,10 @@ var MemoryStore = class {
3884
3884
  const oversized = await this.oversizedFile(target);
3885
3885
  if (!oversized) return null;
3886
3886
  const backup = await this.backupFile(target);
3887
- const suffix = backup ? ` A backup was saved to ${basename(backup)}.` : "";
3887
+ const suffix = backup ? ` 已把备份保存到 ${basename(backup)}。` : "";
3888
3888
  return {
3889
3889
  ok: false,
3890
- message: `Memory file is ${oversized.size} bytes (limit ${oversized.limit * READ_GUARD_FACTOR}) — skipping read.${suffix} Fix the file manually, then retry.`,
3890
+ message: `记忆文件为 ${oversized.size} 字节(上限 ${oversized.limit * READ_GUARD_FACTOR})—— 跳过读取。${suffix} 请手动修复该文件后重试。`,
3891
3891
  entries: [],
3892
3892
  chars: 0,
3893
3893
  limit: this.limitFor(target)
@@ -3920,7 +3920,7 @@ var MemoryStore = class {
3920
3920
  const size = await this.io.size?.(fileFor(this.root, target));
3921
3921
  if (typeof size === "number" && size > SHRINK_LOAD_CEILING) return {
3922
3922
  ok: false,
3923
- message: `Memory file is ${size} bytes - too large to load even for a remove-only batch. Fix the file manually, then retry.`,
3923
+ message: `记忆文件为 ${size} 字节 —— 即使只做删除批处理也过大、无法加载。请手动修复该文件后重试。`,
3924
3924
  entries: [],
3925
3925
  chars: 0,
3926
3926
  limit: this.limitFor(target)
@@ -3934,7 +3934,7 @@ var MemoryStore = class {
3934
3934
  });
3935
3935
  return outcome ?? {
3936
3936
  ok: false,
3937
- message: "internal error: the memory transaction did not invoke the task; no write was performed",
3937
+ message: "内部错误:记忆写事务没有调用任务;未执行任何写入",
3938
3938
  entries: [],
3939
3939
  chars: 0,
3940
3940
  limit: this.limitFor(target)
@@ -3946,7 +3946,7 @@ var MemoryStore = class {
3946
3946
  async addChained(target, facts) {
3947
3947
  if (!facts.trim()) return {
3948
3948
  ok: false,
3949
- message: "Content cannot be empty.",
3949
+ message: "内容不能为空。",
3950
3950
  entries: [],
3951
3951
  chars: 0,
3952
3952
  limit: this.limitFor(target)
@@ -3963,7 +3963,7 @@ var MemoryStore = class {
3963
3963
  if (!content) return {
3964
3964
  result: {
3965
3965
  ok: false,
3966
- message: "Content cannot be empty.",
3966
+ message: "内容不能为空。",
3967
3967
  entries: [],
3968
3968
  chars: 0,
3969
3969
  limit: this.limitFor(target)
@@ -3990,7 +3990,7 @@ var MemoryStore = class {
3990
3990
  if (hasEntryDelimiter(prefixed)) return {
3991
3991
  result: {
3992
3992
  ok: false,
3993
- message: "Fact contains the entry delimiter (§) and would split into multiple entries; rewrite it as separate facts.",
3993
+ message: "该条目含有分隔符(§),会被拆成多条;请改写为多条独立的事实。",
3994
3994
  entries: [],
3995
3995
  chars: 0,
3996
3996
  limit: this.limitFor(target)
@@ -4003,7 +4003,7 @@ var MemoryStore = class {
4003
4003
  return {
4004
4004
  result: {
4005
4005
  ok: true,
4006
- message: `Entry already exists (no duplicate added).${this.storageHint(target, entries.join(ENTRY_DELIMITER).length)}`,
4006
+ message: `该条目已存在(未重复添加)。${this.storageHint(target, entries.join(ENTRY_DELIMITER).length)}`,
4007
4007
  entries,
4008
4008
  chars: entries.join(ENTRY_DELIMITER).length,
4009
4009
  limit: this.limitFor(target)
@@ -4015,14 +4015,14 @@ var MemoryStore = class {
4015
4015
  const total = next.join(ENTRY_DELIMITER).length;
4016
4016
  const addLimit = this.limitFor(target);
4017
4017
  if (addLimit > 0 && total > addLimit) return {
4018
- result: this.failure(target, `Adding this entry would exceed the ${addLimit} char limit. Consolidate or remove stale entries, then retry.`, entries),
4018
+ result: this.failure(target, `添加该条目会超过 ${addLimit} 字符上限。请先合并或删除过期条目,再重试。`, entries),
4019
4019
  write: null
4020
4020
  };
4021
4021
  this.resetFailures();
4022
4022
  return {
4023
4023
  result: {
4024
4024
  ok: true,
4025
- message: `Entry added.${this.storageHint(target, total)}`,
4025
+ message: `已添加条目。${this.storageHint(target, total)}`,
4026
4026
  entries: next,
4027
4027
  chars: total,
4028
4028
  limit: this.limitFor(target)
@@ -4099,10 +4099,9 @@ var MemoryStore = class {
4099
4099
  if (shrinkOnly) return null;
4100
4100
  const limit = this.limitFor(target);
4101
4101
  const entries = normalizeEntries(raw);
4102
- const over = entries.filter((entry) => entry.length > limit).length;
4103
4102
  return {
4104
4103
  ok: false,
4105
- message: `${over} memory ${over === 1 ? "entry exceeds" : "entries exceed"} the configured ${target}CharLimit (${limit}); they were written under a higher limit. Raise the limit or remove entries — remove operations stay available.`,
4104
+ message: `${entries.filter((entry) => entry.length > limit).length} 条记忆超过了配置的 ${target}CharLimit(${limit});它们是在更高上限下写入的。请提高上限或删除条目 —— 删除类操作仍然可用。`,
4106
4105
  entries,
4107
4106
  chars: entries.join(ENTRY_DELIMITER).length,
4108
4107
  limit
@@ -4111,7 +4110,7 @@ var MemoryStore = class {
4111
4110
  const backup = await this.backupFile(target);
4112
4111
  return {
4113
4112
  ok: false,
4114
- message: `External drift detected in memory file.${backup ? ` A backup was saved to ${basename(backup)}.` : ""} Resolve the drift before retrying.`,
4113
+ message: `检测到记忆文件被外部改动。${backup ? ` 已把备份保存到 ${basename(backup)}。` : ""} 请先处理该漂移再重试。`,
4115
4114
  entries: [],
4116
4115
  chars: 0,
4117
4116
  limit: this.limitFor(target)
@@ -4123,7 +4122,7 @@ var MemoryStore = class {
4123
4122
  async applyBatchChained(target, operations) {
4124
4123
  if (operations.length === 0) return {
4125
4124
  ok: false,
4126
- message: "operations list is empty.",
4125
+ message: "operations 列表为空。",
4127
4126
  entries: [],
4128
4127
  chars: 0,
4129
4128
  limit: this.limitFor(target)
@@ -4148,7 +4147,7 @@ var MemoryStore = class {
4148
4147
  if (!body) return {
4149
4148
  result: {
4150
4149
  ok: false,
4151
- message: `Operation ${position} (add): facts is required. No operations were applied.${previewEntries(entries)}`,
4150
+ message: `第 ${position} 个操作(add):必须提供 facts。未应用任何操作。${previewEntries(entries)}`,
4152
4151
  entries,
4153
4152
  chars: entries.join(ENTRY_DELIMITER).length,
4154
4153
  limit: this.limitFor(target)
@@ -4159,7 +4158,7 @@ var MemoryStore = class {
4159
4158
  if (threat) return {
4160
4159
  result: {
4161
4160
  ok: false,
4162
- message: `Operation ${position}: ${threat}${previewEntries(entries)}`,
4161
+ message: `第 ${position} 个操作:${threat}${previewEntries(entries)}`,
4163
4162
  entries,
4164
4163
  chars: entries.join(ENTRY_DELIMITER).length,
4165
4164
  limit: this.limitFor(target)
@@ -4170,7 +4169,7 @@ var MemoryStore = class {
4170
4169
  if (hasEntryDelimiter(entryBody)) return {
4171
4170
  result: {
4172
4171
  ok: false,
4173
- message: `Operation ${position} (add): Fact contains the entry delimiter (§) and would split into multiple entries; rewrite it as separate facts.${previewEntries(entries)}`,
4172
+ message: `第 ${position} 个操作(add):该条目含有分隔符(§),会被拆成多条;请改写为多条独立的事实。${previewEntries(entries)}`,
4174
4173
  entries,
4175
4174
  chars: entries.join(ENTRY_DELIMITER).length,
4176
4175
  limit: this.limitFor(target)
@@ -4184,7 +4183,7 @@ var MemoryStore = class {
4184
4183
  if (rawAction !== "remove" && rawAction !== "replace") return {
4185
4184
  result: {
4186
4185
  ok: false,
4187
- message: `Operation ${position}: unknown action "${String(rawAction)}" (expected add/remove/replace). No operations were applied.${previewEntries(entries)}`,
4186
+ message: `第 ${position} 个操作:未知动作「${String(rawAction)}」(应为 add/remove/replace)。未应用任何操作。${previewEntries(entries)}`,
4188
4187
  entries,
4189
4188
  chars: entries.join(ENTRY_DELIMITER).length,
4190
4189
  limit: this.limitFor(target)
@@ -4195,7 +4194,7 @@ var MemoryStore = class {
4195
4194
  if (!needle) return {
4196
4195
  result: {
4197
4196
  ok: false,
4198
- message: `Operation ${position} (${op.action}): old_text is required. No operations were applied.${previewEntries(entries)}`,
4197
+ message: `第 ${position} 个操作(${op.action}):必须提供 old_text。未应用任何操作。${previewEntries(entries)}`,
4199
4198
  entries,
4200
4199
  chars: entries.join(ENTRY_DELIMITER).length,
4201
4200
  limit: this.limitFor(target)
@@ -4207,13 +4206,13 @@ var MemoryStore = class {
4207
4206
  matchIndex
4208
4207
  })).filter(({ entry }) => entry.includes(needle));
4209
4208
  if (matches.length === 0) return {
4210
- result: this.failure(target, `Operation ${position}: no entry matching "${needle}" found. No operations were applied.`, entries),
4209
+ result: this.failure(target, `第 ${position} 个操作:找不到匹配 "${needle}" 的条目。未应用任何操作。`, entries),
4211
4210
  write: null
4212
4211
  };
4213
4212
  if (new Set(matches.map((m) => m.entry)).size > 1) return {
4214
4213
  result: {
4215
4214
  ok: false,
4216
- message: `Operation ${position}: "${needle}" matched multiple distinct entries. No operations were applied.${previewEntries(entries)}`,
4215
+ message: `第 ${position} 个操作:「${needle}」匹配到多条不同条目。未应用任何操作。${previewEntries(entries)}`,
4217
4216
  entries,
4218
4217
  chars: entries.join(ENTRY_DELIMITER).length,
4219
4218
  limit: this.limitFor(target)
@@ -4227,7 +4226,7 @@ var MemoryStore = class {
4227
4226
  if (!body) return {
4228
4227
  result: {
4229
4228
  ok: false,
4230
- message: `Operation ${position} (replace): facts is required.${previewEntries(entries)}`,
4229
+ message: `第 ${position} 个操作(replace):必须提供 facts。${previewEntries(entries)}`,
4231
4230
  entries,
4232
4231
  chars: entries.join(ENTRY_DELIMITER).length,
4233
4232
  limit: this.limitFor(target)
@@ -4238,7 +4237,7 @@ var MemoryStore = class {
4238
4237
  if (threat) return {
4239
4238
  result: {
4240
4239
  ok: false,
4241
- message: `Operation ${position}: ${threat}${previewEntries(entries)}`,
4240
+ message: `第 ${position} 个操作:${threat}${previewEntries(entries)}`,
4242
4241
  entries,
4243
4242
  chars: entries.join(ENTRY_DELIMITER).length,
4244
4243
  limit: this.limitFor(target)
@@ -4249,7 +4248,7 @@ var MemoryStore = class {
4249
4248
  if (hasEntryDelimiter(entryBody)) return {
4250
4249
  result: {
4251
4250
  ok: false,
4252
- message: `Operation ${position} (replace): Fact contains the entry delimiter (§) and would split into multiple entries; rewrite it as separate facts.${previewEntries(entries)}`,
4251
+ message: `第 ${position} 个操作(replace):该条目含有分隔符(§),会被拆成多条;请改写为多条独立的事实。${previewEntries(entries)}`,
4253
4252
  entries,
4254
4253
  chars: entries.join(ENTRY_DELIMITER).length,
4255
4254
  limit: this.limitFor(target)
@@ -4262,14 +4261,14 @@ var MemoryStore = class {
4262
4261
  const total = working.join(ENTRY_DELIMITER).length;
4263
4262
  const batchLimit = this.limitFor(target);
4264
4263
  if (batchLimit > 0 && total > batchLimit) return {
4265
- result: this.failure(target, `Batch result (${total} chars) exceeds the ${batchLimit} limit. Remove or shorten more entries in the same batch.`, entries),
4264
+ result: this.failure(target, `批处理结果(${total} 字符)超过 ${batchLimit} 上限。请在同一个批里再删除或缩短一些条目。`, entries),
4266
4265
  write: null
4267
4266
  };
4268
4267
  this.resetFailures();
4269
4268
  return {
4270
4269
  result: {
4271
4270
  ok: true,
4272
- message: `Applied ${operations.length} operation(s).${this.storageHint(target, total)}`,
4271
+ message: `已应用 ${operations.length} 个操作。${this.storageHint(target, total)}`,
4273
4272
  entries: working,
4274
4273
  chars: total,
4275
4274
  limit: this.limitFor(target)
@@ -5961,7 +5960,7 @@ function newRunRegistry(options) {
5961
5960
  const parsed = parseIndex(raw);
5962
5961
  if (!parsed.ok) return {
5963
5962
  ok: false,
5964
- note: "run index could not be read as an index (not JSON, or no runs array) — the previous run history is unknown (the reports are unaffected)"
5963
+ note: "运行索引读不出来(不是 JSON,或没有 runs 数组)—— 上一次的运行历史未知(报告不受影响)"
5965
5964
  };
5966
5965
  const wasRunning = new Set([...foreign.values()].filter((row) => row.state === "running").map((row) => row.id));
5967
5966
  const seen = /* @__PURE__ */ new Set();
@@ -8579,7 +8578,7 @@ function contentRetentionFeedback(input) {
8579
8578
  if (before === null || after === null) return null;
8580
8579
  if (before.length < 200) return null;
8581
8580
  if (after.length >= before.length * .5) return null;
8582
- return `Content kept ${Math.round(after.length / before.length * 100)}% of the previous body (${after.length} of ${before.length} characters); the replaced version is preserved in this skill's history.`;
8581
+ return `新内容保留了上一版正文的 ${Math.round(after.length / before.length * 100)}%(${after.length}/${before.length} 字符);被替换的版本已保留在该技能的历史里。`;
8583
8582
  }
8584
8583
  /**
8585
8584
  * Read one skill's versions, oldest first.
@@ -8947,7 +8946,7 @@ function anchorRefusal(name, verdict) {
8947
8946
  ok: false,
8948
8947
  stale: true,
8949
8948
  anchor: verdict,
8950
- message: verdict === "missing" ? `Skill "${name}" not found.` : `Skill "${name}" changed since it was read; the write was refused to avoid overwriting newer content.`
8949
+ message: verdict === "missing" ? `技能「${name}」不存在。` : `技能 "${name}" 在读取之后被改动过;为避免覆盖更新的内容,本次写入被拒绝。`
8951
8950
  };
8952
8951
  }
8953
8952
  /**
@@ -8970,7 +8969,7 @@ function anchorUnverifiable(name, filePath) {
8970
8969
  ok: false,
8971
8970
  stale: true,
8972
8971
  anchor: "drift",
8973
- message: filePath === null ? `Skill "${name}" could not be read to verify the staged content.` : `Support file "${filePath}" of "${name}" could not be read to verify the staged content.`
8972
+ message: filePath === null ? `无法读取技能 "${name}" 以校验暂存内容。` : `无法读取技能 "${name}" 的支撑文件 "${filePath}" 以校验暂存内容。`
8974
8973
  };
8975
8974
  }
8976
8975
  function anchorRefusalFile(name, filePath, verdict) {
@@ -8978,7 +8977,7 @@ function anchorRefusalFile(name, filePath, verdict) {
8978
8977
  ok: false,
8979
8978
  stale: true,
8980
8979
  anchor: verdict,
8981
- message: verdict === "missing" ? `File "${filePath}" not found in skill "${name}".` : `Support file "${filePath}" of "${name}" changed since it was read; the write was refused to avoid overwriting newer content.`
8980
+ message: verdict === "missing" ? `文件「${filePath}」不在技能「${name}」里。` : `技能 "${name}" 的支撑文件 "${filePath}" 在读取之后被改动过;为避免覆盖更新的内容,本次写入被拒绝。`
8982
8981
  };
8983
8982
  }
8984
8983
  /**
@@ -8996,7 +8995,7 @@ function anchorRefusalFile(name, filePath, verdict) {
8996
8995
  function unreadableTarget(label, error) {
8997
8996
  return {
8998
8997
  ok: false,
8999
- message: `Could not read "${label}": ${error?.code === "EISDIR" ? "the path is a DIRECTORY, not a file" : error instanceof Error ? error.message : String(error)}. Nothing was written.`
8998
+ message: `读不出「${label}」:${error?.code === "EISDIR" ? "the path is a DIRECTORY, not a file" : error instanceof Error ? error.message : String(error)}。没有写入任何内容。`
9000
8999
  };
9001
9000
  }
9002
9001
  /** Upper bound of moves per restructure proposal (validator and core agree). */
@@ -9180,15 +9179,15 @@ function validateRestructureTarget(filePath) {
9180
9179
  }
9181
9180
  function validateSupportPath(filePath) {
9182
9181
  const normalized = filePath.replace(/\\/g, "/");
9183
- if (normalized.includes("..")) return "Path traversal is not allowed.";
9182
+ if (normalized.includes("..")) return "不允许路径穿越。";
9184
9183
  const parts = normalized.split("/").filter(Boolean);
9185
9184
  if (parts.length === 0 || !SUPPORT_DIRS.includes(parts[0])) return `file_path must be under one of: ${SUPPORT_DIRS.join(", ")}.`;
9186
- if (parts.length < 2) return "Provide a file name, not just a directory.";
9185
+ if (parts.length < 2) return "请给出文件名,不能只给目录。";
9187
9186
  for (const part of parts.slice(1)) {
9188
- if (!SUPPORT_FILE_NAME_RE.test(part)) return `Unsupported file name "${part}" — use lowercase letters, digits, dots, hyphens, and underscores (leading letter or digit).`;
9189
- if (part.toLowerCase().endsWith(".corrupt") || part.toLowerCase().endsWith(".tmp")) return `Unsupported file name "${part}" — the .corrupt/.tmp suffixes are reserved for the state/IO protocols.`;
9187
+ if (!SUPPORT_FILE_NAME_RE.test(part)) return `不支持的文件名「${part}」:请只用小写字母、数字、点、连字符和下划线(首字符须为字母或数字)。`;
9188
+ if (part.toLowerCase().endsWith(".corrupt") || part.toLowerCase().endsWith(".tmp")) return `不支持的文件名「${part}」:.corrupt/.tmp 后缀由状态与 IO 协议保留。`;
9190
9189
  const stem = part.split(".")[0]?.toLowerCase() ?? "";
9191
- if (WIN32_RESERVED_DEVICE_NAMES.has(stem)) return `Unsupported file name "${part}" — a Windows reserved device name.`;
9190
+ if (WIN32_RESERVED_DEVICE_NAMES.has(stem)) return `不支持的文件名「${part}」:这是 Windows 保留设备名。`;
9192
9191
  }
9193
9192
  return null;
9194
9193
  }
@@ -9337,7 +9336,7 @@ var SkillLibrary = class {
9337
9336
  const o = outcome;
9338
9337
  if (o === void 0 || typeof o !== "object" || !Object.prototype.hasOwnProperty.call(o, "write")) return {
9339
9338
  ok: false,
9340
- message: "internal error: the write transaction did not invoke the task; no write was performed"
9339
+ message: "内部错误:写事务没有调用任务;未执行任何写入"
9341
9340
  };
9342
9341
  if (o.ghostDir === true) await this.cleanupGhostDir(path);
9343
9342
  let result = o.result;
@@ -9357,7 +9356,7 @@ var SkillLibrary = class {
9357
9356
  if (o.write !== null && o.event) this.notifyMutation(o.event);
9358
9357
  return durabilityWarning === "" || !result.ok ? result : {
9359
9358
  ...result,
9360
- message: `${result.message} (warning: the write landed but the directory fsync failed — durability unconfirmed: ${durabilityWarning})`
9359
+ message: `${result.message} (警告:写入已落盘,但目录 fsync 失败 —— 持久性未确认:${durabilityWarning})`
9361
9360
  };
9362
9361
  }
9363
9362
  /**
@@ -9520,7 +9519,7 @@ var SkillLibrary = class {
9520
9519
  */
9521
9520
  badName(name, opts = {}) {
9522
9521
  const normalized = name.trim();
9523
- if (!SKILL_NAME_RE.test(normalized) || normalized.length > this.limits.maxNameLength) return `Invalid skill name "${normalized}". Use lowercase letters, digits, and hyphens (<= ${this.limits.maxNameLength}).`;
9522
+ if (!SKILL_NAME_RE.test(normalized) || normalized.length > this.limits.maxNameLength) return `技能名「${normalized}」不合法:请只用小写字母、数字和连字符(不超过 ${this.limits.maxNameLength} 个)。`;
9524
9523
  if (!opts.allowReserved && WIN32_RESERVED_DEVICE_NAMES.has(normalized)) return `"${normalized}" is a Windows reserved device name and cannot be used as a skill name.`;
9525
9524
  return null;
9526
9525
  }
@@ -9779,7 +9778,7 @@ var SkillLibrary = class {
9779
9778
  };
9780
9779
  if (origin === "background_review") return {
9781
9780
  ok: false,
9782
- message: "Only the foreground (user or the main agent) may pin or unpin skills."
9781
+ message: "只有前台(用户或主智能体)可以固定或取消固定技能。"
9783
9782
  };
9784
9783
  let durabilityWarning = "";
9785
9784
  const dir = this.dirOf(normalized);
@@ -9787,17 +9786,17 @@ var SkillLibrary = class {
9787
9786
  const existing = await this.io.exists(marker);
9788
9787
  if (pinned && existing) return {
9789
9788
  ok: true,
9790
- message: `Skill "${normalized}" is already pinned.`,
9789
+ message: `技能「${normalized}」已被固定。`,
9791
9790
  path: dir
9792
9791
  };
9793
9792
  if (!pinned && !existing) return {
9794
9793
  ok: true,
9795
- message: `Skill "${normalized}" is not pinned; nothing to do.`,
9794
+ message: `技能「${normalized}」未被固定,无需处理。`,
9796
9795
  path: dir
9797
9796
  };
9798
9797
  if (!await this.io.exists(join(dir, "SKILL.md"))) return {
9799
9798
  ok: false,
9800
- message: `Skill "${normalized}" not found.`
9799
+ message: `技能「${normalized}」不存在。`
9801
9800
  };
9802
9801
  if (pinned) {
9803
9802
  try {
@@ -9811,14 +9810,14 @@ var SkillLibrary = class {
9811
9810
  await this.cleanupGhostDir(join(dir, "SKILL.md"));
9812
9811
  return {
9813
9812
  ok: false,
9814
- message: `Skill "${normalized}" was archived concurrently while pinning; the partial marker was removed — retry after the mover settles.`
9813
+ message: `固定过程中技能「${normalized}」被并发归档;残留标记已移除:等搬运完成后重试。`
9815
9814
  };
9816
9815
  }
9817
9816
  } else await this.io.remove(marker);
9818
9817
  await this.audit(normalized, pinned ? "pin" : "unpin", null, null, pinned ? "pinned" : "unpinned");
9819
9818
  return {
9820
9819
  ok: true,
9821
- message: `${pinned ? `Skill "${normalized}" pinned: protected from deletion, background review, and the lifecycle.` : `Skill "${normalized}" unpinned.`}${durabilityWarning === "" ? "" : ` (warning: the write landed but the directory fsync failed — durability unconfirmed: ${durabilityWarning})`}`,
9820
+ message: `${pinned ? `技能 "${normalized}" 已固定:免受删除、后台复核与生命周期影响。` : `技能 "${normalized}" 已取消固定。`}${durabilityWarning === "" ? "" : ` (警告:写入已落盘,但目录 fsync 失败 —— 持久性未确认:${durabilityWarning})`}`,
9822
9821
  path: dir
9823
9822
  };
9824
9823
  }
@@ -9840,7 +9839,7 @@ var SkillLibrary = class {
9840
9839
  const norm = normalizeFrontmatter(content);
9841
9840
  if (norm.issues.length > 0) return {
9842
9841
  ok: false,
9843
- message: `Skill "${normalized}" frontmatter cannot be auto-fixed: ${norm.issues[0]} — wrap the value in double quotes and retry.`
9842
+ message: `技能「${normalized}」的 frontmatter 无法自动修复:${norm.issues[0]}:请用双引号包住取值后重试。`
9844
9843
  };
9845
9844
  const finalContent = norm.changed ? norm.content : content;
9846
9845
  if (norm.changed) {
@@ -9858,7 +9857,7 @@ var SkillLibrary = class {
9858
9857
  const dir = this.dirOf(normalized);
9859
9858
  if (await this.io.exists(join(dir, "SKILL.md"))) return {
9860
9859
  ok: false,
9861
- message: `Skill "${normalized}" already exists.`
9860
+ message: `技能「${normalized}」已存在。`
9862
9861
  };
9863
9862
  let rootEntries;
9864
9863
  try {
@@ -9867,17 +9866,17 @@ var SkillLibrary = class {
9867
9866
  const cause = error instanceof Error ? error.message : String(error);
9868
9867
  return {
9869
9868
  ok: false,
9870
- message: `Skill "${normalized}" could not be checked for a case-variant collision: listing ${this.root} failed (${cause}). Refusing the create — a second directory differing only in case cannot be undone across platforms.`
9869
+ message: `无法检查技能「${normalized}」是否与大小写变体冲突:列出 ${this.root} 失败(${cause})。拒绝创建 —— 仅大小写不同的第二个目录在跨平台时无法撤销。`
9871
9870
  };
9872
9871
  }
9873
9872
  for (const entry of rootEntries) if (typeof entry === "string" && entry !== normalized && entry.toLowerCase() === normalized.toLowerCase()) return {
9874
9873
  ok: false,
9875
- message: `Skill "${normalized}" collides with the existing case-variant directory "${entry}" (skill names are lowercase-only); rename one of them.`
9874
+ message: `技能「${normalized}」与已存在的大小写变体目录「${entry}」冲突(技能名只允许小写):请重命名其中一个。`
9876
9875
  };
9877
9876
  const protection = await this.writeProtection(normalized, origin);
9878
9877
  if (protection) return {
9879
9878
  ok: false,
9880
- message: `Skill "${normalized}" is protected (${protection}).`
9879
+ message: `技能「${normalized}」受保护(${protection})。`
9881
9880
  };
9882
9881
  const onDisk = finalContent.trimEnd() + "\n";
9883
9882
  const createPath = join(dir, "SKILL.md");
@@ -9912,18 +9911,18 @@ var SkillLibrary = class {
9912
9911
  }
9913
9912
  if (!taskRan) return {
9914
9913
  ok: false,
9915
- message: "internal error: the create transaction did not invoke the task; no file was written"
9914
+ message: "内部错误:创建事务没有调用任务;未写入任何文件"
9916
9915
  };
9917
9916
  if (existsAtCommit) return {
9918
9917
  ok: false,
9919
- message: `Skill "${normalized}" already exists.`
9918
+ message: `技能「${normalized}」已存在。`
9920
9919
  };
9921
9920
  let markerWarning = "";
9922
9921
  if (origin !== "foreground") {
9923
9922
  try {
9924
9923
  await this.io.writeText(markerPath(dir, "hermes-managed"), "");
9925
9924
  } catch (error) {
9926
- if (isCommittedOnly(error)) markerWarning = `the hermes-managed marker landed but its directory fsync failed — durability unconfirmed: ${error instanceof Error ? error.message : String(error)}`;
9925
+ if (isCommittedOnly(error)) markerWarning = `hermes-managed 标记已落盘,但其目录 fsync 失败 —— 持久性未确认:${error instanceof Error ? error.message : String(error)}`;
9927
9926
  else markerWarning = `hermes-managed marker write failed (${error instanceof Error ? error.message : String(error)}); the skill landed but is NOT lifecycle-managed — recreate or pin it manually`;
9928
9927
  }
9929
9928
  if (!await this.io.exists(createPath)) {
@@ -9931,7 +9930,7 @@ var SkillLibrary = class {
9931
9930
  await this.cleanupGhostDir(createPath);
9932
9931
  return {
9933
9932
  ok: false,
9934
- message: `Skill "${normalized}" was archived concurrently while being created; the partial marker was removed — retry once the mover settles.`
9933
+ message: `创建过程中技能「${normalized}」被并发归档;残留标记已移除:等搬运完成后重试一次。`
9935
9934
  };
9936
9935
  }
9937
9936
  }
@@ -9941,10 +9940,10 @@ var SkillLibrary = class {
9941
9940
  name: normalized,
9942
9941
  skillDir: dir
9943
9942
  });
9944
- const warnings = [createDurabilityWarning !== "" ? `the write landed but the directory fsync failed — durability unconfirmed: ${createDurabilityWarning}` : "", markerWarning].filter((warning) => warning !== "");
9943
+ const warnings = [createDurabilityWarning !== "" ? `写入已落盘,但目录 fsync 失败 —— 持久性未确认:${createDurabilityWarning}` : "", markerWarning].filter((warning) => warning !== "");
9945
9944
  return {
9946
9945
  ok: true,
9947
- message: `Skill "${normalized}" created.${warnings.length === 0 ? "" : ` (warning: ${warnings.join("; ")})`}`,
9946
+ message: `已创建技能「${normalized}」。${warnings.length === 0 ? "" : ` (警告:${warnings.join(";")})`}`,
9948
9947
  path: dir,
9949
9948
  ...norm.changed ? { normalizedFrontmatterFields: norm.fields } : {}
9950
9949
  };
@@ -9964,7 +9963,7 @@ var SkillLibrary = class {
9964
9963
  const protection = await this.writeProtection(name, origin);
9965
9964
  if (protection) return {
9966
9965
  ok: false,
9967
- message: `Skill "${name}" is protected (${protection}).`
9966
+ message: `技能「${name}」受保护(${protection})。`
9968
9967
  };
9969
9968
  const limitProbe = await probeText(this.io, path);
9970
9969
  if (isUnknown(limitProbe)) console.warn(`skill-store: could not re-read ${path} for the shrink exemption (${limitProbe.reason}); validating without it — an over-limit repair is refused, not accepted`);
@@ -9977,7 +9976,7 @@ var SkillLibrary = class {
9977
9976
  const norm = normalizeFrontmatter(content);
9978
9977
  if (norm.issues.length > 0) return {
9979
9978
  ok: false,
9980
- message: `Skill "${name}" frontmatter cannot be auto-fixed: ${norm.issues[0]} — wrap the value in double quotes and retry.`
9979
+ message: `技能「${name}」的 frontmatter 无法自动修复:${norm.issues[0]}:请用双引号包住取值后重试。`
9981
9980
  };
9982
9981
  const finalContent = norm.changed ? norm.content : content;
9983
9982
  if (norm.changed) {
@@ -10001,14 +10000,14 @@ var SkillLibrary = class {
10001
10000
  if (current === null) return {
10002
10001
  result: {
10003
10002
  ok: false,
10004
- message: `Skill "${name}" not found.`
10003
+ message: `技能「${name}」不存在。`
10005
10004
  },
10006
10005
  write: null
10007
10006
  };
10008
10007
  if (finalContent.trimEnd() === current.trimEnd()) return {
10009
10008
  result: {
10010
10009
  ok: true,
10011
- message: `Skill "${name}" unchanged: the supplied content already matches the current file; nothing written.`,
10010
+ message: `技能「${name}」未变更:提供的内容与当前文件一致,未写入。`,
10012
10011
  noop: true,
10013
10012
  path: dir
10014
10013
  },
@@ -10018,7 +10017,7 @@ var SkillLibrary = class {
10018
10017
  return {
10019
10018
  result: {
10020
10019
  ok: true,
10021
- message: `Skill "${name}" updated.`,
10020
+ message: `技能「${name}」已更新。`,
10022
10021
  path: dir,
10023
10022
  ...norm.changed ? { normalizedFrontmatterFields: norm.fields } : {}
10024
10023
  },
@@ -10052,12 +10051,12 @@ var SkillLibrary = class {
10052
10051
  const skillMd = join(dir, "SKILL.md");
10053
10052
  if (!await this.io.exists(skillMd)) return {
10054
10053
  ok: false,
10055
- message: `Skill "${name}" not found.`
10054
+ message: `技能「${name}」不存在。`
10056
10055
  };
10057
10056
  const protection = await this.writeProtection(name, origin);
10058
10057
  if (protection) return {
10059
10058
  ok: false,
10060
- message: `Skill "${name}" is protected (${protection}).`
10059
+ message: `技能「${name}」受保护(${protection})。`
10061
10060
  };
10062
10061
  let target = skillMd;
10063
10062
  let patchLabel = "SKILL.md";
@@ -10075,7 +10074,7 @@ var SkillLibrary = class {
10075
10074
  if (md === null) return {
10076
10075
  result: {
10077
10076
  ok: false,
10078
- message: `File not found: ${patchLabel}`
10077
+ message: `文件不存在:${patchLabel}`
10079
10078
  },
10080
10079
  write: null
10081
10080
  };
@@ -10097,7 +10096,7 @@ var SkillLibrary = class {
10097
10096
  if (patched === null) return {
10098
10097
  result: {
10099
10098
  ok: false,
10100
- message: `Could not find old_string in "${name}/${patchLabel}" (or the replaceAll fuzzy budget was exceeded). Use update for a full rewrite.`
10099
+ message: `在「${name}/${patchLabel}」里找不到 old_string(或 replaceAll 的模糊匹配预算已用尽)。整篇重写请改用 update。`
10101
10100
  },
10102
10101
  write: null
10103
10102
  };
@@ -10110,7 +10109,7 @@ var SkillLibrary = class {
10110
10109
  if (validation) return {
10111
10110
  result: {
10112
10111
  ok: false,
10113
- message: `Patch rejected: ${validation}`
10112
+ message: `补丁被拒绝:${validation}`
10114
10113
  },
10115
10114
  write: null
10116
10115
  };
@@ -10118,7 +10117,7 @@ var SkillLibrary = class {
10118
10117
  if (norm.issues.length > 0) return {
10119
10118
  result: {
10120
10119
  ok: false,
10121
- message: `Patch rejected: frontmatter cannot be auto-fixed (${norm.issues[0]}).`
10120
+ message: `补丁被拒绝:frontmatter 无法自动修复(${norm.issues[0]})。`
10122
10121
  },
10123
10122
  write: null
10124
10123
  };
@@ -10129,7 +10128,7 @@ var SkillLibrary = class {
10129
10128
  if (revalidated) return {
10130
10129
  result: {
10131
10130
  ok: false,
10132
- message: `Patch rejected: ${revalidated}`
10131
+ message: `补丁被拒绝:${revalidated}`
10133
10132
  },
10134
10133
  write: null
10135
10134
  };
@@ -10138,7 +10137,7 @@ var SkillLibrary = class {
10138
10137
  if (Buffer.byteLength(writeContent, "utf8") > this.limits.maxSkillFileBytes && target !== skillMd) return {
10139
10138
  result: {
10140
10139
  ok: false,
10141
- message: `Patched file exceeds ${this.limits.maxSkillFileBytes} bytes.`
10140
+ message: `修补后的文件超过 ${this.limits.maxSkillFileBytes} 字节。`
10142
10141
  },
10143
10142
  write: null
10144
10143
  };
@@ -10147,7 +10146,7 @@ var SkillLibrary = class {
10147
10146
  if (overLimit && target === skillMd && !repairing) return {
10148
10147
  result: {
10149
10148
  ok: false,
10150
- message: `Patched content exceeds ${this.limits.maxSkillContentChars} characters. ${CONTENT_SPLIT_HINT}`
10149
+ message: `修补后的内容超过 ${this.limits.maxSkillContentChars} 个字符。${CONTENT_SPLIT_HINT}`
10151
10150
  },
10152
10151
  write: null
10153
10152
  };
@@ -10156,7 +10155,7 @@ var SkillLibrary = class {
10156
10155
  if (supportOverCap && this.supportFileCharPolicy() === "enforce") return {
10157
10156
  result: {
10158
10157
  ok: false,
10159
- message: `Patched file content exceeds ${this.limits.maxSkillContentChars} characters. ${CONTENT_SPLIT_HINT}`
10158
+ message: `修补后的文件内容超过 ${this.limits.maxSkillContentChars} 个字符。${CONTENT_SPLIT_HINT}`
10160
10159
  },
10161
10160
  write: null
10162
10161
  };
@@ -10171,7 +10170,7 @@ var SkillLibrary = class {
10171
10170
  if (writeContent.trimEnd() === md.trimEnd()) return {
10172
10171
  result: {
10173
10172
  ok: true,
10174
- message: `Skill "${name}" unchanged: old_string already equals the replacement (${patchLabel}); nothing written.`,
10173
+ message: `技能「${name}」未变更:old_string 与替换内容相同(${patchLabel}),未写入。`,
10175
10174
  noop: true,
10176
10175
  path: dir
10177
10176
  },
@@ -10181,7 +10180,7 @@ var SkillLibrary = class {
10181
10180
  return {
10182
10181
  result: {
10183
10182
  ok: true,
10184
- message: `Skill "${name}" patched (${patchLabel}).${patchNote}${capAdvisory}`,
10183
+ message: `技能「${name}」已修补(${patchLabel})。${patchNote}${capAdvisory}`,
10185
10184
  path: dir,
10186
10185
  ...normalizedFields ? { normalizedFrontmatterFields: normalizedFields } : {}
10187
10186
  },
@@ -10226,9 +10225,9 @@ var SkillLibrary = class {
10226
10225
  const reason = error instanceof Error ? error.message : String(error);
10227
10226
  try {
10228
10227
  await this.io.remove(dest);
10229
- return `the copy succeeded but the source could not be removed (${reason}); the copied tree was rolled back`;
10228
+ return `复制成功,但源目录删不掉(${reason});已回滚复制出的目录树`;
10230
10229
  } catch {
10231
- return `the copy succeeded but the source could not be removed (${reason}) and the copied tree could not be rolled back — the tree now exists in BOTH locations; clean up manually`;
10230
+ return `复制成功,但源目录删不掉(${reason}),且复制出的目录树也无法回滚 —— 该目录树现在同时存在于两处;请手动清理`;
10232
10231
  }
10233
10232
  }
10234
10233
  }
@@ -10271,17 +10270,17 @@ var SkillLibrary = class {
10271
10270
  const md = await this.io.readText(join(dir, "SKILL.md"));
10272
10271
  if (md === null) return {
10273
10272
  ok: false,
10274
- message: `Skill "${name}" not found.`
10273
+ message: `技能「${name}」不存在。`
10275
10274
  };
10276
10275
  const protection = await this.deleteProtection(name, options);
10277
10276
  if (protection) return {
10278
10277
  ok: false,
10279
- message: protection === "pinned" ? `Skill "${name}" is pinned and cannot be archived. Remove the \`.pinned\` marker in its directory, then retry.` : `Skill "${name}" is protected (${protection}).`
10278
+ message: protection === "pinned" ? `Skill "${name}" is pinned and cannot be archived. Remove the \`.pinned\` marker in its directory, then retry.` : `技能「${name}」受保护(${protection})。`
10280
10279
  };
10281
10280
  if (options.absorbedInto) {
10282
10281
  if (options.absorbedInto.trim() === name) return {
10283
10282
  ok: false,
10284
- message: "absorbed_into cannot be the skill being archived (cannot absorb into itself)."
10283
+ message: "absorbed_into 不能是正在归档的技能本身(不能吸收到自己)。"
10285
10284
  };
10286
10285
  const intoBad = this.badName(options.absorbedInto.trim());
10287
10286
  if (intoBad) return {
@@ -10303,22 +10302,22 @@ var SkillLibrary = class {
10303
10302
  if (this.io.isSymlink) {
10304
10303
  if (await this.io.isSymlink(dir) === true) return {
10305
10304
  ok: false,
10306
- message: `Skill "${name}" is a symlink; refusing to archive it.`
10305
+ message: `技能「${name}」是符号链接;拒绝归档。`
10307
10306
  };
10308
10307
  }
10309
10308
  if (await this.supportDirsUnlistable(dir)) return {
10310
10309
  ok: false,
10311
- message: `Skill "${name}" could not be checked for writers (a support directory could not be listed); retry archiving.`
10310
+ message: `无法检查技能「${name}」是否有写入方(有一个支撑目录列不出来):请重试归档。`
10312
10311
  };
10313
10312
  const commitProtection = await this.deleteProtection(name, options);
10314
10313
  if (commitProtection) return {
10315
10314
  ok: false,
10316
- message: commitProtection === "pinned" ? `Skill "${name}" is pinned and cannot be archived. Remove the \`.pinned\` marker in its directory, then retry.` : `Skill "${name}" is protected (${commitProtection}).`
10315
+ message: commitProtection === "pinned" ? `Skill "${name}" is pinned and cannot be archived. Remove the \`.pinned\` marker in its directory, then retry.` : `技能「${name}」受保护(${commitProtection})。`
10317
10316
  };
10318
10317
  const moveFailure = await this.moveDir(dir, dest);
10319
10318
  if (moveFailure !== void 0) return {
10320
10319
  ok: false,
10321
- message: `Skill "${name}" archive failed: ${moveFailure}.`
10320
+ message: `技能「${name}」归档失败:${moveFailure}。`
10322
10321
  };
10323
10322
  const reason = options.reason ?? (options.absorbedInto ? `Consolidated into ${options.absorbedInto}` : "Archived by self-evolution curator");
10324
10323
  try {
@@ -10335,7 +10334,7 @@ var SkillLibrary = class {
10335
10334
  });
10336
10335
  return {
10337
10336
  ok: true,
10338
- message: `Skill "${name}" archived to .archive.`,
10337
+ message: `技能「${name}」已归档到 .archive。`,
10339
10338
  path: dest
10340
10339
  };
10341
10340
  }
@@ -10433,7 +10432,7 @@ var SkillLibrary = class {
10433
10432
  const mode = options.mode ?? "append";
10434
10433
  if (normalizedSources.length === 0) return {
10435
10434
  ok: false,
10436
- message: "Consolidation requires at least one distinct source skill."
10435
+ message: "合并至少需要一个互不相同的来源技能。"
10437
10436
  };
10438
10437
  for (const name of [targetName, ...normalizedSources]) {
10439
10438
  const bad = this.badName(name);
@@ -10446,7 +10445,7 @@ var SkillLibrary = class {
10446
10445
  const targetProtection = await this.writeProtection(targetName, origin);
10447
10446
  if (targetProtection) return {
10448
10447
  ok: false,
10449
- message: `Skill "${targetName}" is protected (${targetProtection}).`
10448
+ message: `技能「${targetName}」受保护(${targetProtection})。`
10450
10449
  };
10451
10450
  return await this.serial(async () => {
10452
10451
  const referenceWrites = [];
@@ -10458,17 +10457,17 @@ var SkillLibrary = class {
10458
10457
  const protection = await this.deleteProtection(source);
10459
10458
  if (protection) return {
10460
10459
  ok: false,
10461
- message: `Skill "${source}" is protected (${protection}).`
10460
+ message: `技能「${source}」受保护(${protection})。`
10462
10461
  };
10463
10462
  const sourceMd = await this.io.readText(join(this.dirOf(source), "SKILL.md"));
10464
10463
  if (!sourceMd) return {
10465
10464
  ok: false,
10466
- message: `Skill "${source}" not found.`
10465
+ message: `技能「${source}」不存在。`
10467
10466
  };
10468
10467
  const parsed = parseFrontmatter(sourceMd);
10469
10468
  if (!parsed) return {
10470
10469
  ok: false,
10471
- message: `Skill "${source}" has no valid frontmatter; refusing to merge.`
10470
+ message: `技能「${source}」没有有效的 frontmatter;拒绝合并。`
10472
10471
  };
10473
10472
  const carriesSupport = await this.countSupportDirs(source) > 0;
10474
10473
  const refs = supportRefs(parsed.body);
@@ -10477,7 +10476,7 @@ var SkillLibrary = class {
10477
10476
  const decision = await this.planSourceRehoming(source, targetName, parsed.body, rehomed.map((file) => file.to));
10478
10477
  if (decision.kind === "blocked") return {
10479
10478
  ok: false,
10480
- message: `Consolidation rejected: ${carriesSupport ? `source "${source}" carries support files` : `source "${source}" body references support files (${refs.join(", ")})`} that would be left behind — use mode:'reference' or archive the whole package instead.${decision.note}`
10479
+ message: `合并被拒绝:${carriesSupport ? `source "${source}" carries support files` : `source "${source}" body references support files (${refs.join(", ")})`} 会被落下。请改用 mode:'reference',或直接归档整个包。${decision.note}`
10481
10480
  };
10482
10481
  rehomed.push(...decision.files);
10483
10482
  appendedBody = decision.rewritten;
@@ -10489,17 +10488,17 @@ var SkillLibrary = class {
10489
10488
  const protection = await this.deleteProtection(source);
10490
10489
  if (protection) return {
10491
10490
  ok: false,
10492
- message: `Skill "${source}" is protected (${protection}).`
10491
+ message: `技能「${source}」受保护(${protection})。`
10493
10492
  };
10494
10493
  const sourceMd = await this.io.readText(join(this.dirOf(source), "SKILL.md"));
10495
10494
  if (!sourceMd) return {
10496
10495
  ok: false,
10497
- message: `Skill "${source}" not found.`
10496
+ message: `技能「${source}」不存在。`
10498
10497
  };
10499
10498
  const parsed = parseFrontmatter(sourceMd);
10500
10499
  if (!parsed) return {
10501
10500
  ok: false,
10502
- message: `Skill "${source}" has no valid frontmatter; refusing to demote.`
10501
+ message: `技能「${source}」没有有效的 frontmatter;拒绝降级。`
10503
10502
  };
10504
10503
  const refs = supportRefs(parsed.body);
10505
10504
  let demotedBody = parsed.body;
@@ -10507,7 +10506,7 @@ var SkillLibrary = class {
10507
10506
  const decision = await this.planSourceRehoming(source, targetName, parsed.body, rehomed.map((file) => file.to));
10508
10507
  if (decision.kind === "blocked") return {
10509
10508
  ok: false,
10510
- message: `Consolidation rejected: source "${source}" body references support files (${refs.join(", ")}) that would be left behind — archive the whole package instead.${decision.note}`
10509
+ message: `合并被拒绝:来源技能「${source}」的正文引用了会被落下的支撑文件(${refs.join(", ")}):请改为归档整个包。${decision.note}`
10511
10510
  };
10512
10511
  rehomed.push(...decision.files);
10513
10512
  demotedBody = decision.rewritten;
@@ -10524,7 +10523,7 @@ var SkillLibrary = class {
10524
10523
  try {
10525
10524
  if (!await this.io.readText(join(targetDir, "SKILL.md"))) return {
10526
10525
  ok: false,
10527
- message: `Skill "${targetName}" not found.`
10526
+ message: `技能「${targetName}」不存在。`
10528
10527
  };
10529
10528
  for (const source of normalizedSources) {
10530
10529
  if (plannedSourceBytes.has(source)) {
@@ -10587,7 +10586,7 @@ var SkillLibrary = class {
10587
10586
  if (!result.ok) throw new Error(result.message);
10588
10587
  return {
10589
10588
  ok: true,
10590
- message: `Consolidated ${normalizedSources.join(", ")} into "${targetName}".`,
10589
+ message: `已把 ${normalizedSources.join(", ")} 合并进「${targetName}」。`,
10591
10590
  path: targetDir
10592
10591
  };
10593
10592
  } catch (error) {
@@ -10600,11 +10599,11 @@ var SkillLibrary = class {
10600
10599
  }
10601
10600
  if (failedRestores.length > 0) return {
10602
10601
  ok: false,
10603
- message: `Consolidation failed (${reason}); rolled back EXCEPT ${failedRestores.join(", ")} — still in .archive, restore them with /evolution skill restore.`
10602
+ message: `合并失败(${reason});已回滚,但以下未回滚:${failedRestores.join(", ")}:它们仍在 .archive 里,请用 /evolution skill restore 恢复。`
10604
10603
  };
10605
10604
  return {
10606
10605
  ok: false,
10607
- message: `Consolidation failed and was rolled back: ${reason}`
10606
+ message: `合并失败,已回滚:${reason}`
10608
10607
  };
10609
10608
  }
10610
10609
  });
@@ -10633,21 +10632,21 @@ var SkillLibrary = class {
10633
10632
  };
10634
10633
  if (moves.length === 0) return {
10635
10634
  ok: false,
10636
- message: "Restructure requires at least one section move."
10635
+ message: "重构至少需要一次章节搬移。"
10637
10636
  };
10638
10637
  if (moves.length > 5) return {
10639
10638
  ok: false,
10640
- message: `Restructure exceeds 5 moves.`
10639
+ message: `重构超过 5 次搬移。`
10641
10640
  };
10642
10641
  for (const move of moves) {
10643
10642
  const raw = move;
10644
10643
  if (raw === null || typeof raw !== "object") return {
10645
10644
  ok: false,
10646
- message: "Every restructure move must be an object with a heading."
10645
+ message: "每次重构搬移都必须是带 heading 的对象。"
10647
10646
  };
10648
10647
  if (typeof move.heading !== "string" || !move.heading.trim()) return {
10649
10648
  ok: false,
10650
- message: "Every restructure move needs a non-empty heading."
10649
+ message: "每次重构搬移都需要非空的 heading。"
10651
10650
  };
10652
10651
  const targetIssue = validateRestructureTarget(move.toFile);
10653
10652
  if (targetIssue) return {
@@ -10659,25 +10658,25 @@ var SkillLibrary = class {
10659
10658
  const md = await this.io.readText(join(dir, "SKILL.md"));
10660
10659
  if (!md) return {
10661
10660
  ok: false,
10662
- message: `Skill "${name}" not found.`
10661
+ message: `技能「${name}」不存在。`
10663
10662
  };
10664
10663
  const block = frontmatterBlock(md);
10665
10664
  if (!block) return {
10666
10665
  ok: false,
10667
- message: "SKILL.md has no valid frontmatter; refusing to restructure."
10666
+ message: "SKILL.md 没有有效的 frontmatter;拒绝重构。"
10668
10667
  };
10669
10668
  const header = block.lines.slice(0, block.end + 1).join("\n");
10670
10669
  const plan = planRestructureSections(md.slice(header.length).replace(/\r\n/g, "\n"), moves);
10671
10670
  if ("error" in plan) return {
10672
10671
  ok: false,
10673
- message: `Restructure rejected: ${plan.error}`
10672
+ message: `重构被拒绝:${plan.error}`
10674
10673
  };
10675
10674
  const newMd = `${header}${plan.body}`.replace(/\r\n/g, "\n");
10676
10675
  const finalMd = block.nl === "\r\n" ? newMd.replace(/\n/g, "\r\n") : newMd;
10677
10676
  const newMdCheck = validateFrontmatter(finalMd, name, this.limits);
10678
10677
  if (newMdCheck) return {
10679
10678
  ok: false,
10680
- message: `Restructure rejected: ${newMdCheck}`
10679
+ message: `重构被拒绝:${newMdCheck}`
10681
10680
  };
10682
10681
  const listing = (this.limits.citationPolicy ?? "verify") === "refuse" ? null : await this.listSupportFiles(name);
10683
10682
  const files = listing !== null && isPresent(listing) ? listing.value : null;
@@ -10686,7 +10685,7 @@ var SkillLibrary = class {
10686
10685
  if (refs.length === 0) continue;
10687
10686
  if (files === null) return {
10688
10687
  ok: false,
10689
- message: `Restructure rejected: section "## ${section.heading}" references support files (${refs.join(", ")}) that stay behind — split the section or move it with its files.`
10688
+ message: `重构被拒绝:章节「## ${section.heading}」引用了会留在原地的支撑文件(${refs.join(", ")}):请拆开该章节,或连同它的文件一起搬。`
10690
10689
  };
10691
10690
  const report = resolveCitations({
10692
10691
  content: section.text,
@@ -10697,7 +10696,7 @@ var SkillLibrary = class {
10697
10696
  const missing = report.dangling.map((ref) => ref.target ?? ref.raw).join(", ");
10698
10697
  return {
10699
10698
  ok: false,
10700
- message: `Restructure rejected: section "## ${section.heading}" cites support file(s) that do not exist (${missing}) — fix the citation or create the file first.`
10699
+ message: `重构被拒绝:章节「## ${section.heading}」引用的支撑文件不存在(${missing}):请修正引用,或先创建该文件。`
10701
10700
  };
10702
10701
  }
10703
10702
  }
@@ -10738,7 +10737,7 @@ var SkillLibrary = class {
10738
10737
  if (!result.ok) return result;
10739
10738
  return {
10740
10739
  ok: true,
10741
- message: `Restructured "${name}": moved ${plan.sections.length} section(s) to references/.`,
10740
+ message: `已重构「${name}」:把 ${plan.sections.length} 个章节搬到 references/。`,
10742
10741
  path: dir
10743
10742
  };
10744
10743
  }
@@ -10760,12 +10759,12 @@ var SkillLibrary = class {
10760
10759
  const md = await this.io.readText(join(dir, "SKILL.md"));
10761
10760
  if (!md) return {
10762
10761
  ok: false,
10763
- message: `Skill "${name}" not found.`
10762
+ message: `技能「${name}」不存在。`
10764
10763
  };
10765
10764
  const protection = plan.protection === "write" ? await this.writeProtection(name, plan.origin) : plan.protection === "delete" ? await this.deleteProtection(name) : null;
10766
10765
  if (protection) return {
10767
10766
  ok: false,
10768
- message: `Skill "${name}" is protected (${protection}).`
10767
+ message: `技能「${name}」受保护(${protection})。`
10769
10768
  };
10770
10769
  const landing = [];
10771
10770
  for (const write of plan.writes) {
@@ -10775,12 +10774,12 @@ var SkillLibrary = class {
10775
10774
  } catch (error) {
10776
10775
  return {
10777
10776
  ok: false,
10778
- message: `Tree change refused: cannot safely pre-read ${write.target} (${error instanceof Error ? error.message : String(error)}); no writes were performed`
10777
+ message: `拒绝目录树变更:无法安全预读 ${write.target}(${error instanceof Error ? error.message : String(error)});未执行任何写入`
10779
10778
  };
10780
10779
  }
10781
10780
  if (Buffer.byteLength(write.content, "utf8") > this.limits.maxSkillFileBytes) return {
10782
10781
  ok: false,
10783
- message: `Write exceeds ${this.limits.maxSkillFileBytes} bytes: ${write.target}`
10782
+ message: `写入超过 ${this.limits.maxSkillFileBytes} 字节:${write.target}`
10784
10783
  };
10785
10784
  const threat = this.contentThreatBlock(write.content);
10786
10785
  if (threat) return {
@@ -10835,11 +10834,11 @@ var SkillLibrary = class {
10835
10834
  const reason = error instanceof Error ? error.message : String(error);
10836
10835
  if (stuck.length === 0) return {
10837
10836
  ok: false,
10838
- message: `Tree change failed and was rolled back: ${reason}`
10837
+ message: `目录树变更失败,已回滚:${reason}`
10839
10838
  };
10840
10839
  return {
10841
10840
  ok: false,
10842
- message: `Tree change failed: ${reason}. The rollback could not restore ${stuck.join(", ")} — recover those targets from the .backups snapshot (or re-apply the change).`
10841
+ message: `目录树变更失败:${reason}。回滚无法恢复 ${stuck.join(", ")}:请从 .backups 快照恢复这些目标(或重新应用这次变更)。`
10843
10842
  };
10844
10843
  }
10845
10844
  const skillMdWrite = landing.find((entry) => entry.target.split(/[\\/]/).pop() === "SKILL.md");
@@ -10853,7 +10852,7 @@ var SkillLibrary = class {
10853
10852
  });
10854
10853
  return {
10855
10854
  ok: true,
10856
- message: durabilityWarning === "" ? `${plan.eventAction} "${name}" succeeded.` : `${plan.eventAction} "${name}" succeeded (warning: the write landed but the directory fsync failed — durability unconfirmed: ${durabilityWarning})`,
10855
+ message: durabilityWarning === "" ? `${plan.eventAction} "${name}" succeeded.` : `${plan.eventAction} "${name}" succeeded (警告:写入已落盘,但目录 fsync 失败 —— 持久性未确认:${durabilityWarning})`,
10857
10856
  path: dir
10858
10857
  };
10859
10858
  }
@@ -10872,7 +10871,7 @@ var SkillLibrary = class {
10872
10871
  const dest = this.dirOf(name);
10873
10872
  if (await this.io.exists(dest)) return {
10874
10873
  ok: false,
10875
- message: await this.io.exists(join(dest, "SKILL.md")) ? `Skill "${name}" already exists in the active root; refusing to overwrite.` : `Skill directory "${name}" already exists in the active root but carries no SKILL.md; remove or repair it before restoring.`
10874
+ message: await this.io.exists(join(dest, "SKILL.md")) ? `技能「${name}」已存在于当前根目录;拒绝覆盖。` : `技能目录「${name}」已存在于当前根目录,但没有 SKILL.md;恢复前请先移除或修复它。`
10876
10875
  };
10877
10876
  let caseVariant;
10878
10877
  try {
@@ -10880,7 +10879,7 @@ var SkillLibrary = class {
10880
10879
  } catch {}
10881
10880
  if (caseVariant !== void 0) return {
10882
10881
  ok: false,
10883
- message: `Skill "${caseVariant}" (same name, different letter case) already exists in the active root; restoring "${name}" beside it would create ambiguous duplicates — restore as "${caseVariant}" or remove the variant first.`
10882
+ message: `技能「${caseVariant}」(同名、仅大小写不同)已存在于当前根目录;把「${name}」恢复到它旁边会造成含义不清的重复:请恢复为「${caseVariant}」,或先移除该变体。`
10884
10883
  };
10885
10884
  const archiveRoot = join(this.root, ".archive");
10886
10885
  let entries;
@@ -10889,7 +10888,7 @@ var SkillLibrary = class {
10889
10888
  } catch {
10890
10889
  return {
10891
10890
  ok: false,
10892
- message: "No skill archive available."
10891
+ message: "没有可用的技能归档。"
10893
10892
  };
10894
10893
  }
10895
10894
  const candidates = entries.filter((entry) => entry === name || entry.startsWith(`${name}-`)).sort().reverse();
@@ -10924,28 +10923,28 @@ var SkillLibrary = class {
10924
10923
  if (!chosen) {
10925
10924
  if (unreadable.length === 0) return {
10926
10925
  ok: false,
10927
- message: `Skill "${name}" is not in .archive.`
10926
+ message: `技能「${name}」不在 .archive 里。`
10928
10927
  };
10929
10928
  return {
10930
10929
  ok: false,
10931
- message: `No archived entry for "${name}" carries a matching frontmatter name, but .archive holds ${unreadable.length} entr(y/ies) named like it: ${unreadable.join(", ")}. Those entries have no readable SKILL.md (or none matching the name), so restoring by name cannot tell them apart — rename the directory to the skill name and restore again, or restore from a snapshot.`
10930
+ message: `.archive 里没有「${name}」对应的 frontmatter 名,但有 ${unreadable.length} 个名字相似的归档项:${unreadable.join(", ")}。这些归档项没有可读的 SKILL.md(或名字对不上),按名字恢复无法区分它们:请把目录改成技能名后再次恢复,或改用快照恢复。`
10932
10931
  };
10933
10932
  }
10934
10933
  const source = join(archiveRoot, chosen);
10935
10934
  if (this.io.isSymlink) {
10936
10935
  if (await this.io.isSymlink(source) === true) return {
10937
10936
  ok: false,
10938
- message: `Archived entry "${chosen}" is a symlink; refusing to restore it.`
10937
+ message: `归档项「${chosen}」是符号链接;拒绝恢复。`
10939
10938
  };
10940
10939
  }
10941
10940
  if (await this.supportDirsUnlistable(dest)) return {
10942
10941
  ok: false,
10943
- message: `Skill "${name}" could not be checked for writers (a support directory could not be listed); retry restoring.`
10942
+ message: `无法检查技能「${name}」是否有写入方(有一个支撑目录列不出来):请重试恢复。`
10944
10943
  };
10945
10944
  const moveFailure = await this.moveDir(source, dest);
10946
10945
  if (moveFailure !== void 0) return {
10947
10946
  ok: false,
10948
- message: `Restore of "${name}" from .archive failed: ${moveFailure}`
10947
+ message: `从 .archive 恢复「${name}」失败:${moveFailure}`
10949
10948
  };
10950
10949
  for (const marker of [".archive-reason", ".archive-name"]) if (await this.io.exists(join(dest, marker))) await this.io.remove(join(dest, marker));
10951
10950
  const restoredProbe = await probeText(this.io, join(dest, "SKILL.md"));
@@ -10958,7 +10957,7 @@ var SkillLibrary = class {
10958
10957
  });
10959
10958
  return {
10960
10959
  ok: true,
10961
- message: `Skill "${name}" restored from .archive.`,
10960
+ message: `技能「${name}」已从 .archive 恢复。`,
10962
10961
  path: dest
10963
10962
  };
10964
10963
  }
@@ -10975,12 +10974,12 @@ var SkillLibrary = class {
10975
10974
  const dir = this.dirOf(name);
10976
10975
  if (!await this.io.exists(join(dir, "SKILL.md"))) return {
10977
10976
  ok: false,
10978
- message: `Skill "${name}" not found.`
10977
+ message: `技能「${name}」不存在。`
10979
10978
  };
10980
10979
  const protection = await this.writeProtection(name, origin);
10981
10980
  if (protection) return {
10982
10981
  ok: false,
10983
- message: `Skill "${name}" is protected (${protection}).`
10982
+ message: `技能「${name}」受保护(${protection})。`
10984
10983
  };
10985
10984
  const validation = validateSupportPath(filePath);
10986
10985
  if (validation) return {
@@ -10989,7 +10988,7 @@ var SkillLibrary = class {
10989
10988
  };
10990
10989
  if (Buffer.byteLength(content, "utf8") > this.limits.maxSkillFileBytes) return {
10991
10990
  ok: false,
10992
- message: `Support file exceeds ${this.limits.maxSkillFileBytes} bytes.`
10991
+ message: `支撑文件超过 ${this.limits.maxSkillFileBytes} 字节。`
10993
10992
  };
10994
10993
  const threat = this.contentThreatBlock(content);
10995
10994
  if (threat) return {
@@ -11009,14 +11008,14 @@ var SkillLibrary = class {
11009
11008
  if (overCap && !repairing && this.supportFileCharPolicy() === "enforce") return {
11010
11009
  result: {
11011
11010
  ok: false,
11012
- message: `Support file "${filePath}" content exceeds ${this.limits.maxSkillContentChars} characters. ${CONTENT_SPLIT_HINT}`
11011
+ message: `支撑文件「${filePath}」的内容超过 ${this.limits.maxSkillContentChars} 个字符。${CONTENT_SPLIT_HINT}`
11013
11012
  },
11014
11013
  write: null
11015
11014
  };
11016
11015
  if (current !== null && content.trimEnd() === current.trimEnd()) return {
11017
11016
  result: {
11018
11017
  ok: true,
11019
- message: `Support file "${filePath}" unchanged: the supplied content already matches the current file; nothing written.`,
11018
+ message: `支撑文件「${filePath}」未变更:提供的内容与当前文件一致,未写入。`,
11020
11019
  noop: true,
11021
11020
  path: target
11022
11021
  },
@@ -11025,7 +11024,7 @@ var SkillLibrary = class {
11025
11024
  return {
11026
11025
  result: {
11027
11026
  ok: true,
11028
- message: `Support file "${filePath}" written to "${name}".${capAdvisory}`,
11027
+ message: `支撑文件「${filePath}」已写入「${name}」。${capAdvisory}`,
11029
11028
  path: target
11030
11029
  },
11031
11030
  write: content,
@@ -11059,12 +11058,12 @@ var SkillLibrary = class {
11059
11058
  const dir = this.dirOf(name);
11060
11059
  if (!await this.io.exists(join(dir, "SKILL.md"))) return {
11061
11060
  ok: false,
11062
- message: `Skill "${name}" not found.`
11061
+ message: `技能「${name}」不存在。`
11063
11062
  };
11064
11063
  const protection = await this.writeProtection(name, origin);
11065
11064
  if (protection) return {
11066
11065
  ok: false,
11067
- message: `Skill "${name}" is protected (${protection}).`
11066
+ message: `技能「${name}」受保护(${protection})。`
11068
11067
  };
11069
11068
  const validation = validateSupportPath(filePath);
11070
11069
  if (validation) return {
@@ -11076,7 +11075,7 @@ var SkillLibrary = class {
11076
11075
  if (anchor !== void 0) return anchorRefusalFile(name, filePath, "missing");
11077
11076
  return {
11078
11077
  ok: false,
11079
- message: `File "${filePath}" not found in skill "${name}".`
11078
+ message: `文件「${filePath}」不在技能「${name}」里。`
11080
11079
  };
11081
11080
  }
11082
11081
  const beforeProbe = await probeText(this.io, target);
@@ -11100,7 +11099,7 @@ var SkillLibrary = class {
11100
11099
  });
11101
11100
  if (!ran.done) return {
11102
11101
  ok: false,
11103
- message: "internal error: the delete transaction did not invoke the task; nothing was removed"
11102
+ message: "内部错误:删除事务没有调用任务;没有删除任何东西"
11104
11103
  };
11105
11104
  } else if (verdict === "match") await this.io.remove(target);
11106
11105
  if (verdict !== "match") return anchorRefusalFile(name, filePath, verdict);
@@ -11113,7 +11112,7 @@ var SkillLibrary = class {
11113
11112
  });
11114
11113
  return {
11115
11114
  ok: true,
11116
- message: `Support file "${filePath}" removed from "${name}".`,
11115
+ message: `支撑文件「${filePath}」已从「${name}」移除。`,
11117
11116
  path: target
11118
11117
  };
11119
11118
  }
@@ -11331,7 +11330,7 @@ var SkillLibrary = class {
11331
11330
  out.push({
11332
11331
  path: join(backupRoot, name),
11333
11332
  createdAt: "",
11334
- reason: "unreadable or missing manifest (orphan snapshot)"
11333
+ reason: "清单读不出来或缺失(孤儿快照)"
11335
11334
  });
11336
11335
  continue;
11337
11336
  }
@@ -11373,12 +11372,12 @@ var SkillLibrary = class {
11373
11372
  const listed = await this.listSnapshots();
11374
11373
  if (isUnknown(listed)) return {
11375
11374
  ok: false,
11376
- message: `Snapshot restore refused: the snapshot directory could not be read (${listed.reason}) — nothing was changed.`
11375
+ message: `拒绝快照恢复:快照目录读不出来(${listed.reason})—— 未做任何改动。`
11377
11376
  };
11378
11377
  const latest = isPresent(listed) ? listed.value[0] : void 0;
11379
11378
  if (!latest) return {
11380
11379
  ok: false,
11381
- message: "No skill snapshot available."
11380
+ message: "没有可用的技能快照。"
11382
11381
  };
11383
11382
  let preRollbackPath;
11384
11383
  try {
@@ -11386,7 +11385,7 @@ var SkillLibrary = class {
11386
11385
  } catch (error) {
11387
11386
  return {
11388
11387
  ok: false,
11389
- message: `Snapshot restore was refused before anything was cleared: taking the pre-rollback snapshot failed (${error instanceof Error ? error.message : String(error)}) — the active tree is UNCHANGED. Resolve the snapshot write failure and retry.`
11388
+ message: `在任何清理之前就拒绝了快照恢复:生成回滚前快照失败(${error instanceof Error ? error.message : String(error)})—— 活动目录树未改变。请解决快照写入失败后重试。`
11390
11389
  };
11391
11390
  }
11392
11391
  let snapshotExtras;
@@ -11395,7 +11394,7 @@ var SkillLibrary = class {
11395
11394
  } catch (error) {
11396
11395
  return {
11397
11396
  ok: false,
11398
- message: `Snapshot restore was refused before anything was cleared: reading the snapshot manifest/extras failed (${error instanceof Error ? error.message : String(error)}) — the active tree is UNCHANGED. Resolve the read failure and retry.`
11397
+ message: `在任何清理之前就拒绝了快照恢复:读取快照清单或附属文件失败(${error instanceof Error ? error.message : String(error)})—— 活动目录树未改变。请解决读取失败后重试。`
11399
11398
  };
11400
11399
  }
11401
11400
  try {
@@ -11406,17 +11405,17 @@ var SkillLibrary = class {
11406
11405
  await this.restoreSnapshotIntoRoot(preRollbackPath);
11407
11406
  return {
11408
11407
  ok: false,
11409
- message: `Snapshot restore failed (${reason}); the active tree was rolled back to the pre-rollback snapshot.`
11408
+ message: `快照恢复失败(${reason});活动目录树已回滚到回滚前的快照。`
11410
11409
  };
11411
11410
  } catch (rollbackError) {
11412
11411
  const rb = rollbackError instanceof Error ? rollbackError.message : String(rollbackError);
11413
11412
  if (isPreClearRefusal(reason) && isPreClearRefusal(rb)) return {
11414
11413
  ok: false,
11415
- message: `Snapshot restore was refused before anything was cleared; the active tree is UNCHANGED.\n- target: ${reason}\n- pre-rollback: ${rb}\nResolve the cause (a live skill write, or an incomplete snapshot) and retry — no manual rescue is needed.`
11414
+ message: `在任何清理之前就拒绝了快照恢复; 活动目录树未改变。\n- 目标:${reason}\n- 回滚前快照:${rb}\n请解决原因(有存活的技能写入,或快照不完整)后重试 —— 无需手动抢救。`
11416
11415
  };
11417
11416
  return {
11418
11417
  ok: false,
11419
- message: `Snapshot restore failed (${reason}) AND pre-rollback restore failed (${rb}). Rescue manually from: ${preRollbackPath} (pre-rollback), ${latest.path} (target).`
11418
+ message: `快照恢复失败(${reason}),且回滚前快照的恢复也失败(${rb})。请手动抢救:${preRollbackPath}(回滚前)、${latest.path}(目标)。`
11420
11419
  };
11421
11420
  }
11422
11421
  }
@@ -11426,7 +11425,7 @@ var SkillLibrary = class {
11426
11425
  });
11427
11426
  return {
11428
11427
  ok: true,
11429
- message: `Restored skill tree from ${latest.path}`,
11428
+ message: `已从 ${latest.path} 恢复技能目录树`,
11430
11429
  path: latest.path,
11431
11430
  ...snapshotExtras.length === 0 ? {} : { extras: snapshotExtras }
11432
11431
  };
@@ -13074,7 +13073,7 @@ function planNamespaceMigration(documentText) {
13074
13073
  skipped.push({
13075
13074
  namespace,
13076
13075
  key,
13077
- reason: "row `" + rowId + "` has no such parameter"
13076
+ reason: "row `" + rowId + "` 没有这个参数"
13078
13077
  });
13079
13078
  continue;
13080
13079
  }
@@ -13126,7 +13125,7 @@ function classifyNamespaceMigration(plan, read) {
13126
13125
  for (const value of entry.values) skipped.push({
13127
13126
  namespace: entry.namespace,
13128
13127
  key: value.source,
13129
- reason: "row `" + entry.rowId + "` is not served in this composition"
13128
+ reason: "row `" + entry.rowId + "` 在本组合中不提供服务"
13130
13129
  });
13131
13130
  continue;
13132
13131
  }