clearai-dsh 0.1.7 → 0.2.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/client.js CHANGED
@@ -72,8 +72,8 @@ window.__ModuleLoader__.load({
72
72
 
73
73
  /** 语言命名空间。表按**源文**索引:键就是中文原文,所以漏翻译一条只会退回中文,不会把 key 显示给人。 */
74
74
  const LOCALE_NS = 'clearai'
75
- const LOCALE_ZH = {" · 交付 ": " · 交付 ", " · 人 ": " · 人 ", " · 在工作区外,面板不读正文": " · 在工作区外,面板不读正文", " · 尺子 ": " · 尺子 ", " · 执行没跑成": " · 执行没跑成", " · 支持到 ": " · 支持到 ", " · 最近 ": " · 最近 ", " · 证据 ": " · 证据 ", " · 车道 ": " · 车道 ", " · 随步骤作废而终止": " · 随步骤作废而终止", " 份)。": " 份)。", " 份产物,但没有任何计划声明过它们。点一条可以直接看(它们不计入交付)。": " 份产物,但没有任何计划声明过它们。点一条可以直接看(它们不计入交付)。", " 份没列出来(这一栏只列最近改动的 ": " 份没列出来(这一栏只列最近改动的 ", " 发起": " 发起", " 处声明": " 处声明", " 字节": " 字节", " 字节 · ": " 字节 · ", " 字节 · 未被任何计划声明": " 字节 · 未被任何计划声明", " 字节 · 资源 ": " 字节 · 资源 ", " 推翻:": " 推翻:", " 旁观 ": " 旁观 ", " 条": " 条", " 条)": " 条)", " 次侦察": " 次侦察", " 次评估者": " 次评估者", " 步": " 步", " 步)": " 步)", " 等 ": " 等 ", " 评估卡": " 评估卡", " 轮": " 轮", " 里打开": " 里打开", "(假设达到这一级且无推翻才升格为事实)": "(假设达到这一级且无推翻才升格为事实)", "(每次修订留痕,旧值不删)": "(每次修订留痕,旧值不删)", "(点一下开右栏「世界树」)": "(点一下开右栏「世界树」)", "(点一下开右栏「世界树」看拓扑)": "(点一下开右栏「世界树」看拓扑)", "(留档不删)": "(留档不删)", "(缺)": "(缺)", "(要独立评估)才达门槛": "(要独立评估)才达门槛", "),所以这个分叉没有归宿了:**随步骤作废而终止**——它既不是被人裁掉(没人做过这个决定),也不是被算术排掉(没有尺子排过它)。要收掉工作副本(保留 ref),对它调 AbandonFork(会弹人工确认)。": "),所以这个分叉没有归宿了:**随步骤作废而终止**——它既不是被人裁掉(没人做过这个决定),也不是被算术排掉(没有尺子排过它)。要收掉工作副本(保留 ref),对它调 AbandonFork(会弹人工确认)。", "),等目标验收时升格为事实": "),等目标验收时升格为事实", ")——它不是落选:落选意味着它跑完了、被尺子排到了后面;这一条是没跑成,所以也没有读数可以参与算术。": ")——它不是落选:落选意味着它跑完了、被尺子排到了后面;这一条是没跑成,所以也没有读数可以参与算术。", "**执行没跑成**(": "**执行没跑成**(", "**执行者未归**:这条世界线的执行者派出去之后没有回灌,而分叉已经收口——它再回来也没有归宿了,所以这里既不判它跑成也没跑成,也不再等它。它的产物(如果写过)还在它自己的工作副本里;要判断那条线到底做出了什么,直接看工作副本比看这条状态可靠。": "**执行者未归**:这条世界线的执行者派出去之后没有回灌,而分叉已经收口——它再回来也没有归宿了,所以这里既不判它跑成也没跑成,也不再等它。它的产物(如果写过)还在它自己的工作副本里;要判断那条线到底做出了什么,直接看工作副本比看这条状态可靠。", ":还差 ": ":还差 ", ";放弃缘由:": ";放弃缘由:", "clearai 面板:右栏页签类型注册失败 ": "clearai 面板:右栏页签类型注册失败 ", "clearai-loop: 席位跟着会话预设进出": "clearai-loop: 席位跟着会话预设进出", "世界树": "世界树", "世界线:": "世界线:", "为什么放弃?(留痕可考)": "为什么放弃?(留痕可考)", "事实": "事实", "产物": "产物", "人审查后决定撤回": "人审查后决定撤回", "人已撤回(记录保留)": "人已撤回(记录保留)", "撤回事实": "撤回事实", "维持原事实": "维持原事实", "被推翻,等你决定": "被推翻,等你决定", "未走过 ": "未走过 ", "认可,继续": "认可,继续", "撤回要留痕:点一下写缘由,写了才能提交": "撤回要留痕:点一下写缘由,写了才能提交", "为什么撤回?(留痕可考)": "为什么撤回?(留痕可考)", "确认撤回": "确认撤回", "确认撤回(记录保留,不再作为「已知」引用)": "确认撤回(记录保留,不再作为「已知」引用)", "要改判据就重做一条世界线(说一句即可)": "要改判据就重做一条世界线(说一句即可)", "这些等级一条证据都没有:跳到高等级不是违规,但要说得清为什么更便宜的路不通": "这些等级一条证据都没有:跳到高等级不是违规,但要说得清为什么更便宜的路不通", "人的裁决:": "人的裁决:", "仅人可引用": "仅人可引用", "会话日志里的原生审批对(不可伪造)": "会话日志里的原生审批对(不可伪造)", "依据": "依据", "侦 ": "侦 ", "侦察 · ": "侦察 · ", "候选": "候选", "做什么": "做什么", "做法": "做法", "停摆等人": "停摆等人", "其他(": "其他(", "出现推翻证据": "出现推翻证据", "出现推翻证据(终态,记录保留)": "出现推翻证据(终态,记录保留)", "分支": "分支", "切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)": "切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)", "判据": "判据", "判据:": "判据:", "判据待写": "判据待写", "升格门槛": "升格门槛", "原生预览打不开这条路(它在工作区外?)": "原生预览打不开这条路(它在工作区外?)", "原生预览打开它": "原生预览打开它", "原生预览打开它(计划声明的产物)": "原生预览打开它(计划声明的产物)", "合并目录、本会话用法、可引用可采纳": "合并目录、本会话用法、可引用可采纳", "命题": "命题", "命题 · ": "命题 · ", "在": "在", "在 ": "在 ", "在世界树里看这一步": "在世界树里看这一步", "在右栏预览": "在右栏预览", "声明的是目录;准入要求具体文件——目录不算物证": "声明的是目录;准入要求具体文件——目录不算物证", "多问我": "多问我", "完成度 ": "完成度 ", "完成度 —": "完成度 —", "审批记录": "审批记录", "工作区模板 · clear/skills": "工作区模板 · clear/skills", "工作区现状(本会话还没有第一轮对话,这份还没进投影)": "工作区现状(本会话还没有第一轮对话,这份还没进投影)", "已交付": "已交付", "已作废": "已作废", "已回灌": "已回灌", "已推翻": "已推翻", "已提出": "已提出", "已撤回": "已撤回", "已收尾 · 存档可看": "已收尾 · 存档可看", "已改版": "已改版", "已放弃": "已放弃", "已放弃探索:": "已放弃探索:", "已放弃的分叉": "已放弃的分叉", "已替代": "已替代", "已确认": "已确认", "已确认事实 · ": "已确认事实 · ", "已被下一版命题替代(版本留着,不参与当前推理)": "已被下一版命题替代(版本留着,不参与当前推理)", "已裁决": "已裁决", "已评估": "已评估", "已达成": "已达成", "已达门槛(": "已达门槛(", "已达门槛,已升格为事实": "已达门槛,已升格为事实", "已采纳": "已采纳", "待开计划": "待开计划", "待推进": "待推进", "待裁决": "待裁决", "我的 · ~/.dsh": "我的 · ~/.dsh", "打开 ": "打开 ", "打开「事实」那一格并展开这条命题": "打开「事实」那一格并展开这条命题", "打开世界树并选中产出这条事实的验证步": "打开世界树并选中产出这条事实的验证步", "打开世界树并选中产生这条证据的验证步": "打开世界树并选中产生这条证据的验证步", "打开失败:HTTP ": "打开失败:HTTP ", "打开计划文档(原生预览)": "打开计划文档(原生预览)", "技能 · 记忆": "技能 · 记忆", "把这道裁决摆到原生提问卡上(带你读到的判据与各分支读数)": "把这道裁决摆到原生提问卡上(带你读到的判据与各分支读数)", "探索中": "探索中", "推翻": "推翻", "推进中": "推进中", "提交中…": "提交中…", "提交失败:": "提交失败:", "支持": "支持", "支持到 ": "支持到 ", "收敛": "收敛", "收束:": "收束:", "收起": "收起", "收起详情": "收起详情", "放弃了这次探索": "放弃了这次探索", "放弃探索": "放弃探索", "放弃缘由(必填)": "放弃缘由(必填)", "放弃要留痕:先写缘由": "放弃要留痕:先写缘由", "放弃要留痕:点一下写缘由,写了才能提交": "放弃要留痕:点一下写缘由,写了才能提交", "放弃这条分叉": "放弃这条分叉", "放弃这次探索(留档不删,ref 保留)": "放弃这次探索(留档不删,ref 保留)", "放行": "放行", "旁观写这条裁决的评估者子会话(论证过程)": "旁观写这条裁决的评估者子会话(论证过程)", "旁观评估者": "旁观评估者", "旁观这条世界线的评估者会话(只读)": "旁观这条世界线的评估者会话(只读)", "无法判定": "无法判定", "是目录(不算物证)": "是目录(不算物证)", "最后改动 ": "最后改动 ", "有了第一条证据": "有了第一条证据", "有人在等你": "有人在等你", "未分类": "未分类", "未声明": "未声明", "未收口(随步骤作废而终止)": "未收口(随步骤作废而终止)", "未知": "未知", "未走:": "未走:", "未采纳": "未采纳", "本会话 模型 ": "本会话 模型 ", "本体声明还没随投影下发,这里用的是规范闭环的镜像;会话跑过一拍后会自动对齐声明。": "本体声明还没随投影下发,这里用的是规范闭环的镜像;会话跑过一拍后会自动对齐声明。", "本项目 · .dsh / .agents": "本项目 · .dsh / .agents", "本项目写的 · clear/skills": "本项目写的 · clear/skills", "核心产物(": "核心产物(", "步 ": "步 ", "没正常结束": "没正常结束", "没送出去:": "没送出去:", "派出 ": "派出 ", "派生 · ": "派生 · ", "点一条 → 右栏预览": "点一条 → 右栏预览", "点一行看细节": "点一行看细节", "点开看这一步的细节": "点开看这一步的细节", "版本": "版本", "状态": "状态", "独立评估者": "独立评估者", "用原生提问卡决定": "用原生提问卡决定", "用原生预览打开章程(它每回合整份注入模型上下文)": "用原生预览打开章程(它每回合整份注入模型上下文)", "用提问卡决定": "用提问卡决定", "盘上已有(": "盘上已有(", "盘上没有": "盘上没有", "盘上没有这个文件": "盘上没有这个文件", "目录": "目录", "目录还没到(内核下一次 pre-step 会发)": "目录还没到(内核下一次 pre-step 会发)", "目录里已经没有(": "目录里已经没有(", "目标": "目标", "目标挂起": "目标挂起", "看评估者": "看评估者", "看这一步的证据": "看这一步的证据", "确认放弃": "确认放弃", "确认放弃(留档不删,ref 保留)": "确认放弃(留档不删,ref 保留)", "等人或等世界线": "等人或等世界线", "等你说一句话": "等你说一句话", "等独立裁决": "等独立裁决", "策略暂停": "策略暂停", "策略暂停(理由没记下,已在日志里告警)": "策略暂停(理由没记下,已在日志里告警)", "算术推荐这条": "算术推荐这条", "续跑:多问我——每个阶段收尾就停下,等你给下一阶段(文档里叫「人在场」)。点一下切成「自己拿主意」。": "续跑:多问我——每个阶段收尾就停下,等你给下一阶段(文档里叫「人在场」)。点一下切成「自己拿主意」。", "续跑:自己拿主意——立约即授权,按轮数自己往下跑,只在不可约的判断上开门(文档里叫「无人值守」)。点一下切成「多问我」。": "续跑:自己拿主意——立约即授权,按轮数自己往下跑,只在不可约的判断上开门(文档里叫「无人值守」)。点一下切成「多问我」。", "续跑停着:": "续跑停着:", "续跑已撤回": "续跑已撤回", "缘由必填": "缘由必填", "缺": "缺", "能用的在上面,正在验的在下面": "能用的在上面,正在验的在下面", "自判": "自判", "自定义": "自定义", "自己拿主意": "自己拿主意", "被 ": "被 ", "被下一版命题改写": "被下一版命题改写", "裁决": "裁决", "裁决:采纳 ": "裁决:采纳 ", "要你": "要你", "观测": "观测", "计划": "计划", "计划 ": "计划 ", "计划受阻,等人处置": "计划受阻,等人处置", "计划在建,**等你确认**": "计划在建,**等你确认**", "计划已交付 ": "计划已交付 ", "计划已收尾(": "计划已收尾(", "计划待确认": "计划待确认", "计划文档": "计划文档", "计划的拓扑与闸门:脊柱、叉开的车道、收在哪、要你拍哪一下": "计划的拓扑与闸门:脊柱、叉开的车道、收在哪、要你拍哪一下", "让内核跑 ConvergeFork 落实它(合并是内核的活)": "让内核跑 ConvergeFork 落实它(合并是内核的活)", "记忆(": "记忆(", "记忆索引": "记忆索引", "证据": "证据", "证据 ": "证据 ", "评 ": "评 ", "评估": "评估", "评估卡": "评估卡", "评估者": "评估者", "评估者 ": "评估者 ", "评估者会话 ": "评估者会话 ", "评估者在裁决": "评估者在裁决", "说一句话就行 —— ": "说一句话就行 —— ", "读不到交付物:": "读不到交付物:", "读取中…": "读取中…", "读数": "读数", "读数(尺子 ": "读数(尺子 ", "起过 ": "起过 ", "跑着": "跑着", "车道 · ": "车道 · ", "边界:": "边界:", "达门槛且无推翻的命题,会在**目标验收**时由系统升格为事实(写在 clear/knowledge/facts/,模型读的 INDEX.md 同步)。": "达门槛且无推翻的命题,会在**目标验收**时由系统升格为事实(写在 clear/knowledge/facts/,模型读的 INDEX.md 同步)。", "运行时注册": "运行时注册", "还有 ": "还有 ", "还没交付": "还没交付", "还没有命题。人与模型都可以提出:每条要有一句话主张与一句「什么结果会推翻它」;通过验证的会升格到上面的事实货架。": "还没有命题。人与模型都可以提出:每条要有一句话主张与一句「什么结果会推翻它」;通过验证的会升格到上面的事实货架。", "还没有目标。目标带一份「怎样算回答了」的判据——判据在结果出现之前写下,由系统强制。": "还没有目标。目标带一份「怎样算回答了」的判据——判据在结果出现之前写下,由系统强制。", "还没有目标。立约并验证之后,达门槛且无推翻的命题会在目标验收时升格为事实。": "还没有目标。立约并验证之后,达门槛且无推翻的命题会在目标验收时升格为事实。", "还没有计划,所以还没有产物。立目标、建计划,交付过的每一步都会在这里按阶段排开。": "还没有计划,所以还没有产物。立目标、建计划,交付过的每一步都会在这里按阶段排开。", "还没有计划。计划立起来之后,这里画的是它的拓扑:脊柱上的步、叉开的车道、收在哪。": "还没有计划。计划立起来之后,这里画的是它的拓扑:脊柱上的步、叉开的车道、收在哪。", "还没有记忆。": "还没有记忆。", "还没有证据:先登记判据,再验证": "还没有证据:先登记判据,再验证", "这一步已作废(缘由:": "这一步已作废(缘由:", "这一步没有声明产物。": "这一步没有声明产物。", "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示工作区的技能目录与记忆。": "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示工作区的技能目录与记忆。", "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示已确认的事实与正在流转的命题。": "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示已确认的事实与正在流转的命题。", "这个会话还没有 ClearAI 的状态。": "这个会话还没有 ClearAI 的状态。", "这个工作区盘上已经有 ": "这个工作区盘上已经有 ", "这个工作区里还没有技能或记忆:用一次 `SaveSkill` 或 `WriteMemory`,或把技能放进 `clear/skills/`。": "这个工作区里还没有技能或记忆:用一次 `SaveSkill` 或 `WriteMemory`,或把技能放进 `clear/skills/`。", "这是系统对自己说的话(我们自己按的暂停 / 人清掉的窗口),不是运行档": "这是系统对自己说的话(我们自己按的暂停 / 人清掉的窗口),不是运行档", "进度": "进度", "采纳": "采纳", "采纳 ": "采纳 ", "采纳:改写 frontmatter,模型从此加载得到它": "采纳:改写 frontmatter,模型从此加载得到它", "采纳了某条世界线": "采纳了某条世界线", "采纳此世界线": "采纳此世界线", "问题:": "问题:", "阶段": "阶段", "阶段 ": "阶段 ", "阶段交界": "阶段交界", "需要你 ": "需要你 ", "面板动作失败:": "面板动作失败:", "项目章程": "项目章程", "预设自带": "预设自带", "验证": "验证", "验证中": "验证中", "这次采纳没有合并:": "这次采纳没有合并:", "(决定已登记,产物由一次普通交付落位)": "(决定已登记,产物由一次普通交付落位)", "分支或工作副本已不在": "分支或工作副本已不在"}
76
- const LOCALE_EN = {" · 交付 ": " · delivered ", " · 人 ": " · human ", " · 在工作区外,面板不读正文": " · outside the workspace; the panel will not read it", " · 尺子 ": " · metric ", " · 执行没跑成": " · execution did not complete", " · 支持到 ": " · supported to ", " · 最近 ": " · latest ", " · 证据 ": " · evidence ", " · 车道 ": " · lanes ", " · 随步骤作废而终止": " · ended when its step was voided", " 份)。": " files).", " 份产物,但没有任何计划声明过它们。点一条可以直接看(它们不计入交付)。": " artifacts on disk, but no plan declared them. Click one to open it (they do not count toward delivery).", " 份没列出来(这一栏只列最近改动的 ": " more not listed (this column lists only the ", " 发起": " started", " 处声明": " declared", " 字节": " bytes", " 字节 · ": " bytes · ", " 字节 · 未被任何计划声明": " bytes · declared by no plan", " 字节 · 资源 ": " bytes · resources ", " 推翻:": "refuted by:", " 旁观 ": " observe ", " 条": " entries", " 条)": " entries)", " 次侦察": " scouts", " 次评估者": " evaluators", " 步": " steps", " 步)": " steps)", " 等 ": " and ", " 评估卡": " evaluation card", " 轮": " rounds", " 里打开": "", "(假设达到这一级且无推翻才升格为事实)": " (a hypothesis is promoted to fact only at this level and with no refutation)", "(每次修订留痕,旧值不删)": " (every revision is kept; old values are not deleted)", "(点一下开右栏「世界树」)": " (click to open Worldlines)", "(点一下开右栏「世界树」看拓扑)": " (click to see the topology in Worldlines)", "(留档不删)": " (kept on record, not deleted)", "(缺)": " (missing)", "(要独立评估)才达门槛": " (independent evaluation required) to reach the threshold", "),所以这个分叉没有归宿了:**随步骤作废而终止**——它既不是被人裁掉(没人做过这个决定),也不是被算术排掉(没有尺子排过它)。要收掉工作副本(保留 ref),对它调 AbandonFork(会弹人工确认)。": "), so this fork has no destination left: **it ended when its step was voided** — it was neither decided by a person (nobody made that call) nor ranked out by arithmetic (no metric ever ranked it). To drop the working copy (keeping the ref), call AbandonFork on it (it asks for human confirmation).", "),等目标验收时升格为事实": "), and is promoted to fact when the goal is accepted", ")——它不是落选:落选意味着它跑完了、被尺子排到了后面;这一条是没跑成,所以也没有读数可以参与算术。": ") — this is not a loss: losing means it ran and was ranked behind; this one did not run, so it has no reading to enter into the arithmetic.", "**执行没跑成**(": "**Execution did not complete** (", "**执行者未归**:这条世界线的执行者派出去之后没有回灌,而分叉已经收口——它再回来也没有归宿了,所以这里既不判它跑成也没跑成,也不再等它。它的产物(如果写过)还在它自己的工作副本里;要判断那条线到底做出了什么,直接看工作副本比看这条状态可靠。": "**Executor never returned**: this worldline's executor was dispatched but never reported back, and the fork has already converged — if it returned now there would be nowhere to land, so it is neither judged done nor judged failed, and it is no longer awaited. Whatever it wrote still sits in its own working copy; to judge what that line actually produced, read the working copy rather than this status.", ":还差 ": ": short by ", ";放弃缘由:": "; reason for abandoning: ", "clearai 面板:右栏页签类型注册失败 ": "clearai panel: failed to register the right-sidebar tab type ", "clearai-loop: 席位跟着会话预设进出": "clearai-loop: seats come and go with the session's preset", "世界树": "Worldlines", "世界线:": "Worldline: ", "为什么放弃?(留痕可考)": "Why abandon it? (the record must be answerable)", "事实": "Facts", "产物": "Deliverables", "人审查后决定撤回": "withdrawn after human review", "人已撤回(记录保留)": "withdrawn by a person (record kept)", "撤回事实": "Retract the fact", "维持原事实": "Keep the fact", "被推翻,等你决定": "refuted — your call", "未走过 ": "untouched: ", "认可,继续": "Approve, continue", "撤回要留痕:点一下写缘由,写了才能提交": "A retraction needs a reason: click, write it, then confirm", "为什么撤回?(留痕可考)": "Why retract it? (the record must be answerable)", "确认撤回": "Confirm retraction", "确认撤回(记录保留,不再作为「已知」引用)": "Confirm retraction (the record is kept; it can no longer be cited as known)", "要改判据就重做一条世界线(说一句即可)": "To change the criterion instead, just say so — the model redoes one worldline", "这些等级一条证据都没有:跳到高等级不是违规,但要说得清为什么更便宜的路不通": "no evidence at these levels at all — jumping is not a violation, but say why the cheaper route would not work", "人的裁决:": "Human decision: ", "仅人可引用": "user-invocable only", "会话日志里的原生审批对(不可伪造)": "the native approval pair in the session log (cannot be forged)", "依据": "Basis", "侦 ": "S", "侦察 · ": "Scout · ", "候选": "candidate", "做什么": "What it does", "做法": "Approach", "停摆等人": "stalled, waiting on a person", "其他(": "Other (", "出现推翻证据": "refuting evidence appeared", "出现推翻证据(终态,记录保留)": "refuting evidence appeared (terminal; record kept)", "分支": "Branch", "切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)": "Switch back to an earlier worldline set (the plans are all still here, and their documents are archived under clear/goals/plans/)", "判据": "Criterion", "判据:": "Criterion: ", "判据待写": "criterion not written", "升格门槛": "Promotion threshold", "原生预览打不开这条路(它在工作区外?)": "The native preview cannot open this path (is it outside the workspace?)", "原生预览打开它": "Open it in the native preview", "原生预览打开它(计划声明的产物)": "Open it in the native preview (an artifact declared by the plan)", "合并目录、本会话用法、可引用可采纳": "Merged catalogue, usage in this session, invocable and adoptable", "命题": "Propositions", "命题 · ": "Propositions · ", "在": "in", "在 ": "in ", "在世界树里看这一步": "See this step in Worldlines", "在右栏预览": "Preview in the right sidebar", "声明的是目录;准入要求具体文件——目录不算物证": "This declares a directory; admission requires a concrete file — a directory is not physical evidence", "多问我": "Ask me more", "完成度 ": "Progress ", "完成度 —": "Progress —", "审批记录": "approval record", "工作区模板 · clear/skills": "Workspace template · clear/skills", "工作区现状(本会话还没有第一轮对话,这份还没进投影)": "Workspace as it stands (this session has no first turn yet, so this has not reached the projection)", "已交付": "delivered", "已作废": "voided", "已回灌": "reported back", "已推翻": "refuted", "已提出": "proposed", "已撤回": "withdrawn", "已收尾 · 存档可看": "closed · archived and readable", "已改版": "superseded", "已放弃": "abandoned", "已放弃探索:": "Exploration abandoned: ", "已放弃的分叉": "abandoned fork", "已替代": "superseded", "已确认": "confirmed", "已确认事实 · ": "Confirmed facts · ", "已被下一版命题替代(版本留着,不参与当前推理)": "superseded by a later version of the proposition (the version is kept but takes no part in current reasoning)", "已裁决": "decided", "已评估": "evaluated", "已达成": "achieved", "已达门槛(": "threshold reached (", "已达门槛,已升格为事实": "threshold reached; promoted to fact", "已采纳": "adopted", "待开计划": "no plan yet", "待推进": "to advance", "待裁决": "awaiting decision", "我的 · ~/.dsh": "Mine · ~/.dsh", "打开 ": "Open ", "打开「事实」那一格并展开这条命题": "Open the Facts pane and expand this proposition", "打开世界树并选中产出这条事实的验证步": "Open Worldlines and select the verification step that produced this fact", "打开世界树并选中产生这条证据的验证步": "Open Worldlines and select the verification step that produced this evidence", "打开失败:HTTP ": "Open failed: HTTP ", "打开计划文档(原生预览)": "Open the plan document (native preview)", "技能 · 记忆": "Skills · Memory", "把这道裁决摆到原生提问卡上(带你读到的判据与各分支读数)": "Put this decision on the native question card (carrying the criterion you read and each branch's reading)", "探索中": "exploring", "推翻": "refute", "推进中": "in progress", "提交中…": "Submitting…", "提交失败:": "Submit failed: ", "支持": "support", "支持到 ": "supported to ", "收敛": "converge", "收束:": "Closed with: ", "收起": "Collapse", "收起详情": "Collapse details", "放弃了这次探索": "abandoned this exploration", "放弃探索": "Abandon exploration", "放弃缘由(必填)": "Reason for abandoning (required)", "放弃要留痕:先写缘由": "Abandoning leaves a record: write the reason first", "放弃要留痕:点一下写缘由,写了才能提交": "Abandoning leaves a record: click to write the reason; it must be written before submitting", "放弃这条分叉": "Abandon this fork", "放弃这次探索(留档不删,ref 保留)": "Abandon this exploration (kept on record, ref preserved)", "放行": "release", "旁观写这条裁决的评估者子会话(论证过程)": "Observe the evaluator sub-session that wrote this verdict (the reasoning process)", "旁观评估者": "Observe evaluator", "旁观这条世界线的评估者会话(只读)": "Observe this worldline's evaluator session (read-only)", "无法判定": "inconclusive", "是目录(不算物证)": "is a directory (not physical evidence)", "最后改动 ": "Last changed ", "有了第一条证据": "the first piece of evidence arrived", "有人在等你": "someone is waiting on you", "未分类": "Uncategorised", "未声明": "not declared", "未收口(随步骤作废而终止)": "not closed (ended when its step was voided)", "未知": "unknown", "未走:": "Not taken: ", "未采纳": "not adopted", "本会话 模型 ": "This session — model ", "本体声明还没随投影下发,这里用的是规范闭环的镜像;会话跑过一拍后会自动对齐声明。": "The ontology declaration has not reached the projection yet; this shows a mirror of the canonical loop and will align with the declaration after one more step.", "本项目 · .dsh / .agents": "This project · .dsh / .agents", "本项目写的 · clear/skills": "Written by this project · clear/skills", "核心产物(": "Core deliverables (", "步 ": "step ", "没正常结束": "did not finish cleanly", "没送出去:": "Not sent: ", "派出 ": "dispatched ", "派生 · ": "derived · ", "点一条 → 右栏预览": "Click one → preview on the right", "点一行看细节": "Click a row for detail", "点开看这一步的细节": "Click to see this step's detail", "版本": "Version", "状态": "Status", "独立评估者": "independent evaluator", "用原生提问卡决定": "Decide with the native question card", "用原生预览打开章程(它每回合整份注入模型上下文)": "Open the charter in the native preview (it is injected whole into the model's context every turn)", "用提问卡决定": "Decide with a question card", "盘上已有(": "Already on disk (", "盘上没有": "not on disk", "盘上没有这个文件": "this file is not on disk", "目录": "directory", "目录还没到(内核下一次 pre-step 会发)": "The catalogue has not arrived yet (the kernel sends it on the next pre-step)", "目录里已经没有(": "no longer in the catalogue (", "目标": "Goal", "目标挂起": "goal suspended", "看评估者": "view evaluator", "看这一步的证据": "See the evidence for this step", "确认放弃": "Confirm abandon", "确认放弃(留档不删,ref 保留)": "Confirm abandon (kept on record, ref preserved)", "等人或等世界线": "waiting on a person or a worldline", "等你说一句话": "waiting for a word from you", "等独立裁决": "waiting for an independent verdict", "策略暂停": "paused by policy", "策略暂停(理由没记下,已在日志里告警)": "paused by policy (no reason recorded; a warning was logged)", "算术推荐这条": "arithmetic recommends this one", "续跑:多问我——每个阶段收尾就停下,等你给下一阶段(文档里叫「人在场」)。点一下切成「自己拿主意」。": "Continuation: ask me more — it stops at the end of each stage and waits for you to give the next one (called \"attended\" in the docs). Click to switch to \"decide for yourself\".", "续跑:自己拿主意——立约即授权,按轮数自己往下跑,只在不可约的判断上开门(文档里叫「无人值守」)。点一下切成「多问我」。": "Continuation: decide for yourself — committing a plan is the authorisation, and it keeps going for a set number of rounds, opening a gate only for decisions it cannot reduce (called \"unattended\" in the docs). Click to switch to \"ask me more\".", "续跑停着:": "Continuation is stopped: ", "续跑已撤回": "Continuation was withdrawn", "缘由必填": "A reason is required", "缺": "missing", "能用的在上面,正在验的在下面": "What you can use is on top; what is still being verified is below", "自判": "self-judged", "自定义": "custom", "自己拿主意": "Decide for yourself", "被 ": "by ", "被下一版命题改写": "rewritten by a later version of the proposition", "裁决": "Verdict", "裁决:采纳 ": "Verdict: adopt ", "要你": "needs you", "观测": "Observation", "计划": "Plan", "计划 ": "Plan ", "计划受阻,等人处置": "plan blocked, waiting for a person", "计划在建,**等你确认**": "plan is being built, **waiting for your confirmation**", "计划已交付 ": "Plan delivered ", "计划已收尾(": "Plan closed (", "计划待确认": "plan awaiting confirmation", "计划文档": "Plan document", "计划的拓扑与闸门:脊柱、叉开的车道、收在哪、要你拍哪一下": "The plan's topology and gates: the spine, the lanes that branch off, where it converges, and where you have to decide", "让内核跑 ConvergeFork 落实它(合并是内核的活)": "Let the kernel run ConvergeFork to apply it (merging is the kernel's job)", "记忆(": "Memory (", "记忆索引": "Memory index", "证据": "Evidence", "证据 ": "Evidence ", "评 ": "E", "评估": "Evaluation", "评估卡": "evaluation card", "评估者": "Evaluator", "评估者 ": "Evaluator ", "评估者会话 ": "Evaluator session ", "评估者在裁决": "an evaluator is deciding", "说一句话就行 —— ": "Just say a word — ", "读不到交付物:": "Cannot read deliverables: ", "读取中…": "Reading…", "读数": "Reading", "读数(尺子 ": "Reading (metric ", "起过 ": "ran ", "跑着": "running", "车道 · ": "Lane · ", "边界:": "Scope: ", "达门槛且无推翻的命题,会在**目标验收**时由系统升格为事实(写在 clear/knowledge/facts/,模型读的 INDEX.md 同步)。": "A proposition that reaches the threshold with no refutation is promoted to fact by the system when the **goal is accepted** (written under clear/knowledge/facts/, with the INDEX.md the model reads kept in sync).", "运行时注册": "registered at runtime", "还有 ": "and ", "还没交付": "not delivered yet", "还没有命题。人与模型都可以提出:每条要有一句话主张与一句「什么结果会推翻它」;通过验证的会升格到上面的事实货架。": "No propositions yet. Both the person and the model can raise one: each needs a one-line claim and a line saying what result would refute it; those that pass verification are promoted to the fact shelf above.", "还没有目标。目标带一份「怎样算回答了」的判据——判据在结果出现之前写下,由系统强制。": "No goal yet. A goal carries a criterion for what would count as an answer — written before any result appears, and enforced by the system.", "还没有目标。立约并验证之后,达门槛且无推翻的命题会在目标验收时升格为事实。": "No goal yet. After you commit a plan and verify it, propositions that reach the threshold with no refutation are promoted to fact when the goal is accepted.", "还没有计划,所以还没有产物。立目标、建计划,交付过的每一步都会在这里按阶段排开。": "No plan yet, so no deliverables. Set a goal and build a plan; every step you deliver will line up here by stage.", "还没有计划。计划立起来之后,这里画的是它的拓扑:脊柱上的步、叉开的车道、收在哪。": "No plan yet. Once one is committed, this draws its topology: the steps on the spine, the lanes that branch off, and where it converges.", "还没有记忆。": "No memory yet.", "还没有证据:先登记判据,再验证": "No evidence yet: register the criterion first, then verify", "这一步已作废(缘由:": "This step was voided (reason: ", "这一步没有声明产物。": "This step declares no artifacts.", "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示工作区的技能目录与记忆。": "This session has not started: the panels read the session log, so after your first message this will show the workspace's skill catalogue and memory.", "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示已确认的事实与正在流转的命题。": "This session has not started: the panels read the session log, so after your first message this will show confirmed facts and the propositions in flight.", "这个会话还没有 ClearAI 的状态。": "This session has no ClearAI state yet.", "这个工作区盘上已经有 ": "This workspace already has ", "这个工作区里还没有技能或记忆:用一次 `SaveSkill` 或 `WriteMemory`,或把技能放进 `clear/skills/`。": "This workspace has no skills or memory yet: use `SaveSkill` or `WriteMemory` once, or put a skill under `clear/skills/`.", "这是系统对自己说的话(我们自己按的暂停 / 人清掉的窗口),不是运行档": "This is the system talking to itself (a pause we pressed, or a window a person cleared) — not a run mode", "进度": "Progress", "采纳": "Adopt", "采纳 ": "Adopt ", "采纳:改写 frontmatter,模型从此加载得到它": "Adopt: rewrites the frontmatter so the model can load it from then on", "采纳了某条世界线": "adopted one worldline", "采纳此世界线": "Adopt this worldline", "问题:": "Question: ", "阶段": "Stage", "阶段 ": "Stage ", "阶段交界": "at a stage boundary", "需要你 ": "needs you ", "面板动作失败:": "Panel action failed: ", "项目章程": "Project charter", "预设自带": "shipped with the preset", "验证": "Verification", "验证中": "verifying", "这次采纳没有合并:": "This adoption was not merged: ", "(决定已登记,产物由一次普通交付落位)": " (the decision is on record; a normal delivery places the artifacts)", "分支或工作副本已不在": "its branch or working copy is gone"}
75
+ const LOCALE_ZH = {"还有 ": "还有 ", " 条未列出 · 用 / 触发菜单选": " 条未列出 · 用 / 触发菜单选", "被推翻 · 待裁决": "被推翻 · 待裁决", "等待输入": "等待输入", "等待人工处理": "等待人工处理", "等待中": "等待中", "等待人工": "等待人工", "异常终止": "异常终止", "发送失败:": "发送失败:", "已获首条证据": "已获首条证据", "按判据推荐": "按判据推荐", "系统内部消息(非运行状态)": "系统内部消息(非运行状态)", "填写缘由后提交": "填写缘由后提交", "请填写缘由": "请填写缘由", "点击在右栏预览": "点击在右栏预览", "点击查看详情": "点击查看详情", "查看步骤详情": "查看步骤详情", "查看词条": "查看词条", "放弃需填写缘由后提交": "放弃需填写缘由后提交", "撤回需填写缘由后提交": "撤回需填写缘由后提交", "暂无数据。发送第一条消息后,此处显示已确立条目与在验命题。": "暂无数据。发送第一条消息后,此处显示已确立条目与在验命题。", "暂无数据。发送第一条消息后,此处显示技能目录与记忆。": "暂无数据。发送第一条消息后,此处显示技能目录与记忆。", "暂无命题。每条需一句主张与一句推翻条件;通过验证后升格为事实。": "暂无命题。每条需一句主张与一句推翻条件;通过验证后升格为事实。", "暂无目标。目标携带验收判据;判据在结果出现之前登记。": "暂无目标。目标携带验收判据;判据在结果出现之前登记。", "暂无目标。验证达门槛且无推翻的命题在验收时升格为事实。": "暂无目标。验证达门槛且无推翻的命题在验收时升格为事实。", "暂无计划。建立计划后,已交付步骤按阶段列于此处。": "暂无计划。建立计划后,已交付步骤按阶段列于此处。", "暂无计划。建立后此处显示计划拓扑:脊柱步、车道与收敛点。": "暂无计划。建立后此处显示计划拓扑:脊柱步、车道与收敛点。", "暂无记忆。": "暂无记忆。", "暂无证据。先登记判据,后执行验证。": "暂无证据。先登记判据,后执行验证。", "此层暂无节点。": "此层暂无节点。", "暂无技能或记忆。使用 `SaveSkill` / `WriteMemory`,或将技能放入 `clear/skills/`。": "暂无技能或记忆。使用 `SaveSkill` / `WriteMemory`,或将技能放入 `clear/skills/`。", "达门槛且无推翻的命题在目标验收时升格为事实(写入 clear/knowledge/facts/)。": "达门槛且无推翻的命题在目标验收时升格为事实(写入 clear/knowledge/facts/)。", "修改判据需重新建立世界线": "修改判据需重新建立世界线", "计划的拓扑与闸门:脊柱步、车道、收敛点、人工决策点": "计划的拓扑与闸门:脊柱步、车道、收敛点、人工决策点", "由内核执行 ConvergeFork 完成合并": "由内核执行 ConvergeFork 完成合并", "通过提问卡做出裁决(含判据与各分支读数)": "通过提问卡做出裁决(含判据与各分支读数)", "通过提问卡决定": "通过提问卡决定", "在世界树中查看此步骤": "在世界树中查看此步骤", "右栏预览": "右栏预览", "查看此步骤的证据": "查看此步骤的证据", "查看评估者": "查看评估者", "工作区现状(首轮对话后进入投影)": "工作区现状(首轮对话后进入投影)", "本体声明尚未进入投影;当前显示规范闭环的镜像,下一拍自动对齐。": "本体声明尚未进入投影;当前显示规范闭环的镜像,下一拍自动对齐。", "目录尚未到达(内核下一次 pre-step 下发)": "目录尚未到达(内核下一次 pre-step 下发)", "这些等级尚无证据:跳级不违规,但需说明原因": "这些等级尚无证据:跳级不违规,但需说明原因", "此谓词已不在词汇中(可能已废止);存量断言仍可读。": "此谓词已不在词汇中(可能已废止);存量断言仍可读。", "策略暂停(原因未记录,已告警)": "策略暂停(原因未记录,已告警)", "未升格:断言仍在命题上": "未升格:断言仍在命题上", "放弃缘由(必填)": "放弃缘由(必填)", "撤回缘由(必填)": "撤回缘由(必填)", "登记概念": "登记概念", "登记谓词": "登记谓词", "名称": "名称", "单位": "单位", "提交": "提交", "取消": "取消", "废止": "废止", "为什么?": "为什么?", "提交中…": "提交中…", "点节点按概念过滤 · 滚轮缩放 · 拖拽平移": "点节点按概念过滤 · 滚轮缩放 · 拖拽平移", "复位": "复位", "全景": "全景", "还原": "还原", "展开图带": "展开图带", "图里只画了前": "图里只画了前", " 个节点;全景可看全部": " 个节点;全景可看全部", "一条边": "一条边", "词汇": "词汇", "概念": "概念", "谓词": "谓词", "已废止": "已废止", "健康": "健康", "单值": "单值", "打开词汇货架(原生预览)": "打开词汇货架(原生预览)", "冲突": "冲突", " 对": " 对", "只暴露,不裁决;撤回或维持由人决定": "只暴露,不裁决;撤回或维持由人决定", "按": "按", "过滤": "", "清除": "清除", "按此谓词过滤": "按此谓词过滤", "在图里看": "在图里看", " · 未升格": " · 未升格", "释义": "释义", "主词域": "主词域", "值域": "值域", "本体": "本体", "本体货架 · ": "本体货架 · ", "这里会长出你的本体:已确立的条目与在验的命题。": "这里会长出你的本体:已确立的条目与在验的命题。", "本体图": "本体图", "实体图": "实体图", " · 交付 ": " · 交付 ", " · 人 ": " · 人 ", " · 在工作区外,面板不读正文": " · 在工作区外,面板不读正文", " · 尺子 ": " · 尺子 ", " · 执行没跑成": " · 执行没跑成", " · 支持到 ": " · 支持到 ", " · 最近 ": " · 最近 ", " · 证据 ": " · 证据 ", " · 车道 ": " · 车道 ", " · 随步骤作废而终止": " · 随步骤作废而终止", " 份)。": " 份)。", " 份产物,但没有任何计划声明过它们。点一条可以直接看(它们不计入交付)。": " 份产物,但没有任何计划声明过它们。点一条可以直接看(它们不计入交付)。", " 份没列出来(这一栏只列最近改动的 ": " 份没列出来(这一栏只列最近改动的 ", " 发起": " 发起", " 处声明": " 处声明", " 字节": " 字节", " 字节 · ": " 字节 · ", " 字节 · 未被任何计划声明": " 字节 · 未被任何计划声明", " 字节 · 资源 ": " 字节 · 资源 ", " 推翻:": " 推翻:", " 旁观 ": " 旁观 ", " 条": " 条", " 条)": " 条)", " 次侦察": " 次侦察", " 次评估者": " 次评估者", " 步": " 步", " 步)": " 步)", " 等 ": " 等 ", " 评估卡": " 评估卡", " 轮": " 轮", " 里打开": " 里打开", "(假设达到这一级且无推翻才升格为事实)": "(假设达到这一级且无推翻才升格为事实)", "(每次修订留痕,旧值不删)": "(每次修订留痕,旧值不删)", "(点一下开右栏「世界树」)": "(点一下开右栏「世界树」)", "(点一下开右栏「世界树」看拓扑)": "(点一下开右栏「世界树」看拓扑)", "(留档不删)": "(留档不删)", "(缺)": "(缺)", "(要独立评估)才达门槛": "(要独立评估)才达门槛", "),所以这个分叉没有归宿了:**随步骤作废而终止**——它既不是被人裁掉(没人做过这个决定),也不是被算术排掉(没有尺子排过它)。要收掉工作副本(保留 ref),对它调 AbandonFork(会弹人工确认)。": "),所以这个分叉没有归宿了:**随步骤作废而终止**——它既不是被人裁掉(没人做过这个决定),也不是被算术排掉(没有尺子排过它)。要收掉工作副本(保留 ref),对它调 AbandonFork(会弹人工确认)。", "),等目标验收时升格为事实": "),等目标验收时升格为事实", ")——它不是落选:落选意味着它跑完了、被尺子排到了后面;这一条是没跑成,所以也没有读数可以参与算术。": ")——它不是落选:落选意味着它跑完了、被尺子排到了后面;这一条是没跑成,所以也没有读数可以参与算术。", "**执行没跑成**(": "**执行没跑成**(", "**执行者未归**:这条世界线的执行者派出去之后没有回灌,而分叉已经收口——它再回来也没有归宿了,所以这里既不判它跑成也没跑成,也不再等它。它的产物(如果写过)还在它自己的工作副本里;要判断那条线到底做出了什么,直接看工作副本比看这条状态可靠。": "**执行者未归**:这条世界线的执行者派出去之后没有回灌,而分叉已经收口——它再回来也没有归宿了,所以这里既不判它跑成也没跑成,也不再等它。它的产物(如果写过)还在它自己的工作副本里;要判断那条线到底做出了什么,直接看工作副本比看这条状态可靠。", ":还差 ": ":还差 ", ";放弃缘由:": ";放弃缘由:", "clearai 面板:右栏页签类型注册失败 ": "clearai 面板:右栏页签类型注册失败 ", "clearai-loop: 席位跟着会话预设进出": "clearai-loop: 席位跟着会话预设进出", "世界树": "世界树", "世界线:": "世界线:", "事实": "事实", "产物": "产物", "人审查后决定撤回": "人审查后决定撤回", "人已撤回(记录保留)": "人已撤回(记录保留)", "撤回事实": "撤回事实", "维持原事实": "维持原事实", "未走过 ": "未走过 ", "认可,继续": "认可,继续", "确认撤回": "确认撤回", "确认撤回(记录保留,不再作为「已知」引用)": "确认撤回(记录保留,不再作为「已知」引用)", "人的裁决:": "人的裁决:", "仅人可引用": "仅人可引用", "会话日志里的原生审批对(不可伪造)": "会话日志里的原生审批对(不可伪造)", "依据": "依据", "侦 ": "侦 ", "侦察 · ": "侦察 · ", "候选": "候选", "做什么": "做什么", "做法": "做法", "其他(": "其他(", "出现推翻证据": "出现推翻证据", "出现推翻证据(终态,记录保留)": "出现推翻证据(终态,记录保留)", "分支": "分支", "切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)": "切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)", "判据": "判据", "判据:": "判据:", "判据待写": "判据待写", "升格门槛": "升格门槛", "原生预览打不开这条路(它在工作区外?)": "原生预览打不开这条路(它在工作区外?)", "原生预览打开它": "原生预览打开它", "原生预览打开它(计划声明的产物)": "原生预览打开它(计划声明的产物)", "合并目录、本会话用法、可引用可采纳": "合并目录、本会话用法、可引用可采纳", "命题": "命题", "命题 · ": "命题 · ", "在": "在", "在 ": "在 ", "声明的是目录;准入要求具体文件——目录不算物证": "声明的是目录;准入要求具体文件——目录不算物证", "多问我": "多问我", "完成度 ": "完成度 ", "完成度 —": "完成度 —", "审批记录": "审批记录", "工作区模板 · clear/skills": "工作区模板 · clear/skills", "已交付": "已交付", "已作废": "已作废", "已回灌": "已回灌", "已推翻": "已推翻", "已提出": "已提出", "已撤回": "已撤回", "已收尾 · 存档可看": "已收尾 · 存档可看", "已改版": "已改版", "已放弃": "已放弃", "已放弃探索:": "已放弃探索:", "已放弃的分叉": "已放弃的分叉", "已替代": "已替代", "已确认": "已确认", "已确认事实 · ": "已确认事实 · ", "已被下一版命题替代(版本留着,不参与当前推理)": "已被下一版命题替代(版本留着,不参与当前推理)", "已裁决": "已裁决", "已评估": "已评估", "已达成": "已达成", "已达门槛(": "已达门槛(", "已达门槛,已升格为事实": "已达门槛,已升格为事实", "已采纳": "已采纳", "待开计划": "待开计划", "待推进": "待推进", "待裁决": "待裁决", "我的 · ~/.dsh": "我的 · ~/.dsh", "打开 ": "打开 ", "打开「事实」那一格并展开这条命题": "打开「事实」那一格并展开这条命题", "打开世界树并选中产出这条事实的验证步": "打开世界树并选中产出这条事实的验证步", "打开世界树并选中产生这条证据的验证步": "打开世界树并选中产生这条证据的验证步", "打开失败:HTTP ": "打开失败:HTTP ", "打开计划文档(原生预览)": "打开计划文档(原生预览)", "技能 · 记忆": "技能 · 记忆", "探索中": "探索中", "推翻": "推翻", "推进中": "推进中", "提交中…": "提交中…", "提交失败:": "提交失败:", "支持": "支持", "支持到 ": "支持到 ", "收敛": "收敛", "收束:": "收束:", "收起": "收起", "收起详情": "收起详情", "放弃了这次探索": "放弃了这次探索", "放弃探索": "放弃探索", "放弃缘由(必填)": "Reason for abandoning (required)", "放弃这条分叉": "放弃这条分叉", "放弃这次探索(留档不删,ref 保留)": "放弃这次探索(留档不删,ref 保留)", "放行": "放行", "旁观写这条裁决的评估者子会话(论证过程)": "旁观写这条裁决的评估者子会话(论证过程)", "旁观评估者": "旁观评估者", "旁观这条世界线的评估者会话(只读)": "旁观这条世界线的评估者会话(只读)", "无法判定": "无法判定", "是目录(不算物证)": "是目录(不算物证)", "最后改动 ": "最后改动 ", "未分类": "未分类", "未声明": "未声明", "未收口(随步骤作废而终止)": "未收口(随步骤作废而终止)", "未知": "未知", "未走:": "未走:", "未采纳": "未采纳", "本会话 模型 ": "本会话 模型 ", "本项目 · .dsh / .agents": "本项目 · .dsh / .agents", "本项目写的 · clear/skills": "本项目写的 · clear/skills", "核心产物(": "核心产物(", "步 ": "步 ", "派出 ": "派出 ", "派生 · ": "派生 · ", "版本": "版本", "状态": "状态", "独立评估者": "独立评估者", "用原生预览打开章程(它每回合整份注入模型上下文)": "用原生预览打开章程(它每回合整份注入模型上下文)", "盘上已有(": "盘上已有(", "盘上没有": "盘上没有", "盘上没有这个文件": "盘上没有这个文件", "目录": "目录", "目录里已经没有(": "目录里已经没有(", "目标": "目标", "目标挂起": "目标挂起", "确认放弃": "确认放弃", "确认放弃(留档不删,ref 保留)": "确认放弃(留档不删,ref 保留)", "等独立裁决": "等独立裁决", "策略暂停": "策略暂停", "续跑:多问我——每个阶段收尾就停下,等你给下一阶段(文档里叫「人在场」)。点一下切成「自己拿主意」。": "续跑:多问我——每个阶段收尾就停下,等你给下一阶段(文档里叫「人在场」)。点一下切成「自己拿主意」。", "续跑:自己拿主意——立约即授权,按轮数自己往下跑,只在不可约的判断上开门(文档里叫「无人值守」)。点一下切成「多问我」。": "续跑:自己拿主意——立约即授权,按轮数自己往下跑,只在不可约的判断上开门(文档里叫「无人值守」)。点一下切成「多问我」。", "续跑停着:": "续跑停着:", "续跑已撤回": "续跑已撤回", "缘由必填": "缘由必填", "缺": "缺", "自判": "自判", "自定义": "自定义", "自己拿主意": "自己拿主意", "被 ": "被 ", "被下一版命题改写": "被下一版命题改写", "裁决": "裁决", "裁决:采纳 ": "裁决:采纳 ", "要你": "要你", "观测": "观测", "计划": "计划", "计划 ": "计划 ", "计划受阻,等人处置": "计划受阻,等人处置", "计划在建,**等你确认**": "计划在建,**等你确认**", "计划已交付 ": "计划已交付 ", "计划已收尾(": "计划已收尾(", "计划待确认": "计划待确认", "计划文档": "计划文档", "记忆(": "记忆(", "记忆索引": "记忆索引", "证据": "证据", "证据 ": "证据 ", "评 ": "评 ", "评估": "评估", "评估卡": "评估卡", "评估者": "评估者", "评估者 ": "评估者 ", "评估者会话 ": "评估者会话 ", "评估者在裁决": "评估者在裁决", "读不到交付物:": "读不到交付物:", "读取中…": "读取中…", "读数": "读数", "读数(尺子 ": "读数(尺子 ", "起过 ": "起过 ", "跑着": "跑着", "车道 · ": "车道 · ", "边界:": "边界:", "运行时注册": "运行时注册", "还有 ": "还有 ", "还没交付": "还没交付", "这一步已作废(缘由:": "这一步已作废(缘由:", "这一步没有声明产物。": "这一步没有声明产物。", "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示已确认的事实与正在流转的命题。": "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示已确认的事实与正在流转的命题。", "这个会话还没有 ClearAI 的状态。": "这个会话还没有 ClearAI 的状态。", "这个工作区盘上已经有 ": "这个工作区盘上已经有 ", "进度": "进度", "采纳": "采纳", "采纳 ": "采纳 ", "采纳:改写 frontmatter,模型从此加载得到它": "采纳:改写 frontmatter,模型从此加载得到它", "采纳了某条世界线": "采纳了某条世界线", "采纳此世界线": "采纳此世界线", "问题:": "问题:", "阶段": "阶段", "阶段 ": "阶段 ", "阶段交界": "阶段交界", "需要你 ": "需要你 ", "面板动作失败:": "面板动作失败:", "项目章程": "项目章程", "预设自带": "预设自带", "验证": "验证", "验证中": "验证中", "这次采纳没有合并:": "这次采纳没有合并:", "(决定已登记,产物由一次普通交付落位)": "(决定已登记,产物由一次普通交付落位)", "分支或工作副本已不在": "分支或工作副本已不在"}
76
+ const LOCALE_EN = {"还有 ": "and ", " 条未列出 · 用 / 触发菜单选": " more not listed · pick them from the / menu", "被推翻 · 待裁决": "refuted · awaiting decision", "等待输入": "awaiting input", "等待人工处理": "awaiting human action", "等待中": "waiting", "等待人工": "awaiting human", "异常终止": "terminated abnormally", "发送失败:": "send failed: ", "已获首条证据": "first evidence received", "按判据推荐": "recommended by criterion", "系统内部消息(非运行状态)": "system-internal message (not a run state)", "填写缘由后提交": "fill in the reason, then submit", "请填写缘由": "reason required", "点击在右栏预览": "click to preview in the right sidebar", "点击查看详情": "click for details", "查看步骤详情": "view step details", "查看词条": "view term", "放弃需填写缘由后提交": "fill in the reason before abandoning", "撤回需填写缘由后提交": "fill in the reason before retracting", "暂无数据。发送第一条消息后,此处显示已确立条目与在验命题。": "No data yet. After your first message this shows established entries and propositions in verification.", "暂无数据。发送第一条消息后,此处显示技能目录与记忆。": "No data yet. After your first message this shows the skill catalogue and memory.", "暂无命题。每条需一句主张与一句推翻条件;通过验证后升格为事实。": "No propositions yet. Each needs a one-line claim and a refutation condition; verified ones are promoted to facts.", "暂无目标。目标携带验收判据;判据在结果出现之前登记。": "No goal yet. A goal carries its acceptance criterion; the criterion is registered before any result.", "暂无目标。验证达门槛且无推翻的命题在验收时升格为事实。": "No goal yet. Verified propositions reaching the threshold without refutation are promoted at acceptance.", "暂无计划。建立计划后,已交付步骤按阶段列于此处。": "No plan yet. Delivered steps are listed here by stage once a plan exists.", "暂无计划。建立后此处显示计划拓扑:脊柱步、车道与收敛点。": "No plan yet. Once committed, this shows the plan topology: spine steps, lanes, and convergence.", "暂无记忆。": "No memory yet.", "暂无证据。先登记判据,后执行验证。": "No evidence yet. Register the criterion first, then verify.", "此层暂无节点。": "No nodes on this layer yet.", "暂无技能或记忆。使用 `SaveSkill` / `WriteMemory`,或将技能放入 `clear/skills/`。": "No skills or memory yet. Use `SaveSkill` / `WriteMemory`, or put a skill under `clear/skills/`.", "达门槛且无推翻的命题在目标验收时升格为事实(写入 clear/knowledge/facts/)。": "Propositions reaching the threshold with no refutation are promoted to fact at goal acceptance (written under clear/knowledge/facts/).", "修改判据需重新建立世界线": "changing the criterion requires a new worldline", "计划的拓扑与闸门:脊柱步、车道、收敛点、人工决策点": "Plan topology and gates: spine steps, lanes, convergence, human decision points", "由内核执行 ConvergeFork 完成合并": "the kernel runs ConvergeFork to complete the merge", "通过提问卡做出裁决(含判据与各分支读数)": "decide via the question card (with the criterion and each branch's reading)", "通过提问卡决定": "decide via question card", "在世界树中查看此步骤": "see this step in Worldlines", "右栏预览": "preview in right sidebar", "查看此步骤的证据": "see the evidence for this step", "查看评估者": "view evaluator", "工作区现状(首轮对话后进入投影)": "workspace state (enters the projection after the first turn)", "本体声明尚未进入投影;当前显示规范闭环的镜像,下一拍自动对齐。": "The ontology declaration has not reached the projection; a canonical-loop mirror is shown and will align at the next step.", "目录尚未到达(内核下一次 pre-step 下发)": "the catalogue has not arrived yet (the kernel sends it on the next pre-step)", "这些等级尚无证据:跳级不违规,但需说明原因": "no evidence at these levels: skipping is not a violation, but state why", "此谓词已不在词汇中(可能已废止);存量断言仍可读。": "this predicate is no longer in the vocabulary (possibly deprecated); existing assertions remain readable.", "策略暂停(原因未记录,已告警)": "paused by policy (reason not recorded; warned)", "未升格:断言仍在命题上": "not yet promoted: the assertion is still on a proposition", "放弃缘由(必填)": "Reason for abandoning (required)", "撤回缘由(必填)": "Reason for retracting (required)", "登记概念": "Register a concept", "登记谓词": "Register a predicate", "名称": "Label", "单位": "Unit", "提交": "Submit", "取消": "Cancel", "废止": "Deprecate", "为什么?": "Why?", "提交中…": "Submitting…", "点节点按概念过滤 · 滚轮缩放 · 拖拽平移": "Click a node to filter by concept · wheel to zoom · drag to pan", "复位": "Reset view", "全景": "Panorama", "还原": "Restore", "展开图带": "Show the graph band", "图里只画了前": "Showing the first", " 个节点;全景可看全部": " nodes; the panorama shows all", "一条边": "An edge", "词汇": "Vocabulary", "概念": "concepts", "谓词": "predicates", "已废止": "deprecated", "健康": "Health", "单值": "single-valued", "打开词汇货架(原生预览)": "Open the vocabulary shelf (native preview)", "冲突": "Conflict", " 对": " pair(s)", "只暴露,不裁决;撤回或维持由人决定": "surfaced, never adjudicated; retracting or keeping is a human decision", "按": "Filtered by", "过滤": "", "清除": "Clear", "按此谓词过滤": "Filter by this predicate", "在图里看": "See it in the graph", " · 未升格": " · not yet promoted", "释义": "Gloss", "主词域": "Subject domain", "值域": "Range", "本体": "Ontology", "本体货架 · ": "Ontology shelf · ", "这里会长出你的本体:已确立的条目与在验的命题。": "This is where your ontology grows: established entries and propositions still in verification.", "本体图": "Ontology graph", "实体图": "Entity graph", " · 交付 ": " · delivered ", " · 人 ": " · human ", " · 在工作区外,面板不读正文": " · outside the workspace; the panel will not read it", " · 尺子 ": " · metric ", " · 执行没跑成": " · execution did not complete", " · 支持到 ": " · supported to ", " · 最近 ": " · latest ", " · 证据 ": " · evidence ", " · 车道 ": " · lanes ", " · 随步骤作废而终止": " · ended when its step was voided", " 份)。": " files).", " 份产物,但没有任何计划声明过它们。点一条可以直接看(它们不计入交付)。": " artifacts on disk, but no plan declared them. Click one to open it (they do not count toward delivery).", " 份没列出来(这一栏只列最近改动的 ": " more not listed (this column lists only the ", " 发起": " started", " 处声明": " declared", " 字节": " bytes", " 字节 · ": " bytes · ", " 字节 · 未被任何计划声明": " bytes · declared by no plan", " 字节 · 资源 ": " bytes · resources ", " 推翻:": "refuted by:", " 旁观 ": " observe ", " 条": " entries", " 条)": " entries)", " 次侦察": " scouts", " 次评估者": " evaluators", " 步": " steps", " 步)": " steps)", " 等 ": " and ", " 评估卡": " evaluation card", " 轮": " rounds", " 里打开": "", "(假设达到这一级且无推翻才升格为事实)": " (a hypothesis is promoted to fact only at this level and with no refutation)", "(每次修订留痕,旧值不删)": " (every revision is kept; old values are not deleted)", "(点一下开右栏「世界树」)": " (click to open Worldlines)", "(点一下开右栏「世界树」看拓扑)": " (click to see the topology in Worldlines)", "(留档不删)": " (kept on record, not deleted)", "(缺)": " (missing)", "(要独立评估)才达门槛": " (independent evaluation required) to reach the threshold", "),所以这个分叉没有归宿了:**随步骤作废而终止**——它既不是被人裁掉(没人做过这个决定),也不是被算术排掉(没有尺子排过它)。要收掉工作副本(保留 ref),对它调 AbandonFork(会弹人工确认)。": "), so this fork has no destination left: **it ended when its step was voided** — it was neither decided by a person (nobody made that call) nor ranked out by arithmetic (no metric ever ranked it). To drop the working copy (keeping the ref), call AbandonFork on it (it asks for human confirmation).", "),等目标验收时升格为事实": "), and is promoted to fact when the goal is accepted", ")——它不是落选:落选意味着它跑完了、被尺子排到了后面;这一条是没跑成,所以也没有读数可以参与算术。": ") — this is not a loss: losing means it ran and was ranked behind; this one did not run, so it has no reading to enter into the arithmetic.", "**执行没跑成**(": "**Execution did not complete** (", "**执行者未归**:这条世界线的执行者派出去之后没有回灌,而分叉已经收口——它再回来也没有归宿了,所以这里既不判它跑成也没跑成,也不再等它。它的产物(如果写过)还在它自己的工作副本里;要判断那条线到底做出了什么,直接看工作副本比看这条状态可靠。": "**Executor never returned**: this worldline's executor was dispatched but never reported back, and the fork has already converged — if it returned now there would be nowhere to land, so it is neither judged done nor judged failed, and it is no longer awaited. Whatever it wrote still sits in its own working copy; to judge what that line actually produced, read the working copy rather than this status.", ":还差 ": ": short by ", ";放弃缘由:": "; reason for abandoning: ", "clearai 面板:右栏页签类型注册失败 ": "clearai panel: failed to register the right-sidebar tab type ", "clearai-loop: 席位跟着会话预设进出": "clearai-loop: seats come and go with the session's preset", "世界树": "Worldlines", "世界线:": "Worldline: ", "事实": "Facts", "产物": "Deliverables", "人审查后决定撤回": "withdrawn after human review", "人已撤回(记录保留)": "withdrawn by a person (record kept)", "撤回事实": "Retract the fact", "维持原事实": "Keep the fact", "未走过 ": "untouched: ", "认可,继续": "Approve, continue", "确认撤回": "Confirm retraction", "确认撤回(记录保留,不再作为「已知」引用)": "Confirm retraction (the record is kept; it can no longer be cited as known)", "人的裁决:": "Human decision: ", "仅人可引用": "user-invocable only", "会话日志里的原生审批对(不可伪造)": "the native approval pair in the session log (cannot be forged)", "依据": "Basis", "侦 ": "S", "侦察 · ": "Scout · ", "候选": "candidate", "做什么": "What it does", "做法": "Approach", "其他(": "Other (", "出现推翻证据": "refuting evidence appeared", "出现推翻证据(终态,记录保留)": "refuting evidence appeared (terminal; record kept)", "分支": "Branch", "切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)": "Switch back to an earlier worldline set (the plans are all still here, and their documents are archived under clear/goals/plans/)", "判据": "Criterion", "判据:": "Criterion: ", "判据待写": "criterion not written", "升格门槛": "Promotion threshold", "原生预览打不开这条路(它在工作区外?)": "The native preview cannot open this path (is it outside the workspace?)", "原生预览打开它": "Open it in the native preview", "原生预览打开它(计划声明的产物)": "Open it in the native preview (an artifact declared by the plan)", "合并目录、本会话用法、可引用可采纳": "Merged catalogue, usage in this session, invocable and adoptable", "命题": "Propositions", "命题 · ": "Propositions · ", "在": "in", "在 ": "in ", "声明的是目录;准入要求具体文件——目录不算物证": "This declares a directory; admission requires a concrete file — a directory is not physical evidence", "多问我": "Ask me more", "完成度 ": "Progress ", "完成度 —": "Progress —", "审批记录": "approval record", "工作区模板 · clear/skills": "Workspace template · clear/skills", "已交付": "delivered", "已作废": "voided", "已回灌": "reported back", "已推翻": "refuted", "已提出": "proposed", "已撤回": "withdrawn", "已收尾 · 存档可看": "closed · archived and readable", "已改版": "superseded", "已放弃": "abandoned", "已放弃探索:": "Exploration abandoned: ", "已放弃的分叉": "abandoned fork", "已替代": "superseded", "已确认": "confirmed", "已确认事实 · ": "Confirmed facts · ", "已被下一版命题替代(版本留着,不参与当前推理)": "superseded by a later version of the proposition (the version is kept but takes no part in current reasoning)", "已裁决": "decided", "已评估": "evaluated", "已达成": "achieved", "已达门槛(": "threshold reached (", "已达门槛,已升格为事实": "threshold reached; promoted to fact", "已采纳": "adopted", "待开计划": "no plan yet", "待推进": "to advance", "待裁决": "awaiting decision", "我的 · ~/.dsh": "Mine · ~/.dsh", "打开 ": "Open ", "打开「事实」那一格并展开这条命题": "Open the Facts pane and expand this proposition", "打开世界树并选中产出这条事实的验证步": "Open Worldlines and select the verification step that produced this fact", "打开世界树并选中产生这条证据的验证步": "Open Worldlines and select the verification step that produced this evidence", "打开失败:HTTP ": "Open failed: HTTP ", "打开计划文档(原生预览)": "Open the plan document (native preview)", "技能 · 记忆": "Skills · Memory", "探索中": "exploring", "推翻": "refute", "推进中": "in progress", "提交中…": "Submitting…", "提交失败:": "Submit failed: ", "支持": "support", "支持到 ": "supported to ", "收敛": "converge", "收束:": "Closed with: ", "收起": "Collapse", "收起详情": "Collapse details", "放弃了这次探索": "abandoned this exploration", "放弃探索": "Abandon exploration", "放弃缘由(必填)": "Reason for abandoning (required)", "放弃这条分叉": "Abandon this fork", "放弃这次探索(留档不删,ref 保留)": "Abandon this exploration (kept on record, ref preserved)", "放行": "release", "旁观写这条裁决的评估者子会话(论证过程)": "Observe the evaluator sub-session that wrote this verdict (the reasoning process)", "旁观评估者": "Observe evaluator", "旁观这条世界线的评估者会话(只读)": "Observe this worldline's evaluator session (read-only)", "无法判定": "inconclusive", "是目录(不算物证)": "is a directory (not physical evidence)", "最后改动 ": "Last changed ", "未分类": "Uncategorised", "未声明": "not declared", "未收口(随步骤作废而终止)": "not closed (ended when its step was voided)", "未知": "unknown", "未走:": "Not taken: ", "未采纳": "not adopted", "本会话 模型 ": "This session — model ", "本项目 · .dsh / .agents": "This project · .dsh / .agents", "本项目写的 · clear/skills": "Written by this project · clear/skills", "核心产物(": "Core deliverables (", "步 ": "step ", "派出 ": "dispatched ", "派生 · ": "derived · ", "版本": "Version", "状态": "Status", "独立评估者": "independent evaluator", "用原生预览打开章程(它每回合整份注入模型上下文)": "Open the charter in the native preview (it is injected whole into the model's context every turn)", "盘上已有(": "Already on disk (", "盘上没有": "not on disk", "盘上没有这个文件": "this file is not on disk", "目录": "directory", "目录里已经没有(": "no longer in the catalogue (", "目标": "Goal", "目标挂起": "goal suspended", "确认放弃": "Confirm abandon", "确认放弃(留档不删,ref 保留)": "Confirm abandon (kept on record, ref preserved)", "等独立裁决": "waiting for an independent verdict", "策略暂停": "paused by policy", "续跑:多问我——每个阶段收尾就停下,等你给下一阶段(文档里叫「人在场」)。点一下切成「自己拿主意」。": "Continuation: ask me more — it stops at the end of each stage and waits for you to give the next one (called \"attended\" in the docs). Click to switch to \"decide for yourself\".", "续跑:自己拿主意——立约即授权,按轮数自己往下跑,只在不可约的判断上开门(文档里叫「无人值守」)。点一下切成「多问我」。": "Continuation: decide for yourself — committing a plan is the authorisation, and it keeps going for a set number of rounds, opening a gate only for decisions it cannot reduce (called \"unattended\" in the docs). Click to switch to \"ask me more\".", "续跑停着:": "Continuation is stopped: ", "续跑已撤回": "Continuation was withdrawn", "缘由必填": "A reason is required", "缺": "missing", "自判": "self-judged", "自定义": "custom", "自己拿主意": "Decide for yourself", "被 ": "by ", "被下一版命题改写": "rewritten by a later version of the proposition", "裁决": "Verdict", "裁决:采纳 ": "Verdict: adopt ", "要你": "needs you", "观测": "Observation", "计划": "Plan", "计划 ": "Plan ", "计划受阻,等人处置": "plan blocked, waiting for a person", "计划在建,**等你确认**": "plan is being built, **waiting for your confirmation**", "计划已交付 ": "Plan delivered ", "计划已收尾(": "Plan closed (", "计划待确认": "plan awaiting confirmation", "计划文档": "Plan document", "记忆(": "Memory (", "记忆索引": "Memory index", "证据": "Evidence", "证据 ": "Evidence ", "评 ": "E", "评估": "Evaluation", "评估卡": "evaluation card", "评估者": "Evaluator", "评估者 ": "Evaluator ", "评估者会话 ": "Evaluator session ", "评估者在裁决": "an evaluator is deciding", "读不到交付物:": "Cannot read deliverables: ", "读取中…": "Reading…", "读数": "Reading", "读数(尺子 ": "Reading (metric ", "起过 ": "ran ", "跑着": "running", "车道 · ": "Lane · ", "边界:": "Scope: ", "运行时注册": "registered at runtime", "还有 ": "and ", "还没交付": "not delivered yet", "这一步已作废(缘由:": "This step was voided (reason: ", "这一步没有声明产物。": "This step declares no artifacts.", "这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示已确认的事实与正在流转的命题。": "This session has not started: the panels read the session log, so after your first message this will show confirmed facts and the propositions in flight.", "这个会话还没有 ClearAI 的状态。": "This session has no ClearAI state yet.", "这个工作区盘上已经有 ": "This workspace already has ", "进度": "Progress", "采纳": "Adopt", "采纳 ": "Adopt ", "采纳:改写 frontmatter,模型从此加载得到它": "Adopt: rewrites the frontmatter so the model can load it from then on", "采纳了某条世界线": "adopted one worldline", "采纳此世界线": "Adopt this worldline", "问题:": "Question: ", "阶段": "Stage", "阶段 ": "Stage ", "阶段交界": "at a stage boundary", "需要你 ": "needs you ", "面板动作失败:": "Panel action failed: ", "项目章程": "Project charter", "预设自带": "shipped with the preset", "验证": "Verification", "验证中": "verifying", "这次采纳没有合并:": "This adoption was not merged: ", "(决定已登记,产物由一次普通交付落位)": " (the decision is on record; a normal delivery places the artifacts)", "分支或工作副本已不在": "its branch or working copy is gone"}
77
77
 
78
78
  /**
79
79
  * 翻译函数:**由原生 locale 座位绑定**(`ctx.locale.bind`),不是我们自建的一套 i18n。
@@ -122,10 +122,10 @@ window.__ModuleLoader__.load({
122
122
  drafting: t('判据待写'),
123
123
  planning: t('待开计划'),
124
124
  executing: t('推进中'),
125
- waiting: t('等人或等世界线'),
125
+ waiting: t('等待中'),
126
126
  stage_boundary: t('阶段交界'),
127
127
  auditing: t('评估者在裁决'),
128
- stalled: t('停摆等人'),
128
+ stalled: t('等待人工'),
129
129
  suspended: t('目标挂起'),
130
130
  achieved: t('已达成'),
131
131
  abandoned: t('已放弃'),
@@ -147,7 +147,7 @@ window.__ModuleLoader__.load({
147
147
  /** 人在面板上做过的裁决(树详情里要如实回放:谁、以什么理由)。 */
148
148
  const FORK_ACTION = lazyTable(() => ({ adopt_branch: t('采纳了某条世界线'), abandon_fork: t('放弃了这次探索') }))
149
149
  /** 侦察的三种结局(与 fold 的派生同源):跑着 / 正常回灌 / 没正常结束。 */
150
- const SCOUT = lazyTable(() => ({ running: t('跑着'), settled: t('已回灌'), failed: t('没正常结束') }))
150
+ const SCOUT = lazyTable(() => ({ running: t('跑着'), settled: t('已回灌'), failed: t('异常终止') }))
151
151
 
152
152
  const STRONG = { refuted: true, stalled: true, refute: true }
153
153
 
@@ -216,6 +216,15 @@ window.__ModuleLoader__.load({
216
216
 
217
217
  // ── 样式:颜色一律用主题令牌(--dsw-alias-*),不写死色值 ─────────────────
218
218
  const S = {
219
+ /** 断言芯片:一条断言的一行;点开就地展开词条卡。 */
220
+ chipRow: { display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 4 },
221
+ chipWrap: { display: 'inline-flex', flexDirection: 'column', gap: 2, maxWidth: '100%' },
222
+ chip: { display: 'inline-flex', alignItems: 'center', padding: '1px 8px', borderRadius: 999, border: '1px solid rgba(127,127,127,0.35)', fontSize: 11, cursor: 'pointer', lineHeight: '20px' },
223
+ chipCard: { display: 'flex', flexDirection: 'column', gap: 2, padding: '6px 10px', borderRadius: 6, border: '1px solid rgba(127,127,127,0.22)', background: 'var(--dsw-alias-bg-layer-1)', fontSize: 11 },
224
+ chipCardTitle: { fontWeight: 600 },
225
+ chipActions: { display: 'flex', gap: 10, marginTop: 2 },
226
+ chipAction: { color: 'var(--dsh-alias-link-primary, #4a8dff)', cursor: 'pointer', fontSize: 11 },
227
+
219
228
  /** 空态里的标记行:quiet,只陈述"这一格是谁的",不跟正文抢。 */
220
229
  emptyMark: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10, color: 'var(--dsw-alias-label-tertiary)' },
221
230
  emptyName: { fontSize: 13, fontWeight: 600, letterSpacing: '.02em' },
@@ -452,7 +461,7 @@ window.__ModuleLoader__.load({
452
461
  * ② 旧日志没有 `origins` 时走**只读回退**:材料 id → 材料表里的路径,换不出来的**丢掉** ——
453
462
  * 绝不把裸 id 渲染成"能点"的样子(失效模式:整排出处因此点不开)。
454
463
  */
455
- const ORIGIN_LABEL = lazyTable(() => ({ 'audit-card': t('评估卡'), 'evaluator-session': t('看评估者'), 'approval-record': t('审批记录') }))
464
+ const ORIGIN_LABEL = lazyTable(() => ({ 'audit-card': t('评估卡'), 'evaluator-session': t('查看评估者'), 'approval-record': t('审批记录') }))
456
465
  /**
457
466
  * 出处的**可点标签**:产物用**文件名**,不用「产物」三个字 ——
458
467
  * 一条证据常常挂着两三个产物,都叫「产物」就没人知道该点谁。
@@ -498,7 +507,7 @@ window.__ModuleLoader__.load({
498
507
  audits.find((row) => row.stepId === item.stepId) ??
499
508
  (item.branch === null || item.branch === undefined ? undefined : audits.find((row) => String(row.stepId ?? '').endsWith(`:${item.branch}`)))
500
509
  if (audit?.cardPath !== null && audit?.cardPath !== undefined) out.push({ kind: 'audit-card', label: t('评估卡'), path: String(audit.cardPath) })
501
- if (audit?.evaluatorSession !== null && audit?.evaluatorSession !== undefined) out.push({ kind: 'evaluator-session', label: t('看评估者'), session: String(audit.evaluatorSession) })
510
+ if (audit?.evaluatorSession !== null && audit?.evaluatorSession !== undefined) out.push({ kind: 'evaluator-session', label: t('查看评估者'), session: String(audit.evaluatorSession) })
502
511
  }
503
512
  const fallbackPaths = (item.refs ?? []).map((ref) => asPath(ref)).filter((path) => path !== null)
504
513
  for (const ref of item.refs ?? []) {
@@ -567,7 +576,7 @@ window.__ModuleLoader__.load({
567
576
  if (row.status === 'superseded') return t('已被下一版命题替代(版本留着,不参与当前推理)')
568
577
  if (row.status === 'confirmed') return t('已达门槛,已升格为事实')
569
578
  if (row.status === 'retracted') return t('人已撤回(记录保留)')
570
- if (row.supportedLevel === null || row.supportedLevel === undefined) return t('还没有证据:先登记判据,再验证')
579
+ if (row.supportedLevel === null || row.supportedLevel === undefined) return t('暂无证据。先登记判据,后执行验证。')
571
580
  if (levelRank(row.supportedLevel) >= levelRank(threshold)) return `${t('已达门槛(')}${row.supportedLevel}${t('),等目标验收时升格为事实')}`
572
581
  return `${t('支持到 ')}${row.supportedLevel}${t(':还差 ')}${threshold}${t('(要独立评估)才达门槛')}`
573
582
  }
@@ -614,7 +623,7 @@ window.__ModuleLoader__.load({
614
623
  */
615
624
  if (evidence.length > 0) {
616
625
  const first = evidence[0]
617
- out.push({ to: 'alive', on: t('有了第一条证据'), by: `${first.id} · ${dash(first.level)} ${gloss(VERDICT, first.verdict)}`, independent: first.evaluator === 'independent' })
626
+ out.push({ to: 'alive', on: t('已获首条证据'), by: `${first.id} · ${dash(first.level)} ${gloss(VERDICT, first.verdict)}`, independent: first.evaluator === 'independent' })
618
627
  }
619
628
  if (row.status === 'refuted') {
620
629
  const refute = evidence.find((item) => item.verdict === 'refute')
@@ -794,7 +803,7 @@ window.__ModuleLoader__.load({
794
803
  ),
795
804
  ),
796
805
  declared === null
797
- ? h('div', { style: { ...S.faint, fontSize: 11, marginTop: 2 } }, t('本体声明还没随投影下发,这里用的是规范闭环的镜像;会话跑过一拍后会自动对齐声明。'))
806
+ ? h('div', { style: { ...S.faint, fontSize: 11, marginTop: 2 } }, t('本体声明尚未进入投影;当前显示规范闭环的镜像,下一拍自动对齐。'))
798
807
  : null,
799
808
  )
800
809
  }
@@ -823,8 +832,9 @@ window.__ModuleLoader__.load({
823
832
  */
824
833
  (row.untouchedLevels ?? []).length === 0
825
834
  ? null
826
- : h('span', { style: { ...S.faint, flex: '0 0 auto' }, title: t('这些等级一条证据都没有:跳到高等级不是违规,但要说得清为什么更便宜的路不通') }, `${t('未走过 ')}${row.untouchedLevels.join('/')}`),
835
+ : h('span', { style: { ...S.faint, flex: '0 0 auto' }, title: t('这些等级尚无证据:跳级不违规,但需说明原因') }, `${t('未走过 ')}${row.untouchedLevels.join('/')}`),
827
836
  ),
837
+ h(AssertionChips, { assertions: row.assertions, ui: data.assertionUI, promoted: false }),
828
838
  open === true
829
839
  ? h(
830
840
  'div',
@@ -851,7 +861,7 @@ window.__ModuleLoader__.load({
851
861
  },
852
862
  title: t('打开世界树并选中产生这条证据的验证步'),
853
863
  },
854
- t('在世界树里看这一步'),
864
+ t('在世界树中查看此步骤'),
855
865
  ),
856
866
  ),
857
867
  )
@@ -878,7 +888,7 @@ window.__ModuleLoader__.load({
878
888
  Section,
879
889
  { title: `${t('命题 · ')}${rows.length}` },
880
890
  rows.length === 0
881
- ? h('div', { style: S.faint }, t('还没有命题。人与模型都可以提出:每条要有一句话主张与一句「什么结果会推翻它」;通过验证的会升格到上面的事实货架。'))
891
+ ? h('div', { style: S.faint }, t('暂无命题。每条需一句主张与一句推翻条件;通过验证后升格为事实。'))
882
892
  : h(
883
893
  'div',
884
894
  null,
@@ -901,14 +911,14 @@ window.__ModuleLoader__.load({
901
911
  const facts = data.facts ?? []
902
912
  return h(
903
913
  Section,
904
- { title: `${t('已确认事实 · ')}${facts.length}`, mark: true },
914
+ { title: `${t('本体货架 · ')}${facts.length}`, mark: true },
905
915
  facts.length === 0
906
916
  ? h(
907
917
  'div',
908
918
  { style: S.faint },
909
919
  data.goal === null || data.goal === undefined
910
- ? t('还没有目标。立约并验证之后,达门槛且无推翻的命题会在目标验收时升格为事实。')
911
- : t('达门槛且无推翻的命题,会在**目标验收**时由系统升格为事实(写在 clear/knowledge/facts/,模型读的 INDEX.md 同步)。'),
920
+ ? t('暂无目标。验证达门槛且无推翻的命题在验收时升格为事实。')
921
+ : t('达门槛且无推翻的命题在目标验收时升格为事实(写入 clear/knowledge/facts/)。'),
912
922
  )
913
923
  : h(
914
924
  'div',
@@ -934,7 +944,7 @@ window.__ModuleLoader__.load({
934
944
  row.review?.decision === 'retracted'
935
945
  ? h('span', { style: { ...S.tag, marginLeft: 6 } }, t('人已撤回(记录保留)'))
936
946
  : row.refuted === true
937
- ? h('span', { style: { ...S.tag, marginLeft: 6 } }, t('被推翻,等你决定'))
947
+ ? h('span', { style: { ...S.tag, marginLeft: 6 } }, t('被推翻 · 待裁决'))
938
948
  : null,
939
949
  ),
940
950
  h(
@@ -969,8 +979,16 @@ window.__ModuleLoader__.load({
969
979
  },
970
980
  title: t('打开世界树并选中产出这条事实的验证步'),
971
981
  },
972
- t('在世界树里看这一步'),
982
+ t('在世界树中查看此步骤'),
973
983
  ),
984
+ /**
985
+ * **冲突内联标记**:冲突行只给指针,受害的条目自己也要亮出来——
986
+ * 读者扫到这一行时不必回头去对那一行指针。
987
+ */
988
+ data.conflictOf !== undefined && data.conflictOf.has(row.id)
989
+ ? h('div', { style: S.row }, h('span', { style: { ...S.tag, borderColor: 'rgba(220,38,38,0.7)', color: '#dc2626' } }, `${t('冲突')} · ${String(data.conflictOf.get(row.id).predicate)}`), h('span', { style: S.faint }, ` ${data.conflictOf.get(row.id).sides.map((side) => `${side.fact}(${side.value})`).join(' ')}`))
990
+ : null,
991
+ h(AssertionChips, { assertions: row.assertions, ui: data.assertionUI, promoted: true }),
974
992
  ),
975
993
  ),
976
994
  ),
@@ -989,9 +1007,16 @@ window.__ModuleLoader__.load({
989
1007
  // 取数与 Panel/Deliverables 同一姿势:宿主半的会话投影单元 `clearai` 由插座作为标准 prop 交下来。
990
1008
  const projected = typeof props.useProjection === 'function' ? props.useProjection('clearai') : undefined
991
1009
  const [manual, setManual] = React.useState(null)
1010
+ /** 本体格的界面状态:图层次/全景/图带开关/过滤/芯片展开/词汇区开关。全是界面状态,不进账本。 */
1011
+ const [layer, setLayer] = React.useState('ontology')
1012
+ const [expanded, setExpanded] = React.useState(false)
1013
+ const [bandOpen, setBandOpen] = React.useState(true)
1014
+ const [filter, setFilter] = React.useState(null)
1015
+ const [chipKey, setChipKey] = React.useState(null)
1016
+ const [vocabOpen, setVocabOpen] = React.useState(null)
992
1017
  const incoming = useFocus(factsFocus)
993
1018
  if (projected === undefined || projected === null) {
994
- return h('div', { style: S.wrap }, h('div', { style: S.bar }, h('span', { style: S.title }, t('事实'))), h(Empty, null, t('这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示已确认的事实与正在流转的命题。')))
1019
+ return h('div', { style: S.wrap }, h('div', { style: S.bar }, h('span', { style: S.title }, t('本体'))), h(Empty, null, t('暂无数据。发送第一条消息后,此处显示已确立条目与在验命题。')))
995
1020
  }
996
1021
  const data = { ...projected, openPreview: props.openPreview, openRail: props.openRail, openSpectator: props.openSpectator }
997
1022
  const facts = data.facts ?? []
@@ -999,22 +1024,74 @@ window.__ModuleLoader__.load({
999
1024
  /** 外面点进来的聚焦优先;手动点行仍然有效(聚焦为 null 时用它)。 */
1000
1025
  const focused = incoming === null || incoming === undefined ? null : propositionForStep(data, incoming.step)
1001
1026
  const open = focused ?? manual
1027
+ /**
1028
+ * **本体层**:没有词条时下面这一切都不存在(零成本契约)——
1029
+ * 图带、冲突行、过滤、芯片、维护区,每一个都以「有东西可说」为前提。
1030
+ */
1031
+ const lexicon = data.lexicon ?? null
1032
+ const hasVocabulary = lexicon !== null && ((lexicon.terms ?? []).length > 0 || (lexicon.predicates ?? []).length > 0)
1033
+ const conflicts = hasVocabulary === true ? (lexicon.conflicts ?? []) : []
1034
+ /** factId → 它卷入的那对冲突(内联标记用;同一事实卷多对时取第一对)。 */
1035
+ const conflictOf = new Map()
1036
+ for (const conflict of conflicts) for (const side of conflict.sides) if (typeof side.fact === 'string' && !conflictOf.has(side.fact)) conflictOf.set(side.fact, conflict)
1037
+ /** 过滤词条:图带点概念节点或芯片动作都会给词条 id;文本兜底匹配。 */
1038
+ const filterTerm = filter === null ? null : ((lexicon?.terms ?? []).find((item) => item.id === filter) ?? (lexicon?.predicates ?? []).find((item) => item.id === filter) ?? { id: filter, label: filter, aliases: [] })
1039
+ const matchedFacts = filterTerm === null ? facts : facts.filter((row) => termMatches(filterTerm, row))
1040
+ const matchedPropositions = filterTerm === null ? propositions : propositions.filter((row) => termMatches(filterTerm, row))
1041
+ const filteredData = filterTerm === null ? data : { ...data, facts: matchedFacts, goal: { ...data.goal, hypotheses: matchedPropositions } }
1042
+ /** 断言芯片的公共道具:词条卡从词汇里查,动作回连过滤与图带。 */
1043
+ const assertionUI = hasVocabulary === true ? { lexicon, openKey: chipKey, onToggle: (key) => setChipKey(chipKey === key ? null : key), onFilter: (id) => { setFilter(id); setChipKey(null) }, onGraph: () => { setBandOpen(true); setChipKey(null) } } : null
1044
+ filteredData.assertionUI = assertionUI
1045
+ filteredData.conflictOf = conflictOf
1046
+ /** 语言先于句子:0 条目 0 命题而有词条时,维护区自动展开。 */
1047
+ const vocabAutoOpen = vocabOpen === null ? (facts.length === 0 && propositions.length > 0 === false && hasVocabulary === true) : vocabOpen
1048
+ const vocabActuallyOpen = vocabOpen === null ? (facts.length === 0 && propositions.length === 0 && hasVocabulary === true) : vocabOpen
1049
+ const bar = h(
1050
+ 'div',
1051
+ { style: S.bar },
1052
+ h('span', { style: S.title }, t('本体')),
1053
+ )
1054
+ if (hasVocabulary === false) {
1055
+ /** 零成本:没有词条时,这一格与从前逐像素相同(两个货架 + 页眉)。 */
1056
+ return h('div', { style: S.wrap }, bar, h(FactShelf, { data }), h(PropositionShelf, {
1057
+ data,
1058
+ open,
1059
+ onToggle: (id) => {
1060
+ factsFocus.set(null)
1061
+ setManual(open === id ? null : id)
1062
+ },
1063
+ }))
1064
+ }
1002
1065
  return h(
1003
1066
  'div',
1004
1067
  { style: S.wrap },
1005
- h(
1006
- 'div',
1007
- { style: S.bar },
1008
- h('span', { style: S.title }, t('事实')),
1009
- /**
1010
- * 页眉只说这一格是干什么的:计数在下面两段的标题里(同屏四个数字两两重复 = 噪声),
1011
- * 「模型读的是同一张表」是实现保证、不是用户信息 ✗。
1012
- */
1013
- h('span', { style: S.faint }, t('能用的在上面,正在验的在下面')),
1014
- ),
1015
- h(FactShelf, { data }),
1068
+ bar,
1069
+ /** 冲突行:仅当有冲突。一行指针 + 内联标记,不做大区块(例外才打扰)。 */
1070
+ conflicts.length > 0
1071
+ ? h(
1072
+ 'div',
1073
+ { style: S.section },
1074
+ h('div', { style: S.head }, `${t('冲突')} ${conflicts.length}${t(' 对')}`),
1075
+ ...conflicts.map((conflict, index) =>
1076
+ h('div', { key: `cf-${index}`, style: S.row }, `${String(conflict.predicate)} · ${String(conflict.subject)}:`, ...conflict.sides.map((side, sideIndex) => h('span', { key: `cf-${index}-${sideIndex}`, style: S.faint }, ` ${String(side.fact ?? '?')}(${String(side.value)})`)), ` —— ${t('只暴露,不裁决;撤回或维持由人决定')}`),
1077
+ ),
1078
+ )
1079
+ : null,
1080
+ bandOpen === false
1081
+ ? h('div', { style: S.section }, h('span', { style: S.chipAction, onClick: () => setBandOpen(true) }, t('展开图带')))
1082
+ : h(GraphBand, { lexicon, layer, onLayer: setLayer, expanded, onToggleExpand: () => setExpanded(expanded !== true), onFilter: (id) => setFilter(filter === id ? null : id) }),
1083
+ /** 过滤状态行:仅当过滤激活;N/M 说真话,✕ 一键清除。 */
1084
+ filterTerm === null
1085
+ ? null
1086
+ : h(
1087
+ 'div',
1088
+ { style: S.inline },
1089
+ h('span', { style: S.tag }, `${t('按')}「${String(filterTerm.label ?? filterTerm.id)}」${t('过滤')}:${matchedFacts.length + matchedPropositions.length}/${facts.length + propositions.length}${t(' 条')}`),
1090
+ h('span', { style: S.chipAction, onClick: () => setFilter(null) }, t('清除')),
1091
+ ),
1092
+ h(FactShelf, { data: filteredData }),
1016
1093
  h(PropositionShelf, {
1017
- data,
1094
+ data: filteredData,
1018
1095
  open,
1019
1096
  onToggle: (id) => {
1020
1097
  // 手动点行:先清掉外面的聚焦(否则它一直压着手动选择,点了没反应 ✗)
@@ -1022,6 +1099,7 @@ window.__ModuleLoader__.load({
1022
1099
  setManual(open === id ? null : id)
1023
1100
  },
1024
1101
  }),
1102
+ h(VocabBlock, { lexicon, open: vocabActuallyOpen, onToggle: () => setVocabOpen(vocabActuallyOpen !== true), openPreview: props.openPreview, sessionId: data.sessionId }),
1025
1103
  )
1026
1104
  }
1027
1105
 
@@ -1175,7 +1253,7 @@ window.__ModuleLoader__.load({
1175
1253
  * 「份」= 去重后的文件。混着写会让人以为盘上有四份。
1176
1254
  */
1177
1255
  h('span', { style: S.faint }, `${t('阶段 ')}${(stages ?? []).length}${t(' · 交付 ')}${delivered}/${declared}${t(' 处声明')}${onDisk.length === 0 ? '' : ` · 盘上 ${onDisk.length} 份`}`),
1178
- clickable === 0 ? null : h('span', { style: { ...S.faint, marginLeft: 'auto' } }, t('点一条 → 右栏预览')),
1256
+ clickable === 0 ? null : h('span', { style: { ...S.faint, marginLeft: 'auto' } }, t('点击在右栏预览')),
1179
1257
  ),
1180
1258
  error !== null ? h('div', { style: S.faint }, `${t('读不到交付物:')}${error}`) : null,
1181
1259
  coreOutputs.length === 0
@@ -1226,7 +1304,7 @@ window.__ModuleLoader__.load({
1226
1304
  Empty,
1227
1305
  null,
1228
1306
  onDisk.length === 0
1229
- ? t('还没有计划,所以还没有产物。立目标、建计划,交付过的每一步都会在这里按阶段排开。')
1307
+ ? t('暂无计划。建立计划后,已交付步骤按阶段列于此处。')
1230
1308
  : `${t('这个工作区盘上已经有 ')}${onDisk.length}${t(' 份产物,但没有任何计划声明过它们。点一条可以直接看(它们不计入交付)。')}`,
1231
1309
  )
1232
1310
  : stages.map((stage) =>
@@ -1272,7 +1350,7 @@ window.__ModuleLoader__.load({
1272
1350
  * 它带来的信息仍然齐全:路径、分类、「盘上没有」。
1273
1351
  */
1274
1352
  artifact.exists
1275
- ? h('span', { className: 'clearai-link', onClick: () => open(artifact.path), title: t('在右栏预览') }, artifact.path)
1353
+ ? h('span', { className: 'clearai-link', onClick: () => open(artifact.path), title: t('右栏预览') }, artifact.path)
1276
1354
  : h(
1277
1355
  'span',
1278
1356
  { style: S.mono, title: artifact.directory === true ? t('声明的是目录;准入要求具体文件——目录不算物证') : t('盘上没有这个文件') },
@@ -1630,7 +1708,7 @@ window.__ModuleLoader__.load({
1630
1708
  const chosen = wanted === null ? null : plans.find((item) => item.id === wanted) ?? null
1631
1709
  const plan = chosen ?? (data === null || data === undefined ? null : data.plan)
1632
1710
  if (plan === null || plan === undefined) {
1633
- return h('div', { style: S.wrap }, h('div', { style: S.bar }, h('span', { style: S.title }, t('世界树'))), h(Empty, null, t('还没有计划。计划立起来之后,这里画的是它的拓扑:脊柱上的步、叉开的车道、收在哪。')))
1711
+ return h('div', { style: S.wrap }, h('div', { style: S.bar }, h('span', { style: S.title }, t('世界树'))), h(Empty, null, t('暂无计划。建立后此处显示计划拓扑:脊柱步、车道与收敛点。')))
1634
1712
  }
1635
1713
  const rows = treeRows(plan, data.forks)
1636
1714
  /** 页眉那一句:计划的首个非空行,过长再截(整篇在 tooltip 与「计划文档」里)。 */
@@ -1791,7 +1869,7 @@ window.__ModuleLoader__.load({
1791
1869
  props.openPreview === undefined
1792
1870
  ? null
1793
1871
  : h(Link, { onClick: () => props.openPreview(`clear/goals/plans/${plan.id}.md`), title: t('打开计划文档(原生预览)') }, t('计划文档')),
1794
- h('span', { style: { ...S.faint, marginLeft: 'auto' } }, t('点一行看细节')),
1872
+ h('span', { style: { ...S.faint, marginLeft: 'auto' } }, t('点击查看详情')),
1795
1873
  ),
1796
1874
  /**
1797
1875
  * 这一格是**计划的一切**:目标是脊柱的起点、拓扑是它的形状、
@@ -1823,7 +1901,7 @@ window.__ModuleLoader__.load({
1823
1901
  treeFocus.set(null)
1824
1902
  setManual(isSel ? null : index)
1825
1903
  },
1826
- title: t('点开看这一步的细节'),
1904
+ title: t('查看步骤详情'),
1827
1905
  },
1828
1906
  h(
1829
1907
  'span',
@@ -1844,7 +1922,7 @@ window.__ModuleLoader__.load({
1844
1922
  },
1845
1923
  rowLabel(row),
1846
1924
  ),
1847
- row.kind === 'branch' && row.fork.recommended === row.branch.id && row.fork.phase !== 'settled' ? h('span', { style: { color: TREE_COLOR.recommend, flex: '0 0 auto' }, title: t('算术推荐这条') }, '★') : null,
1925
+ row.kind === 'branch' && row.fork.recommended === row.branch.id && row.fork.phase !== 'settled' ? h('span', { style: { color: TREE_COLOR.recommend, flex: '0 0 auto' }, title: t('按判据推荐') }, '★') : null,
1848
1926
  row.kind === 'branch' && row.branch.reading !== null && row.branch.reading !== undefined
1849
1927
  ? h('span', { style: { ...S.mono, color: marks.color, flex: '0 0 auto' }, title: `${t('读数(尺子 ')}${row.fork.decideBy?.metric ?? '—'})` }, String(row.branch.reading))
1850
1928
  : null,
@@ -2006,7 +2084,7 @@ window.__ModuleLoader__.load({
2006
2084
  onClick: () => props.openFacts(step.id),
2007
2085
  title: t('打开「事实」那一格并展开这条命题'),
2008
2086
  },
2009
- t('看这一步的证据'),
2087
+ t('查看此步骤的证据'),
2010
2088
  ),
2011
2089
  ),
2012
2090
  ),
@@ -2046,7 +2124,7 @@ window.__ModuleLoader__.load({
2046
2124
  ? h(
2047
2125
  'div',
2048
2126
  { style: { marginTop: 6, display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' } },
2049
- h(Chip, { disabled: busy !== null, onClick: () => send('adopt_branch', { fork: fork.id, branch: branch === null ? fork.recommended ?? null : branch.id }), title: t('让内核跑 ConvergeFork 落实它(合并是内核的活)') }, busy === 'adopt_branch' ? t('提交中…') : t('采纳此世界线')),
2127
+ h(Chip, { disabled: busy !== null, onClick: () => send('adopt_branch', { fork: fork.id, branch: branch === null ? fork.recommended ?? null : branch.id }), title: t('由内核执行 ConvergeFork 完成合并') }, busy === 'adopt_branch' ? t('提交中…') : t('采纳此世界线')),
2050
2128
  h('input', {
2051
2129
  value: note,
2052
2130
  placeholder: t('放弃缘由(必填)'),
@@ -2208,8 +2286,8 @@ window.__ModuleLoader__.load({
2208
2286
  // 两种情况要分开说:会话还没开始(没有第一轮对话 = 还没有任何事实)vs 真的没有技能或记忆。
2209
2287
  const note =
2210
2288
  data === undefined
2211
- ? t('这个会话还没开始:面板的数据来自会话日志,发第一句话之后,这里会显示工作区的技能目录与记忆。')
2212
- : t('这个工作区里还没有技能或记忆:用一次 `SaveSkill` 或 `WriteMemory`,或把技能放进 `clear/skills/`。')
2289
+ ? t('暂无数据。发送第一条消息后,此处显示技能目录与记忆。')
2290
+ : t('暂无技能或记忆。使用 `SaveSkill` / `WriteMemory`,或将技能放入 `clear/skills/`。')
2213
2291
  return h('div', { style: S.wrap }, h('div', { style: S.bar }, h('span', { style: S.title }, t('技能 · 记忆'))), h(Empty, null, note))
2214
2292
  }
2215
2293
  const overview = Array.isArray(brain.skills) ? brain.skills : []
@@ -2269,7 +2347,7 @@ window.__ModuleLoader__.load({
2269
2347
  */
2270
2348
  candidate ? h(Chip, { disabled: busy, onClick: () => promote(skill.name), title: t('采纳:改写 frontmatter,模型从此加载得到它') }, t('采纳')) : null,
2271
2349
  // 混合路径:同一件事也可以摆到原生提问卡上答(卡里带它的描述与后果)。
2272
- candidate ? h('span', { className: busy ? undefined : 'clearai-link', style: S.faint, onClick: busy ? undefined : () => promote(skill.name, true), title: t('用原生提问卡决定') }, t('用提问卡决定')) : null,
2350
+ candidate ? h('span', { className: busy ? undefined : 'clearai-link', style: S.faint, onClick: busy ? undefined : () => promote(skill.name, true), title: t('通过提问卡决定') }, t('通过提问卡决定')) : null,
2273
2351
  ),
2274
2352
  /**
2275
2353
  * 描述只留**认得出这条技能的那一句**(真数据里每条是一整段「适用/不适用」✗,
@@ -2298,7 +2376,7 @@ window.__ModuleLoader__.load({
2298
2376
  * 「与模型看到的是同一张表」是实现保证、不是用户信息,与事实那一格同一条规矩 → 去掉。
2299
2377
  * 只留**状态**:目录到没到、这份是不是"本会话还没有第一轮对话"的工作区现状。
2300
2378
  */
2301
- entries === null || fromLive ? h('span', { style: S.faint }, entries === null ? t('目录还没到(内核下一次 pre-step 会发)') : t('工作区现状(本会话还没有第一轮对话,这份还没进投影)')) : null,
2379
+ entries === null || fromLive ? h('span', { style: S.faint }, entries === null ? t('目录尚未到达(内核下一次 pre-step 下发)') : t('工作区现状(首轮对话后进入投影)')) : null,
2302
2380
  ),
2303
2381
  error !== null ? h('div', { style: S.faint }, `${t('面板动作失败:')}${error}`) : null,
2304
2382
  /**
@@ -2331,14 +2409,38 @@ window.__ModuleLoader__.load({
2331
2409
  h('span', { style: S.faint }, `${t('最后改动 ')}${stampOf(constitution.modifiedAt)} · ${constitution.bytes}${t(' 字节')}`),
2332
2410
  ),
2333
2411
  ),
2334
- ...groups.map((group) =>
2335
- h(
2412
+ ...groups.map((group) => {
2413
+ /**
2414
+ * **每段封顶**:合并目录在真机器上可以有一百多条(全局技能 + 模板 + 记忆),
2415
+ * 全列出来就是信息爆炸——这一格的用途是"认出这条技能",不是"读完整个目录"。
2416
+ *
2417
+ * 保留顺序**按用途排**,不是按字母:
2418
+ * ① 候选(等人拍板,不列出来那件事就没有出口);
2419
+ * ② 本会话真的用过(正在被引用的那些);
2420
+ * ③ 其余按原序补到上限。
2421
+ * 被截掉的那部分不消失:`/` 原生触发菜单仍然是完整目录,这里只留一句话说清还有多少。
2422
+ */
2423
+ const shownItems = (() => {
2424
+ const cap = 8
2425
+ if (group.items.length <= cap) return group.items
2426
+ const candidates = group.items.filter((skill) => overviewOf.get(skill.name)?.status === 'candidate')
2427
+ const used = group.items.filter((skill) => skill.status === 'candidate' ? false : usage.has(skill.name))
2428
+ const picked = []
2429
+ for (const skill of [...candidates, ...used, ...group.items]) {
2430
+ if (picked.length >= cap) break
2431
+ if (!picked.includes(skill)) picked.push(skill)
2432
+ }
2433
+ return picked
2434
+ })()
2435
+ const hidden = group.items.length - shownItems.length
2436
+ return h(
2336
2437
  'div',
2337
2438
  { key: group.label, style: S.section },
2338
2439
  h('div', { style: S.head }, `${group.label}(${group.items.length})`),
2339
- group.items.map((skill) => row(skill)),
2340
- ),
2341
- ),
2440
+ shownItems.map((skill) => row(skill)),
2441
+ hidden <= 0 ? null : h('div', { style: S.faint }, `${t('还有 ')}${hidden}${t(' 条未列出 · 用 / 触发菜单选')}`),
2442
+ )
2443
+ }),
2342
2444
  orphanUsage.length === 0
2343
2445
  ? null
2344
2446
  : h(
@@ -2371,7 +2473,7 @@ window.__ModuleLoader__.load({
2371
2473
  ),
2372
2474
  ),
2373
2475
  ),
2374
- memory.count === 0 ? h('div', { style: S.faint }, t('还没有记忆。')) : null,
2476
+ memory.count === 0 ? h('div', { style: S.faint }, t('暂无记忆。')) : null,
2375
2477
  ),
2376
2478
  )
2377
2479
  }
@@ -2445,7 +2547,7 @@ window.__ModuleLoader__.load({
2445
2547
  item.needs !== 'click'
2446
2548
  ? null
2447
2549
  : item.kind === FORK_RENDERED
2448
- ? t('用提问卡决定')
2550
+ ? t('通过提问卡决定')
2449
2551
  : item.kind === 'fact_refutation'
2450
2552
  ? t('撤回事实')
2451
2553
  : item.kind === 'provisional_review'
@@ -2476,10 +2578,10 @@ window.__ModuleLoader__.load({
2476
2578
  type: 'button',
2477
2579
  className: 'clearai-btn',
2478
2580
  disabled: busy !== null,
2479
- title: t('把这道裁决摆到原生提问卡上(带你读到的判据与各分支读数)'),
2581
+ title: t('通过提问卡做出裁决(含判据与各分支读数)'),
2480
2582
  onClick: () => send({ kind: 'fork_adopt', human_action: 'ask', plan: fork.plan ?? null, step: fork.stepId }, { gate: 'fork_adopt', fork: fork.id }),
2481
2583
  },
2482
- t('用提问卡决定'),
2584
+ t('通过提问卡决定'),
2483
2585
  ),
2484
2586
  ...fork.branches.map((branch) =>
2485
2587
  h(
@@ -2506,7 +2608,7 @@ window.__ModuleLoader__.load({
2506
2608
  className: 'clearai-btn',
2507
2609
  disabled: busy !== null,
2508
2610
  onClick: () => setAbandon(fork.id),
2509
- title: t('放弃要留痕:点一下写缘由,写了才能提交'),
2611
+ title: t('放弃需填写缘由后提交'),
2510
2612
  },
2511
2613
  t('放弃这条分叉'),
2512
2614
  ),
@@ -2516,7 +2618,7 @@ window.__ModuleLoader__.load({
2516
2618
  { style: { display: 'inline-flex', gap: 6, alignItems: 'center' } },
2517
2619
  h('input', {
2518
2620
  value: abandonNote,
2519
- placeholder: t('为什么放弃?(留痕可考)'),
2621
+ placeholder: t('放弃缘由(必填)'),
2520
2622
  onChange: (event) => setAbandonNote(event.target.value),
2521
2623
  style: { fontSize: 11.5, padding: '2px 6px', borderRadius: 6, border: '.5px solid var(--dsw-alias-border-l3)', background: 'transparent', color: 'inherit', minWidth: 140 },
2522
2624
  }),
@@ -2557,12 +2659,12 @@ window.__ModuleLoader__.load({
2557
2659
  disabled: busy !== null,
2558
2660
  /** 撤回先开缘由框(两步):「为什么撤回」是最值得留下的那句话。 */
2559
2661
  onClick: () => (item.kind === 'fact_refutation' ? setRetract(item.value) : send(act, extra)),
2560
- title: item.kind === 'fact_refutation' ? t('撤回要留痕:点一下写缘由,写了才能提交') : undefined,
2662
+ title: item.kind === 'fact_refutation' ? t('撤回需填写缘由后提交') : undefined,
2561
2663
  },
2562
2664
  label(item),
2563
2665
  )
2564
2666
  : item.needs === 'word'
2565
- ? h('span', { style: { ...S.faint, opacity: 0.9 } }, `${t('说一句话就行 —— ')}${item.ask ?? '说一句你的决定'}`)
2667
+ ? h('span', { style: { ...S.faint, opacity: 0.9 } }, `${t('')}${item.ask ?? '说一句你的决定'}`)
2566
2668
  : null,
2567
2669
  /**
2568
2670
  * 事实复核那道门有**两个**结局,而且两个都必须能一键落地:
@@ -2582,7 +2684,7 @@ window.__ModuleLoader__.load({
2582
2684
  { style: { display: 'inline-flex', gap: 6, alignItems: 'center' } },
2583
2685
  h('input', {
2584
2686
  value: retractNote,
2585
- placeholder: t('为什么撤回?(留痕可考)'),
2687
+ placeholder: t('撤回缘由(必填)'),
2586
2688
  onChange: (event) => setRetractNote(event.target.value),
2587
2689
  style: { fontSize: 11.5, padding: '2px 6px', borderRadius: 6, border: '.5px solid var(--dsw-alias-border-l3)', background: 'transparent', color: 'inherit', minWidth: 140 },
2588
2690
  }),
@@ -2601,7 +2703,7 @@ window.__ModuleLoader__.load({
2601
2703
  : null,
2602
2704
  )
2603
2705
  }),
2604
- error === null ? null : h('div', { style: S.faint }, `${t('没送出去:')}${error}`),
2706
+ error === null ? null : h('div', { style: S.faint }, `${t('发送失败:')}${error}`),
2605
2707
  )
2606
2708
  }
2607
2709
 
@@ -2728,8 +2830,8 @@ window.__ModuleLoader__.load({
2728
2830
  const HOLD_WHY = lazyTable(() => ({
2729
2831
  audit: t('等独立裁决'),
2730
2832
  plan_confirm: t('计划待确认'),
2731
- gate: t('有人在等你'),
2732
- unknown: t('策略暂停(理由没记下,已在日志里告警)'),
2833
+ gate: t('等待人工处理'),
2834
+ unknown: t('策略暂停(原因未记录,已告警)'),
2733
2835
  }))
2734
2836
 
2735
2837
  /**
@@ -2757,7 +2859,7 @@ window.__ModuleLoader__.load({
2757
2859
  const vanished = hostGoal === null || hostGoal === undefined
2758
2860
  /** 门要**一句话**时(dock 只会说"目标已暂停"),这句话说得更准:等你说一声 ✓ */
2759
2861
  const wordGate = Array.isArray(data?.inbox) && data.inbox.some((item) => item.needs === 'word')
2760
- const holdText = wordGate ? t('等你说一句话') : (HOLD_WHY[cont.why] ?? cont.why ?? t('策略暂停'))
2862
+ const holdText = wordGate ? t('等待输入') : (HOLD_WHY[cont.why] ?? cont.why ?? t('策略暂停'))
2761
2863
  const text =
2762
2864
  cont.state === 'withdrawn' || ((cont.state === 'armed' || cont.state === 'paused') && vanished)
2763
2865
  ? t('续跑已撤回')
@@ -2770,7 +2872,7 @@ window.__ModuleLoader__.load({
2770
2872
  {
2771
2873
  className: 'clearai-toolctl',
2772
2874
  style: { opacity: 0.8, fontSize: 11.5, cursor: 'default' },
2773
- title: t('这是系统对自己说的话(我们自己按的暂停 / 人清掉的窗口),不是运行档'),
2875
+ title: t('系统内部消息(非运行状态)'),
2774
2876
  },
2775
2877
  text,
2776
2878
  )
@@ -2794,6 +2896,326 @@ window.__ModuleLoader__.load({
2794
2896
  * 当前会话的 `projectionValues.agentPreset` 走。
2795
2897
  */
2796
2898
  /** 包一层**只做一次**:现造会让 React 每次渲染都当成新组件,把面板整个重挂。 */
2899
+
2900
+ /**
2901
+ * **过滤的判据**(纯函数,导出给测试):一条事实/命题与一个词条是否相关。
2902
+ *
2903
+ * 匹配范围刻意放宽到「文本包含词条名/别名」:只按断言匹配更「纯」,但用户会觉得
2904
+ * 「明明有条条目说到炉次,过滤出来没有」。断言命中优先,文本命中兜底——两种都算,
2905
+ * 数字行(N/M)会把没匹配的说清楚,不会静默消失。
2906
+ */
2907
+ const termMatches = (term, row) => {
2908
+ const id = String(term?.id ?? '')
2909
+ if (id === '') return false
2910
+ const labels = [term.label, ...(Array.isArray(term.aliases) ? term.aliases : [])].filter((item) => typeof item === 'string' && item !== '')
2911
+ const hitsText = [String(row?.text ?? ''), String(row?.claim ?? '')].some((text) => text.includes(id) || labels.some((label) => text.includes(label)))
2912
+ const hitsAssertion = (Array.isArray(row?.assertions) ? row.assertions : []).some((assertion) => {
2913
+ const subject = assertion?.subject ?? {}
2914
+ const object = assertion?.object ?? {}
2915
+ if (String(subject.type ?? '') === id || String(subject.id ?? '') === id || String(assertion?.predicate ?? '') === id) return true
2916
+ if (String(object.kind) === 'instance' && (String(object.type ?? '') === id || String(object.value ?? '') === id)) return true
2917
+ return false
2918
+ })
2919
+ return hitsAssertion || hitsText
2920
+ }
2921
+
2922
+ /**
2923
+ * **断言芯片行**:一条已确立条目(或命题)的断言,点开就地展开词条卡。
2924
+ *
2925
+ * 为什么是「就地展开」而不是跳走:芯片的用途就是**读这条结论时**顺手看清
2926
+ * 「这个谓词什么意思、是不是单值、依据是什么」——跳一步,读者的上下文就断了。
2927
+ * 词条卡的两个人物(筛选此概念 / 在图里看)由外层经 `ui` 递进来。
2928
+ */
2929
+ const AssertionChips = ({ assertions, ui, promoted }) => {
2930
+ const rows = Array.isArray(assertions) ? assertions : []
2931
+ if (ui === null || ui === undefined || rows.length === 0) return null
2932
+ return h(
2933
+ 'div',
2934
+ { style: S.chipRow },
2935
+ ...rows.map((assertion, index) => {
2936
+ const key = `${promoted === false ? 'p' : 'f'}-${index}`
2937
+ const open = ui.openKey === key
2938
+ const predicate = (ui.lexicon?.predicates ?? []).find((item) => item.id === assertion?.predicate) ?? null
2939
+ const label = String(assertion?.chip ?? `${String(assertion?.subject?.id ?? '')} · ${String(assertion?.predicate ?? '')}`)
2940
+ const card =
2941
+ open === false
2942
+ ? null
2943
+ : h(
2944
+ 'div',
2945
+ { style: S.chipCard },
2946
+ predicate === null
2947
+ ? h('div', { style: S.faint }, t('此谓词已不在词汇中(可能已废止);存量断言仍可读。'))
2948
+ : h('div', null,
2949
+ h('div', { style: S.chipCardTitle }, `${predicate.label ?? predicate.id} · ${predicate.id}`),
2950
+ h('div', { style: S.kv }, h('span', { style: S.faint }, `${t('释义')}:`), ` ${String(predicate.gloss ?? '—')}`),
2951
+ h('div', { style: S.kv }, h('span', { style: S.faint }, `${t('主词域')}:`), ` ${String(predicate.domain ?? '—')}`),
2952
+ h('div', { style: S.kv }, h('span', { style: S.faint }, `${t('值域')}:`), ` ${predicate.range?.term ?? (predicate.range?.form ?? '—') + (predicate.range?.unit ?? '')}`),
2953
+ h('div', { style: S.kv }, h('span', { style: S.faint }, `${t('单值')}:`), ` ${predicate.functional === true ? '✓' : '—'}`),
2954
+ h('div', { style: S.kv }, h('span', { style: S.faint }, `${t('依据')}:`), ` ${String(predicate.basis ?? '—')}`),
2955
+ ),
2956
+ h(
2957
+ 'div',
2958
+ { style: S.chipActions },
2959
+ h('span', { style: S.chipAction, onClick: () => ui.onFilter(assertion?.predicate ?? null) }, t('按此谓词过滤')),
2960
+ h('span', { style: S.chipAction, onClick: () => ui.onGraph() }, t('在图里看')),
2961
+ ),
2962
+ )
2963
+ return h(
2964
+ 'div',
2965
+ { key, style: S.chipWrap },
2966
+ h(
2967
+ 'span',
2968
+ {
2969
+ style: open === true ? { ...S.chip, borderColor: 'rgba(74,163,255,0.9)' } : S.chip,
2970
+ onClick: () => ui.onToggle(key),
2971
+ title: promoted === false ? t('未升格:断言仍在命题上') : t('查看词条'),
2972
+ },
2973
+ `${label}${promoted === false ? t(' · 未升格') : ''}`,
2974
+ ),
2975
+ card,
2976
+ )
2977
+ }),
2978
+ )
2979
+ }
2980
+
2981
+ /**
2982
+ * **图带**:本体格的门面。本体图(语言长什么样)与实体图(已验证出什么)一键切换;
2983
+ * 点概念节点 = 按概念过滤下方货架——**图上的节点就是索引**,取代一行文字芯片。
2984
+ * 只读:缩放(滚轮)、平移(拖拽)、全景(⤢,解除节点截断)都是界面状态,不进账本。
2985
+ */
2986
+ const GraphBand = ({ lexicon, layer, onLayer, expanded, onToggleExpand, onFilter }) => {
2987
+ const [view, setView] = React.useState({ zoom: 1, pan: { x: 0, y: 0 } })
2988
+ const [picked, setPicked] = React.useState(null)
2989
+ const graph = lexicon?.graph ?? { nodes: [], edges: [], bounds: { width: 0, height: 0 } }
2990
+ const conflicts = Array.isArray(lexicon?.conflicts) ? lexicon.conflicts : []
2991
+ const conflicted = new Set(conflicts.flatMap((item) => item.sides.map((side) => side.fact)).filter((id) => typeof id === 'string'))
2992
+ const kinds = layer === 'ontology' ? ['concept', 'value_type'] : ['instance', 'literal']
2993
+ const edgeKinds = layer === 'ontology' ? ['is_a', 'predicate'] : ['assertion']
2994
+ /** 截断是**界面决定**,不进投影;被截掉多少如实写出来,不假装这就是全部。 */
2995
+ const MAX_NODES = expanded === true ? 100000 : 40
2996
+ const allNodes = graph.nodes.filter((node) => kinds.includes(node.kind))
2997
+ const shownNodes = allNodes.slice(0, MAX_NODES)
2998
+ const shownIds = new Set(shownNodes.map((node) => node.id))
2999
+ const nodeById = new Map(shownNodes.map((node) => [node.id, node]))
3000
+ const shownEdges = graph.edges.filter((edge) => edgeKinds.includes(edge.kind) && shownIds.has(edge.from) && shownIds.has(edge.to))
3001
+ const NODE_W = 148
3002
+ const NODE_H = 36
3003
+ const centerOf = (id) => {
3004
+ const node = nodeById.get(id)
3005
+ return node === undefined ? null : { x: node.x + NODE_W / 2, y: node.y + NODE_H / 2 }
3006
+ }
3007
+ const svgHeight = expanded === true ? 480 : 208
3008
+ const width = Math.max(graph.bounds?.width ?? 0, 240)
3009
+ const height = Math.max(graph.bounds?.height ?? 0, 100)
3010
+ return h(
3011
+ 'div',
3012
+ { style: { ...S.section, padding: 6 } },
3013
+ h(
3014
+ 'div',
3015
+ { style: S.inline },
3016
+ h('span', { style: { ...S.tag, cursor: 'pointer', opacity: layer === 'ontology' ? 1 : 0.5 }, onClick: () => onLayer('ontology') }, t('本体图')),
3017
+ h('span', { style: { ...S.tag, cursor: 'pointer', opacity: layer === 'entity' ? 1 : 0.5 }, onClick: () => onLayer('entity') }, t('实体图')),
3018
+ h('span', { style: { ...S.faint, flex: '1 1 auto' } }, t('点节点按概念过滤 · 滚轮缩放 · 拖拽平移')),
3019
+ h('span', { style: S.chipAction, onClick: () => setView({ zoom: 1, pan: { x: 0, y: 0 } }) }, t('复位')),
3020
+ h('span', { style: S.chipAction, onClick: onToggleExpand }, expanded === true ? t('还原') : t('全景')),
3021
+ ),
3022
+ shownNodes.length === 0
3023
+ ? h('div', { style: S.faint }, t('此层暂无节点。'))
3024
+ : h(
3025
+ 'div',
3026
+ { style: { overflow: 'auto', border: '1px solid rgba(127,127,127,0.18)', borderRadius: 6, maxHeight: svgHeight + 8 } },
3027
+ h(
3028
+ 'svg',
3029
+ {
3030
+ width,
3031
+ height,
3032
+ viewBox: `${view.pan.x} ${view.pan.y} ${width / view.zoom} ${height / view.zoom}`,
3033
+ style: { display: 'block', cursor: 'grab' },
3034
+ onWheel: (event) => {
3035
+ const delta = typeof event?.deltaY === 'number' ? event.deltaY : 0
3036
+ const zoom = Math.min(3, Math.max(0.3, view.zoom * (1 - delta * 0.001)))
3037
+ setView({ ...view, zoom })
3038
+ },
3039
+ onMouseDown: (event) => {
3040
+ const startX = typeof event?.clientX === 'number' ? event.clientX : 0
3041
+ const startY = typeof event?.clientY === 'number' ? event.clientY : 0
3042
+ const base = view
3043
+ const move = (moveEvent) => {
3044
+ setView({ ...base, pan: { x: base.pan.x - ((moveEvent?.clientX ?? startX) - startX) / base.zoom, y: base.pan.y - ((moveEvent?.clientY ?? startY) - startY) / base.zoom } })
3045
+ }
3046
+ const up = () => {
3047
+ window?.removeEventListener?.('mousemove', move)
3048
+ window?.removeEventListener?.('mouseup', up)
3049
+ }
3050
+ window?.addEventListener?.('mousemove', move)
3051
+ window?.addEventListener?.('mouseup', up)
3052
+ },
3053
+ },
3054
+ h('defs', null, h('marker', { id: 'clearai-onto-arrow', markerWidth: 8, markerHeight: 8, refX: 7, refY: 3, orient: 'auto' }, h('path', { d: 'M0,0 L7,3 L0,6 z', fill: 'currentColor' }))),
3055
+ ...shownEdges.map((edge) => {
3056
+ const from = centerOf(edge.from)
3057
+ const to = centerOf(edge.to)
3058
+ if (from === null || to === null) return null
3059
+ const hot = edge.kind === 'assertion' && conflicted.has(edge.fact)
3060
+ return h(
3061
+ 'g',
3062
+ { key: `e-${edge.id}`, style: { cursor: 'pointer' }, onClick: () => setPicked({ kind: 'edge', edge }) },
3063
+ h('line', {
3064
+ x1: from.x + NODE_W / 2 - 8,
3065
+ y1: from.y,
3066
+ x2: to.x - NODE_W / 2 + 8,
3067
+ y2: to.y,
3068
+ stroke: hot ? '#dc2626' : 'rgba(127,127,127,0.55)',
3069
+ strokeWidth: hot ? 2 : 1,
3070
+ strokeDasharray: edge.kind === 'is_a' ? '4 3' : undefined,
3071
+ markerEnd: 'url(#clearai-onto-arrow)',
3072
+ }),
3073
+ h('text', { x: (from.x + to.x) / 2, y: (from.y + to.y) / 2 - 4, fontSize: 10, textAnchor: 'middle', opacity: 0.75, fill: hot ? '#dc2626' : 'currentColor' }, String(edge.label ?? '')),
3074
+ )
3075
+ }),
3076
+ ...shownNodes.map((node) =>
3077
+ h(
3078
+ 'g',
3079
+ {
3080
+ key: `n-${node.id}`,
3081
+ style: { cursor: node.kind === 'concept' || node.kind === 'instance' ? 'pointer' : 'default' },
3082
+ onClick: () => {
3083
+ if (node.kind === 'concept' || node.kind === 'instance') onFilter(node.ref ?? null, node.kind)
3084
+ else setPicked({ kind: 'node', node })
3085
+ },
3086
+ },
3087
+ h('rect', {
3088
+ x: node.x,
3089
+ y: node.y,
3090
+ width: NODE_W,
3091
+ height: NODE_H,
3092
+ rx: 7,
3093
+ fill: node.kind === 'concept' ? 'rgba(74,163,255,0.16)' : node.kind === 'value_type' ? 'rgba(217,119,6,0.16)' : node.kind === 'instance' ? 'rgba(22,163,74,0.16)' : 'rgba(147,51,234,0.16)',
3094
+ stroke: 'rgba(127,127,127,0.35)',
3095
+ strokeDasharray: node.status === 'deprecated' ? '4 3' : undefined,
3096
+ }),
3097
+ h('text', { x: node.x + NODE_W / 2, y: node.y + 16, fontSize: 11, textAnchor: 'middle' }, String(node.label ?? '').slice(0, 16)),
3098
+ h('text', { x: node.x + NODE_W / 2, y: node.y + 29, fontSize: 9, textAnchor: 'middle', opacity: 0.6 }, node.kind === 'concept' ? `${node.ref ?? ''}${node.uses > 0 ? ` · ${node.uses}` : ''}` : node.kind === 'value_type' ? String(node.ref ?? '') : node.kind === 'instance' ? String(node.type ?? '') : String(node.ref ?? '')),
3099
+ ),
3100
+ ),
3101
+ ),
3102
+ ),
3103
+ allNodes.length > shownNodes.length ? h('div', { style: S.faint }, `${t('图里只画了前')} ${shownNodes.length}/${allNodes.length}${t(' 个节点;全景可看全部')}`) : null,
3104
+ picked === null
3105
+ ? null
3106
+ : h('div', { style: S.chipCard },
3107
+ h('div', { style: S.chipCardTitle }, picked.kind === 'edge' ? `${t('一条边')} · ${String(picked.edge.predicate ?? picked.edge.label ?? '')}` : `${String(picked.node.label ?? '')} · ${String(picked.node.ref ?? '')}`),
3108
+ picked.kind === 'edge' && picked.edge.kind === 'assertion'
3109
+ ? h('div', { style: S.kv }, h('span', { style: S.faint }, `${t('事实')}:`), ` ${String(picked.edge.fact ?? '—')} · ${String(picked.edge.level ?? '—')}`)
3110
+ : null,
3111
+ ),
3112
+ )
3113
+ }
3114
+
3115
+ /**
3116
+ * **词汇维护区**(折叠):词条表、健康度、废止列表、货架入口。
3117
+ * 默认收起——它是参考材料,不挡结论;**0 条目 0 命题而有词条时自动展开**:
3118
+ * 语言先于句子时,立好的词得有地方站。
3119
+ */
3120
+ const VocabBlock = ({ lexicon, open, onToggle, openPreview, sessionId }) => {
3121
+ const terms = Array.isArray(lexicon?.terms) ? lexicon.terms : []
3122
+ const predicates = Array.isArray(lexicon?.predicates) ? lexicon.predicates : []
3123
+ const health = Array.isArray(lexicon?.health) ? lexicon.health : []
3124
+ const warnings = health.filter((issue) => issue.severity === 'warning')
3125
+ const deprecated = [...terms, ...predicates].filter((entry) => entry.status === 'deprecated')
3126
+ /** 编辑是**具名动词的图形前端**:抽屉里填字段,提交走人门通道,面板从不写文件。 */
3127
+ const [drawer, setDrawer] = React.useState(null)
3128
+ const [busy, setBusy] = React.useState(false)
3129
+ const [error, setError] = React.useState(null)
3130
+ const submitOnto = (action, entry) => {
3131
+ setBusy(true)
3132
+ setError(null)
3133
+ fetch('/api/clearai/gate', {
3134
+ method: 'POST',
3135
+ headers: { 'content-type': 'application/json' },
3136
+ body: JSON.stringify({ sessionId, action, entry }),
3137
+ })
3138
+ .then((response) => response.json())
3139
+ .then((result) => {
3140
+ if (result.ok !== true) setError((result.problems ?? [result.error ?? 'failed']).join(';').slice(0, 200))
3141
+ else setDrawer(null)
3142
+ })
3143
+ .catch((thrown) => setError(String(thrown?.message ?? thrown)))
3144
+ .finally(() => setBusy(false))
3145
+ }
3146
+ if (terms.length === 0 && predicates.length === 0) return null
3147
+ return h(
3148
+ 'div',
3149
+ { style: S.section },
3150
+ h(
3151
+ 'div',
3152
+ { style: { ...S.head, cursor: 'pointer' }, onClick: onToggle },
3153
+ `${t('词汇')}(${terms.length} ${t('概念')} · ${predicates.length} ${t('谓词')}${deprecated.length > 0 ? ` · ${deprecated.length} ${t('已废止')}` : ''}) ${open === true ? '▾' : '▸'}`,
3154
+ ),
3155
+ open === false
3156
+ ? null
3157
+ : h(
3158
+ 'div',
3159
+ null,
3160
+ ...terms.map((term) => h('div', { key: `vt-${term.id}`, style: S.row }, h('span', { style: S.mono }, term.id), h('span', { style: S.faint }, ` ${String(term.label ?? '')}${term.status === 'deprecated' ? ` · ${t('已废止')}` : ''}${term.parent ? ` ↖${term.parent}` : ''}`), term.status === 'deprecated' ? null : h('span', { style: S.chipAction, onClick: () => { const reason = window?.prompt?.(`${t('废止')} ${term.id}:${t('为什么?')}`) ; if (typeof reason === 'string' && reason.trim() !== '') submitOnto('deprecate_entry', { id: term.id, reason: reason.trim() }) } }, t('废止')))),
3161
+ ...predicates.map((predicate) => h('div', { key: `vp-${predicate.id}`, style: S.row }, h('span', { style: S.mono }, predicate.id), h('span', { style: S.faint }, ` ${String(predicate.label ?? '')}${predicate.functional === true ? ` · ${t('单值')}` : ''}${predicate.status === 'deprecated' ? ` · ${t('已废止')}` : ''}`), predicate.status === 'deprecated' ? null : h('span', { style: S.chipAction, onClick: () => { const reason = window?.prompt?.(`${t('废止')} ${predicate.id}:${t('为什么?')}`) ; if (typeof reason === 'string' && reason.trim() !== '') submitOnto('deprecate_entry', { id: predicate.id, reason: reason.trim() }) } }, t('废止')))),
3162
+ warnings.length > 0 ? h('div', { style: S.row }, `${t('健康')}:`, ...warnings.map((issue, index) => h('div', { key: `vh-${index}`, style: S.faint }, ` ${issue.id}:${issue.detail}`))) : null,
3163
+ deprecated.length > 0
3164
+ ? h('div', { style: S.row }, ...deprecated.map((entry) => h('div', { key: `vd-${entry.id}`, style: S.faint }, ` ${entry.id} — ${String(entry.deprecated?.reason ?? '')}`)))
3165
+ : null,
3166
+ openPreview === undefined ? null : h('span', { style: S.chipAction, onClick: () => openPreview('clear/ontology/domain.md') }, t('打开词汇货架(原生预览)')),
3167
+ /**
3168
+ * **编辑入口(阶段 E)**:登记概念 / 登记谓词两个表单抽屉;条目行的
3169
+ * 修订与废止在各自那行(见下)。提交 = 一次人门动词;判据在宿主半,
3170
+ * 界面只把表单递过去、把问题清单带回来。
3171
+ */
3172
+ h('div', { style: S.inline },
3173
+ h('span', { style: S.chipAction, onClick: () => setDrawer({ kind: 'term' }) }, `+ ${t('概念')}`),
3174
+ h('span', { style: S.chipAction, onClick: () => setDrawer({ kind: 'predicate' }) }, `+ ${t('谓词')}`),
3175
+ ),
3176
+ drawer === null
3177
+ ? null
3178
+ : h(OntoDrawer, { drawer, setDrawer, busy, error, onSubmit: submitOnto }),
3179
+ ),
3180
+ )
3181
+ }
3182
+
3183
+ /**
3184
+ * **词汇抽屉**:登记概念/谓词的最小表单。字段与动词参数一一对应;
3185
+ * 判据不在这里重复——服务端拒了就把问题清单原样亮出来。
3186
+ */
3187
+ const OntoDrawer = ({ drawer, setDrawer, busy, error, onSubmit }) => {
3188
+ const [form, setForm] = React.useState({ id: '', label: '', gloss: '', basis: '', parent: '', domain: '', unit: '', form: 'quantity', functional: false })
3189
+ const field = (key, placeholder) =>
3190
+ h('input', {
3191
+ value: form[key] ?? '',
3192
+ placeholder,
3193
+ style: { ...S.chip, cursor: 'text', width: '100%' },
3194
+ onInput: (event) => setForm({ ...form, [key]: event?.target?.value ?? '' }),
3195
+ })
3196
+ const isTerm = drawer.kind === 'term'
3197
+ const entry = isTerm
3198
+ ? { id: form.id, label: form.label, gloss: form.gloss, basis: form.basis, parent: form.parent === '' ? undefined : form.parent }
3199
+ : { id: form.id, label: form.label, gloss: form.gloss, basis: form.basis, domain: form.domain === '' ? undefined : form.domain, range: { form: form.form, unit: form.unit === '' ? undefined : form.unit }, functional: form.functional === true ? true : undefined }
3200
+ return h(
3201
+ 'div',
3202
+ { style: S.chipCard },
3203
+ h('div', { style: S.chipCardTitle }, isTerm ? t('登记概念') : t('登记谓词')),
3204
+ field('id', 'id(snake_case)'),
3205
+ field('label', isTerm ? t('名称') : t('名称')),
3206
+ field('gloss', t('释义(一句话)')),
3207
+ isTerm ? field('parent', `${t('父概念')} id(可选)`) : field('domain', `${t('主词域')} id(可选)`),
3208
+ isTerm === true ? null : field('unit', `${t('单位')}(可选)`),
3209
+ isTerm === true ? null : h('label', { style: S.faint }, h('input', { type: 'checkbox', checked: form.functional === true, onChange: (event) => setForm({ ...form, functional: event?.target?.checked === true }) }), ` ${t('单值')}`),
3210
+ field('basis', `${t('依据')}(必填)`),
3211
+ error === null ? null : h('div', { style: { color: '#dc2626', fontSize: 11 } }, String(error)),
3212
+ h('div', { style: S.chipActions },
3213
+ h('span', { style: S.chipAction, onClick: busy === true ? undefined : () => onSubmit(isTerm === true ? 'register_term' : 'register_predicate', entry) }, busy === true ? t('提交中…') : t('提交')),
3214
+ h('span', { style: S.chipAction, onClick: () => setDrawer(null) }, t('取消')),
3215
+ ),
3216
+ )
3217
+ }
3218
+
2797
3219
  const LocalizedDeliverables = withLocale(Deliverables)
2798
3220
  const LocalizedFacts = withLocale(Facts)
2799
3221
  const LocalizedWorldTree = withLocale(WorldTree)
@@ -2912,9 +3334,14 @@ window.__ModuleLoader__.load({
2912
3334
  * 而"当下什么状态"由工具行那颗**计划芯片**回答(它一直在,不用切页签)。
2913
3335
  * 页签越少,越不需要向人解释每个页签该在什么时候看。
2914
3336
  */
3337
+ /**
3338
+ * 标签与说明必须是**函数**:页签类型只在预设生效时注册一次,而语言座位是**随后**才切到
3339
+ * 用户偏好的——写成 `label: t('世界树')` 就把注册那一刻的语言固化了(界面中文、
3340
+ * 右栏页签却是 Worldlines)。惰性取值让原生每次渲染现问一次,切换语言立刻跟上。
3341
+ */
2915
3342
  const rightRail = [
2916
- { id: 'clearai-worldtree', kind: 'clearai-worldtree', label: t('世界树'), order: 15, description: t('计划的拓扑与闸门:脊柱、叉开的车道、收在哪、要你拍哪一下'), icon: NATIVE_ICONS.IconBranchOutline16 },
2917
- { id: 'clearai-brain', kind: 'clearai-brain', label: t('技能 · 记忆'), order: 20, description: t('合并目录、本会话用法、可引用可采纳'), icon: NATIVE_ICONS.IconSkillOutline16 },
3343
+ { id: 'clearai-worldtree', kind: 'clearai-worldtree', label: () => t('世界树'), order: 15, description: () => t('计划的拓扑与闸门:脊柱步、车道、收敛点、人工决策点'), icon: NATIVE_ICONS.IconBranchOutline16 },
3344
+ { id: 'clearai-brain', kind: 'clearai-brain', label: () => t('技能 · 记忆'), order: 20, description: () => t('合并目录、本会话用法、可引用可采纳'), icon: NATIVE_ICONS.IconSkillOutline16 },
2918
3345
  ]
2919
3346
  const shown = new Set()
2920
3347
  const syncRail = () => {
@@ -2936,8 +3363,8 @@ window.__ModuleLoader__.load({
2936
3363
  own.push(ctx.effect(() => sidebarRightTabs.register({
2937
3364
  id: tab.id,
2938
3365
  kind: tab.kind,
2939
- title: () => tab.label,
2940
- guide: [{ order: tab.order, title: () => tab.label, description: () => tab.description, icon: tab.icon }],
3366
+ title: tab.label,
3367
+ guide: [{ order: tab.order, title: tab.label, description: tab.description, icon: tab.icon }],
2941
3368
  }), `clearai: rail type ${tab.id}`))
2942
3369
  } catch (error) {
2943
3370
  // 类型已注册(同名同 layer)不是致命:如实记一笔,继续。
@@ -3047,7 +3474,7 @@ window.__ModuleLoader__.load({
3047
3474
  * 注册时必须把**打开器**都交下去:证据的四类出处、事实原件、跳世界树全靠它们。
3048
3475
  * 漏了它们,界面看着能点、点了什么也不会发生。
3049
3476
  */
3050
- occupy('conversation.view', () => ({ id: 'clearai-facts', order: 20, label: t('事实') }), (props) => h(LocalizedFacts, { ...props, openRail, openSpectator, openPreview: openPreviewFor(props) }))
3477
+ occupy('conversation.view', () => ({ id: 'clearai-facts', order: 20, label: t('本体') }), (props) => h(LocalizedFacts, { ...props, openRail, openSpectator, openPreview: openPreviewFor(props) }))
3051
3478
  /**
3052
3479
  * **计划面坐在原生 plan 那个座位上**。
3053
3480
  *
@@ -3097,12 +3524,14 @@ window.__ModuleLoader__.load({
3097
3524
  * 真的跑一遍渲染路径(捕 undefined 字段访问这类只有渲染时才炸的错)。
3098
3525
  * 仍然不是给别的包用的接口。
3099
3526
  */
3100
- exports.__components = { PlanChip, ContinuationNote, Deliverables, WorldTree, BrainTab, Inbox, TreeDetail, Facts, FactShelf, PropositionShelf, ClearAIMark, LOOP_LABEL, PROPOSITION_GROUPS }
3527
+ exports.__components = { PlanChip, ContinuationNote, Deliverables, WorldTree, BrainTab, GraphBand, VocabBlock, AssertionChips, Inbox, TreeDetail, Facts, FactShelf, PropositionShelf, ClearAIMark, LOOP_LABEL, PROPOSITION_GROUPS }
3101
3528
  /**
3102
3529
  * 测试缝之三:命题那一列的**派生**是纯函数(分组、处境、来路、证据链),
3103
3530
  * 渲染本身没法在没浏览器的地方细究——把它导出去,让测试直接断言派生结果。
3104
3531
  */
3105
3532
  exports.__propositions = { evidenceOf, transitionsOf, whereOf, judgeOf, originsOf, stepOfFact }
3533
+ /** 测试缝之四:本体格的过滤判据(纯函数)。 */
3534
+ exports.__ontology = { termMatches }
3106
3535
  return module.exports
3107
3536
  },
3108
3537
  })