clearai-dsh 0.4.0 → 0.5.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/CHANGELOG.md +40 -0
- package/README.md +6 -6
- package/README.zh-CN.md +6 -6
- package/bin/clearai.mjs +29 -231
- package/cordis.patch.yml +3 -3
- package/lib/client.js +4 -3
- package/lib/domain-language.js +71 -9
- package/lib/fold.js +109 -14
- package/lib/knowledge-view.js +85 -26
- package/package.json +2 -2
- package/presets/clearai/agent.cordis.yml +5 -2
- package/presets/clearai/clearai.patch.yml +5 -2
- package/presets/clearai/plugins/clearai-kernel.js +578 -60
- package/presets/clearai/plugins/ontology.js +21 -7
- package/presets/clearai/plugins/prompts.js +18 -16
- package/presets/clearai/skills/clearai-loop/SKILL.md +12 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are recorded here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.5.0] — 2026-10-08
|
|
8
|
+
|
|
9
|
+
这一版是 0.5 升级的阶段一与阶段二:预期与未解释项、评估者查数据可信、不可逆命令拦在执行前、三档等级、经验与本体分类,宿主下界提到 DSH 0.2。
|
|
10
|
+
|
|
11
|
+
**开发集上的初步结果**(盲评,不当作有效性证据,见 [docs/optimization/sim-runs/](docs/optimization/sim-runs/)):反应器题漂移纠正 ClearAI 3/4、裸模型 1/4;同一现场 3 题序列里第 3 题全部用上了前两题的经验,第 3 题均分 1.5 对 1.17,差距来自漂移这一项;配方与探索深度两边持平。正式验证和探索深度([设计草稿](docs/optimization/0.5-plan/exploration-depth.zh-CN.md))留到之后的版本。
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **预期与未解释项(反常)**:步骤可以带预期 `expect`(预计看到什么、从哪条关系或经验来),动手前也能用 `RevisePlan(action="expect")` 补写。结果和预期或本体对不上的地方,交付时写进 `AdvancePlan.anomalies`,或随时用新工具 `Anomaly` 登记;它们挂在卡上,只有三个去处:被解释、写明理由排除、交给人。不阻塞结案。`STATE_VERSION` 17(投影多了 `anomalies`)。
|
|
16
|
+
- **评估者查还有什么没解释**:任务书列出未解释项,纪律要求查原始数据里没登记的异常(参考读数、重复点漂移、装置之间的差)和排除理由站不站得住;裁决多一个 `anomalies` 字段,折成「评估者发现」的未解释项退回给模型。
|
|
17
|
+
- **不可逆动作拦在命令上**:`Frame` 的 `irreversible` 声明动作和命令特征,匹配的 bash 命令执行前当场问人;不放行或没人能答就拒。
|
|
18
|
+
- **经验(跨任务的「下次怎么做」)**:`Conclude(outcome="achieved")` 多一个可选的 `lessons`(每条一句,分坑 / 先核 / 会骗人的捷径 / 先验四类,带涉及的装置或量、凭据、不适用的条件)。结案评估者对照记录逐条判(裁决多一个 `lessons` 字段),支持的由系统写进 `clear/knowledge/lessons/<id>.json`(做的人写不了),其余在回执里列出。别的会话经工作区同步读到它们;卡上在立题、定计划、写预期前摆出最多 6 条,和眼下目标、下一步提到同一装置或量的排前面。人把文件里的 `status` 改成 `retracted` 就撤回。`STATE_VERSION` 18(投影多了 `lessons`,派生多了 `lessonRows`)。
|
|
19
|
+
- **本体只留能产出预期的东西**:概念分类别 / 度量 / 现象(`kind`),度量必须写 `unit`;关系分影响 / 定义 / 测量 / 表现为(`kind`),影响关系可写大致形状 `shape`(单调升、单调降、有峰、阈值、耦合),测量关系写读数怎么核(`check`);实体可带带日期的 `history`。卡上「用到的关系」把形状和核法递出来;词面命中也看下一步要做什么和它的预期。都是可选格,旧文件照旧有效,指纹不变。
|
|
20
|
+
- 0.5 的设计与升级计划:[meta 设计](docs/optimization/0.5-plan/meta-design.zh-CN.md)、[升级计划](docs/optimization/0.5-plan/upgrade-plan.zh-CN.md)。
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- 本体与认识论状态在决策点递到模型眼前:运行态卡给出判断用到的概念释义和相关事实的原话与边界;目标还没立或已结案时,直接列出以前留下的事实。
|
|
25
|
+
- 本体的提示改为只写推理要用的东西:度量写成概念、释义写口径;因果关系写进关系;实体只在结论要指认它时才建。
|
|
26
|
+
- 独立评估者可以复跑(`auditRerun`,预设打开):评估者在工作区副本里跑产物自带的脚本核数字,原工作区只读;评估期间收下的产物被改动过,这份裁决不认。
|
|
27
|
+
- **等级只给三档**:L2 自己检验、L3 独立评估、L4 人放行。L0–L2 的细分从没改变过谁来判,合并;旧账里的 L0、L1 读作自己检验,新写的收成 L2。
|
|
28
|
+
|
|
29
|
+
- **宿主下界提到 DSH `0.2.0-rc.2`(`engines.dsh` 为 `>=0.2.0-rc.2`),更早的宿主不再支持。** ClearAI 用到的事件、服务方法、客户端插座和 `dsh plugin` 命令行在 0.2.x 上都没有破坏性变化,运行时代码不用改;改的是只在旧的 root 目录名册上才有意义的工具和文档。
|
|
30
|
+
- **`install.sh`(开发形态)改走产品那条路**:构建出包,再 `dsh plugin add` 装进 profile。旧做法把预设拷进 `~/.dsh/.agent-presets`,名册不读它,装得上却选不到 ClearAI。
|
|
31
|
+
- **`verify-deploy` 只验装出来的那个包**,预期的工具数与段数从部署的目录现算;`verify-clean-install` / `verify-lifecycle` 只认声明行;`e2e-run` 只在宿主还带着 `@deepseek-ai/dsh-invariants` 时才插那一行(`0.2.1-alpha.1` 已移除该包)。
|
|
32
|
+
|
|
33
|
+
### Removed
|
|
34
|
+
|
|
35
|
+
- 对手判断(`rival` / `split_by`)与「检验可能太弱」的提示:两道难题的 8 组运行里对手 0 次使用,提示连续出现也没改变做法。
|
|
36
|
+
- 运行态卡上的本体提纲与计数:它从没改变过下一步。卡上只出现被判断引用到的本体项。
|
|
37
|
+
- `clearai-dsh root-yaml` / `seed` / `unseed`:它们服务的是旧名册的目录扫描,0.2.x 宿主里没有这个名册。`doctor` 改为检查组合里有没有 `preset-clearai` 声明行。
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- 判断几乎从不升格成事实:升格只看模型自己给步骤标的等级,而 L0–L2 允许自判,五个长程任务的 9 次运行里模型一律标 L1/L2,一条事实都没有。现在结案那次独立评估顺带逐条判还活着的判断,判为支持的升格(证据记为独立、等级按目标门槛),判为推翻的不升格并照常复核已有事实;不多派评估者。
|
|
42
|
+
- 别的会话留下的事实被新证据推翻时不会问人:这一问只认本目标的判断编号。现在判断可带 `retests: "<事实 id>"`,复检被推翻就当场问人撤回还是维持,结论写回事实文件。
|
|
43
|
+
- 复检旧事实时模型把判断写成「旧事实被推翻」,评估判支持后它升格成一条与旧事实相反的新事实,旧事实照旧「已确立」,也没人被问。`retests` 的说明和提示词现在要求 claim 照抄旧事实原来的说法。
|
|
44
|
+
|
|
5
45
|
## [0.4.0] — 2026-10-02
|
|
6
46
|
|
|
7
47
|
这一版包括「少即是多」改造的全部六个阶段(见下面各段)、本体改成文件树,以及中英两种语言的完整支持。
|
package/README.md
CHANGED
|
@@ -22,8 +22,8 @@ ClearAI is an **ontology discovery and exploration platform**, built on two core
|
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
# Install (npm package, prebuilt — no build step, no allowBuilds prompt)
|
|
25
|
-
dsh plugin --profile web add clearai-dsh@0.
|
|
26
|
-
# or in the app: Plugins → Add plugin → clearai-dsh@0.
|
|
25
|
+
dsh plugin --profile web add clearai-dsh@0.5.0
|
|
26
|
+
# or in the app: Plugins → Add plugin → clearai-dsh@0.5.0
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Restart `dsh web`, then pick **ClearAI** in the preset picker at the top of a new session. That is the whole setup. [Full install notes ↓](#install-and-use)
|
|
@@ -74,16 +74,16 @@ ClearAI does **not** claim recursive self-improvement. It provides the epistemic
|
|
|
74
74
|
|
|
75
75
|
## Install and use
|
|
76
76
|
|
|
77
|
-
**Requirements:** DSH ≥ `0.
|
|
77
|
+
**Requirements:** DSH ≥ `0.2.0-rc.2` (the current `latest`). The preset is registered through a composition declaration line, which is the only way the host's preset registry finds presets. Verified against the host's `0.2.0-rc.2`, and also checked against `0.2.1-alpha.1`. Hosts older than `0.2.0` are no longer supported.
|
|
78
78
|
|
|
79
79
|
**Recommended — install it in the app, with the version pinned:**
|
|
80
80
|
|
|
81
|
-
In the sidebar open **Plugins → Add plugin**, enter `clearai-dsh@0.
|
|
81
|
+
In the sidebar open **Plugins → Add plugin**, enter `clearai-dsh@0.5.0`, and install. That is DSH's own plugin manager: it hands what you type to pnpm, checks that the package declares a bundle and is compatible with this host, and applies it live. (The Settings page **插件列表 / Plugins** is the read-only inventory — installing happens on the sidebar's Plugins page.)
|
|
82
82
|
|
|
83
83
|
**Or from a terminal — the same install:**
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
|
-
dsh plugin --profile web add clearai-dsh@0.
|
|
86
|
+
dsh plugin --profile web add clearai-dsh@0.5.0
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
This installs the prebuilt package from the npm registry. Nothing is compiled on your machine, so there is no `allowBuilds` grant to approve — the plugin is ready the moment the command returns.
|
|
@@ -116,7 +116,7 @@ dsh plugin --profile web add github:Clearailhc/clearai-dsh
|
|
|
116
116
|
|
|
117
117
|
Git fetches source rather than build artifacts, so pnpm ≥10 will refuse to run the `prepare` script until you add an `allowBuilds` entry to the profile's `pnpm-workspace.yaml`. That grant means *permission for this package's code to execute on your machine at install time* — grant it only if you have read the source, and pin a commit. If you just want to use ClearAI, use the npm install above.
|
|
118
118
|
|
|
119
|
-
The installer's output follows your system language (`--lang zh|en` overrides it, `doctor`
|
|
119
|
+
The installer's output follows your system language (`--lang zh|en` overrides it, and `doctor` takes the same flag). Its only runtime dependency is `zod`; the graph stack is bundled into the client half at build time.
|
|
120
120
|
|
|
121
121
|
Restart `dsh web` afterwards (`npx @deepseek-ai/dsh web`), then **create a session and switch to the `ClearAI` mode in the picker at the top**:
|
|
122
122
|
|
package/README.zh-CN.md
CHANGED
|
@@ -22,8 +22,8 @@ ClearAI 是一个**本体发现与探索平台**,核心由两个概念支撑
|
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
# 安装(npm 包,预构建——无需构建步骤,不会触发 allowBuilds 授权)
|
|
25
|
-
dsh plugin --profile web add clearai-dsh@0.
|
|
26
|
-
# 或在应用里:侧栏「插件」→ 添加插件 → clearai-dsh@0.
|
|
25
|
+
dsh plugin --profile web add clearai-dsh@0.5.0
|
|
26
|
+
# 或在应用里:侧栏「插件」→ 添加插件 → clearai-dsh@0.5.0
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
重启 `dsh web`,在新建会话顶部的模式选择器里选 **ClearAI** 即可。这就是全部步骤。[完整安装说明 ↓](#安装与使用)
|
|
@@ -74,16 +74,16 @@ ClearAI **不**声称递归自我改进。它提供的是自我改进系统所
|
|
|
74
74
|
|
|
75
75
|
## 安装与使用
|
|
76
76
|
|
|
77
|
-
**要求:** DSH ≥ `0.
|
|
77
|
+
**要求:** DSH ≥ `0.2.0-rc.2`(当前的 `latest`)。预设靠组合里的声明行注册,宿主的预设名册只认这一种。已在宿主的 `0.2.0-rc.2` 上验过,`0.2.1-alpha.1` 也核过。`0.2.0` 以前的宿主不再支持。
|
|
78
78
|
|
|
79
79
|
**推荐——在应用里装,并把版本钉住:**
|
|
80
80
|
|
|
81
|
-
侧栏打开**「插件」→ 添加插件**,填 `clearai-dsh@0.
|
|
81
|
+
侧栏打开**「插件」→ 添加插件**,填 `clearai-dsh@0.5.0`,安装。这就是 DSH 自己的插件管理器:它把你填的东西交给 pnpm,校验这个包声明了组合包、与当前宿主兼容,然后当场生效。(设置里的**插件列表**是**只读清单**;安装入口在侧栏那个「插件」页。)
|
|
82
82
|
|
|
83
83
|
**或者开终端——同一次安装:**
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
|
-
dsh plugin --profile web add clearai-dsh@0.
|
|
86
|
+
dsh plugin --profile web add clearai-dsh@0.5.0
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
从 npm registry 装预构建产物。本机不跑任何编译,因此不需要批准 `allowBuilds` 授权——命令返回时插件就已经可用。
|
|
@@ -116,7 +116,7 @@ dsh plugin --profile web add github:Clearailhc/clearai-dsh
|
|
|
116
116
|
|
|
117
117
|
Git 拉的是源码而不是构建产物,所以 pnpm ≥10 会拒绝运行 `prepare` 脚本,直到你在该 profile 的 `pnpm-workspace.yaml` 里加上 `allowBuilds` 条目。那条授权的含义是**允许该包代码在安装时于你机器上执行**——只在你读过源码后再授权,并且固定 commit。如果你只是想用 ClearAI,请用上面的 npm 安装。
|
|
118
118
|
|
|
119
|
-
安装侧的输出**跟系统语言走**(`--lang zh|en` 可覆盖;`doctor`
|
|
119
|
+
安装侧的输出**跟系统语言走**(`--lang zh|en` 可覆盖;`doctor` 同样认这个开关)。运行时依赖只有 `zod`——图谱那套栈在构建期就打进客户端了。
|
|
120
120
|
|
|
121
121
|
|
|
122
122
|
装完重启 `dsh web`(`npx @deepseek-ai/dsh web`),然后**新建会话,在顶部的模式选择器里切换到 `ClearAI`**:
|
package/bin/clearai.mjs
CHANGED
|
@@ -5,27 +5,23 @@
|
|
|
5
5
|
* 分包的三样东西落在三个平面:
|
|
6
6
|
* · 宿主半(`lib/host.js`)—— 由包自带的 `cordis.patch.yml` 在 profile 层插一行,`dsh plugin add` 自动生效;
|
|
7
7
|
* · 浏览器半(`lib/client.js`)—— 同一份清单里的 `dsh.client`,浏览器 Loader 自己扫;
|
|
8
|
-
* · agent 预设(`presets/clearai
|
|
9
|
-
*
|
|
8
|
+
* · agent 预设(`presets/clearai/clearai.patch.yml`)—— 一条 `- id: preset-clearai` 声明行,
|
|
9
|
+
* 经清单的 `dsh.bundle.patch` 挂进组合;名册(`agent-preset-registry`)读的就是它。
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* 宿主 ≥0.2.0 的名册**不扫目录、不收预设路径**(`@deepseek-ai/dsh-agent-preset-registry` 的 README:
|
|
12
|
+
* "the registry neither scans directories nor accepts preset paths"),所以旧的 root 目录那几个动词
|
|
13
|
+
* (`root-yaml` / `seed` / `unseed`)已经删掉:它们写出去的东西在这些宿主上没人读。
|
|
14
|
+
*
|
|
15
|
+
* 两个动词(默认是 `doctor` —— 一个安装侧工具不该在你没说要装的时候动你的部署):
|
|
16
|
+
* doctor 看现状:包在哪、预设在哪、组合里有没有宿主行与预设声明行、探测到的 dsh / profile 是什么
|
|
14
17
|
* install 把包装进 profile —— `dsh plugin --profile <p> add <spec>` 的一层**前置解析**
|
|
15
18
|
* (读者不必知道 profile 叫什么、CLI 从哪来、包名怎么写),装完给读数与下一步
|
|
16
|
-
* root-yaml 打印**可以直接粘进 profile 的 `cordis.patch.yml`** 的那一行(路径已算成绝对路径)
|
|
17
|
-
* seed 把预设**播种**到用户根 `~/.dsh/.agent-presets/<id>`(带哈希记账:改过的不覆盖)
|
|
18
|
-
* unseed 撤掉播种:只删「我们播的、且没被改过」的文件;用户 fork 的 id 一律不碰
|
|
19
|
-
*
|
|
20
|
-
* 纪律(与内核播种模板技能同一条):**改过的东西不覆盖,只如实报漂移**;删东西之前先看哈希。
|
|
21
|
-
* 不改用户的 `cordis.patch.yml` —— 那一行的内容由人自己粘(工具只负责把绝对路径算对)。
|
|
22
19
|
*/
|
|
23
20
|
|
|
24
|
-
import { createHash } from 'node:crypto'
|
|
25
21
|
import { spawnSync } from 'node:child_process'
|
|
26
|
-
import {
|
|
22
|
+
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
27
23
|
import { homedir } from 'node:os'
|
|
28
|
-
import { delimiter, dirname, join,
|
|
24
|
+
import { delimiter, dirname, join, resolve } from 'node:path'
|
|
29
25
|
import { fileURLToPath } from 'node:url'
|
|
30
26
|
|
|
31
27
|
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
@@ -33,7 +29,6 @@ const PKG_DIR = resolve(HERE, '..')
|
|
|
33
29
|
const PRESET_ID = 'clearai'
|
|
34
30
|
const PRESET_SRC = join(PKG_DIR, 'presets', PRESET_ID)
|
|
35
31
|
const DSH_HOME = process.env.DSH_HOME ?? join(homedir(), '.dsh')
|
|
36
|
-
const LEDGER = join(DSH_HOME, '.clearai-dsh.json')
|
|
37
32
|
|
|
38
33
|
const argv = process.argv.slice(2)
|
|
39
34
|
const command = argv[0] ?? 'doctor'
|
|
@@ -67,13 +62,9 @@ const TEXT = {
|
|
|
67
62
|
zh: {
|
|
68
63
|
pkgDir: '包目录 ',
|
|
69
64
|
presetSrc: '预设源 ',
|
|
70
|
-
presetOk: '(
|
|
71
|
-
presetMissing: '(缺
|
|
65
|
+
presetOk: '(clearai.patch.yml ✓)',
|
|
66
|
+
presetMissing: '(缺 clearai.patch.yml ✗)',
|
|
72
67
|
dshHome: 'DSH_HOME ',
|
|
73
|
-
userRoot: '用户根 ',
|
|
74
|
-
rosterVisible: '✓ 名册看得见',
|
|
75
|
-
rosterAbsent: '✗ 还没有(用 seed 播种,或把 root-yaml 那一行粘进 profile)',
|
|
76
|
-
shadowCopy: ' ⚠️ 影子副本 {path} 与包里的那份**不一致**,而它被包的 root 遮住、永远不会被读到(自检却会优先读它)。删掉它,或用它来承载你自己的改动并换一个 id。',
|
|
77
68
|
profileRow: 'profile ',
|
|
78
69
|
profileAbsent: '(不存在:先跑一次 dsh --profile {profile})',
|
|
79
70
|
composeRow: '组合 ',
|
|
@@ -81,13 +72,10 @@ const TEXT = {
|
|
|
81
72
|
hostRow: '宿主行 ',
|
|
82
73
|
hostIn: '在组合里 ✓',
|
|
83
74
|
hostOut: '不在组合里(先 dsh plugin --profile {profile} add <本包>)',
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
ledgerEmpty: '(空)',
|
|
89
|
-
ledgerCount: '{count} 个条目 · {path}',
|
|
90
|
-
doctorHint: '\n提示:doctor 只读;它不会替你改 profile,也不会替你播种。',
|
|
75
|
+
presetRow: '预设声明行 ',
|
|
76
|
+
presetIn: '在组合里 ✓(preset-clearai)',
|
|
77
|
+
presetOut: '不在组合里:名册里不会有 ClearAI(这个 profile 可能没挂 agent-preset-registry,或宿主早于 0.2.0)',
|
|
78
|
+
doctorHint: '\n提示:doctor 只读;它不会替你改 profile。',
|
|
91
79
|
installHeader: '【安装】{name}@{version}',
|
|
92
80
|
installWhat: '装什么 ',
|
|
93
81
|
installWhere: '装到哪 ',
|
|
@@ -104,30 +92,15 @@ const TEXT = {
|
|
|
104
92
|
hostAbsent: '**不在组合里** —— 装是装上了,但组合里没看到它(用 doctor 查)',
|
|
105
93
|
nextStep: '\n 下一步 重启 dsh web(两半都在进程里按模块 URL 缓存,只刷新浏览器不够),然后在预设选择器里选 ClearAI。',
|
|
106
94
|
uninstall: ' 卸载 dsh plugin --profile {profile} remove {name}(同样可以冠 npx)',
|
|
107
|
-
rootYamlComment1: '# ClearAI 预设的 root(由 clearai-dsh 的 bin 打印,路径已算成绝对路径)',
|
|
108
|
-
rootYamlComment2: ' # ⚠️ 补丁层会**替换整份 config**:下面这些键必须与你部署里那份一致,否则会丢。',
|
|
109
|
-
rootYamlComment3: ' # 先 `dsh --profile <p> --dump-config | grep -A 20 agent-presets` 看一眼当前值再粘。',
|
|
110
|
-
noPresetInPackage: '✗ 包里没有预设:{path}',
|
|
111
|
-
seededTo: ' 播种到 {dest}',
|
|
112
|
-
seedCounts: ' 新增 {seeded} · 刷新 {refreshed}',
|
|
113
|
-
seedDrifted: ' · **你改过、没覆盖** {count}({list})',
|
|
114
|
-
seedNext: ' 下一步:重启 dsh(或刷新页面)后,预设选择器里应出现「ClearAI」。',
|
|
115
|
-
noSeedLedger: ' 没有播种记账:什么都不做(不知道哪些是我们播的,就不删)。',
|
|
116
|
-
unseedRemoved: ' 删掉 {count} 个「我们播的、没被改过」的文件',
|
|
117
|
-
unseedKept: ' **保留** {count} 个你改过的文件(它们现在是你的):{list}',
|
|
118
95
|
unknownCommand: 'unknown command: {command}',
|
|
119
|
-
usage: '用法:clearai-dsh [doctor|install|
|
|
96
|
+
usage: '用法:clearai-dsh [doctor|install|version] [--profile web] [--home <dir>] [--lang zh|en]\n install 还可以:--dist <dir> | --tarball <tgz> | --spec <spec>',
|
|
120
97
|
},
|
|
121
98
|
en: {
|
|
122
99
|
pkgDir: 'package ',
|
|
123
100
|
presetSrc: 'preset src ',
|
|
124
|
-
presetOk: '(
|
|
125
|
-
presetMissing: '(no
|
|
101
|
+
presetOk: '(clearai.patch.yml ✓)',
|
|
102
|
+
presetMissing: '(no clearai.patch.yml ✗)',
|
|
126
103
|
dshHome: 'DSH_HOME ',
|
|
127
|
-
userRoot: 'user root ',
|
|
128
|
-
rosterVisible: '✓ visible to the roster',
|
|
129
|
-
rosterAbsent: '✗ not there yet (seed it, or paste the root-yaml line into the profile)',
|
|
130
|
-
shadowCopy: ' ⚠️ shadow copy {path} differs from the copy in the package, and the package root shadows it — it will never be read (while the self-check reads it first). Delete it, or keep your changes there under a different id.',
|
|
131
104
|
profileRow: 'profile ',
|
|
132
105
|
profileAbsent: '(does not exist yet: run dsh --profile {profile} once)',
|
|
133
106
|
composeRow: 'composition ',
|
|
@@ -135,13 +108,10 @@ const TEXT = {
|
|
|
135
108
|
hostRow: 'host row ',
|
|
136
109
|
hostIn: 'is in the composition ✓',
|
|
137
110
|
hostOut: 'is NOT in the composition (run dsh plugin --profile {profile} add <this package>)',
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
ledgerEmpty: '(empty)',
|
|
143
|
-
ledgerCount: '{count} entries · {path}',
|
|
144
|
-
doctorHint: '\ndoctor only reads. It will not change your profile and will not seed anything for you.',
|
|
111
|
+
presetRow: 'preset row ',
|
|
112
|
+
presetIn: 'is in the composition ✓ (preset-clearai)',
|
|
113
|
+
presetOut: 'is NOT in the composition: the roster will not offer ClearAI (this profile may not mount agent-preset-registry, or the host predates 0.2.0)',
|
|
114
|
+
doctorHint: '\ndoctor only reads. It will not change your profile.',
|
|
145
115
|
installHeader: '[install] {name}@{version}',
|
|
146
116
|
installWhat: 'what ',
|
|
147
117
|
installWhere: 'where ',
|
|
@@ -158,73 +128,18 @@ const TEXT = {
|
|
|
158
128
|
hostAbsent: '**NOT in the composition** — it installed, but the composition does not show it (run doctor)',
|
|
159
129
|
nextStep: '\n next restart dsh web (both halves are cached in the running process by module URL, so a browser refresh is not enough), then pick ClearAI in the preset picker.',
|
|
160
130
|
uninstall: ' uninstall dsh plugin --profile {profile} remove {name}(npx works too)',
|
|
161
|
-
rootYamlComment1: '# ClearAI preset root (printed by clearai-dsh; the path is already absolute)',
|
|
162
|
-
rootYamlComment2: ' # ⚠️ a patch layer **replaces the whole config**: these keys must match the ones in your deployment, or they are lost.',
|
|
163
|
-
rootYamlComment3: ' # Run `dsh --profile <p> --dump-config | grep -A 20 agent-presets` first and paste over the current values.',
|
|
164
|
-
noPresetInPackage: '✗ no preset in the package: {path}',
|
|
165
|
-
seededTo: ' seeded to {dest}',
|
|
166
|
-
seedCounts: ' added {seeded} · refreshed {refreshed}',
|
|
167
|
-
seedDrifted: ' · **kept your edits** {count}({list})',
|
|
168
|
-
seedNext: ' next: restart dsh (or refresh the page) — ClearAI should now appear in the preset picker.',
|
|
169
|
-
noSeedLedger: ' nothing was seeded: doing nothing (without the ledger there is no way to tell which files are ours, so nothing is deleted).',
|
|
170
|
-
unseedRemoved: ' removed {count} file(s) we seeded and you did not edit',
|
|
171
|
-
unseedKept: ' **kept** {count} file(s) you edited (they are yours now): {list}',
|
|
172
131
|
unknownCommand: 'unknown command: {command}',
|
|
173
|
-
usage: 'usage: clearai-dsh [doctor|install|
|
|
132
|
+
usage: 'usage: clearai-dsh [doctor|install|version] [--profile web] [--home <dir>] [--lang zh|en]\n install also takes: --dist <dir> | --tarball <tgz> | --spec <spec>',
|
|
174
133
|
},
|
|
175
134
|
}
|
|
176
135
|
|
|
177
|
-
/** `{name}`
|
|
136
|
+
/** `{name}` 是占位符。 */
|
|
178
137
|
function t(key, params) {
|
|
179
138
|
const text = TEXT[lang][key] ?? TEXT.zh[key]
|
|
180
139
|
if (text === undefined) throw new Error(`missing text: ${key}`)
|
|
181
140
|
return typeof text === 'function' ? text(params ?? {}) : text.replace(/\{(\w+)\}/g, (_, name) => String(params?.[name] ?? ''))
|
|
182
141
|
}
|
|
183
142
|
|
|
184
|
-
/** 递归列出文件(相对路径 → sha256 前 16 位)。只为记账,不为校验完整性。 */
|
|
185
|
-
function hashTree(root) {
|
|
186
|
-
const out = {}
|
|
187
|
-
const walk = (dir) => {
|
|
188
|
-
let entries = []
|
|
189
|
-
try {
|
|
190
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
191
|
-
} catch {
|
|
192
|
-
return
|
|
193
|
-
}
|
|
194
|
-
for (const entry of entries) {
|
|
195
|
-
const full = join(dir, entry.name)
|
|
196
|
-
if (entry.isDirectory()) walk(full)
|
|
197
|
-
else if (entry.isFile()) out[relative(root, full)] = createHash('sha256').update(readFileSync(full)).digest('hex').slice(0, 16)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
walk(root)
|
|
201
|
-
return out
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function readLedger() {
|
|
205
|
-
try {
|
|
206
|
-
const parsed = JSON.parse(readFileSync(LEDGER, 'utf8'))
|
|
207
|
-
return parsed !== null && typeof parsed === 'object' ? parsed : {}
|
|
208
|
-
} catch {
|
|
209
|
-
return {}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function writeLedger(next) {
|
|
214
|
-
try {
|
|
215
|
-
mkdirSync(dirname(LEDGER), { recursive: true })
|
|
216
|
-
writeFileSync(LEDGER, `${JSON.stringify(next, null, 2)}\n`, 'utf8')
|
|
217
|
-
return true
|
|
218
|
-
} catch {
|
|
219
|
-
return false
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/** 名册会扫哪些 root —— 与 `@deepseek-ai/dsh-agent-presets` 的规则同形(自带 → 配置 → 用户根)。 */
|
|
224
|
-
function rosterRoots() {
|
|
225
|
-
return [join(DSH_HOME, '.agent-presets')]
|
|
226
|
-
}
|
|
227
|
-
|
|
228
143
|
/**
|
|
229
144
|
* 在 PATH 上找一个可执行文件,找到就返回全路径。
|
|
230
145
|
*
|
|
@@ -266,35 +181,12 @@ function composeQuery(profileName, env) {
|
|
|
266
181
|
function doctor() {
|
|
267
182
|
const rows = []
|
|
268
183
|
rows.push(`${t('pkgDir')}${PKG_DIR}`)
|
|
269
|
-
rows.push(`${t('presetSrc')}${PRESET_SRC}${existsSync(join(PRESET_SRC, '
|
|
184
|
+
rows.push(`${t('presetSrc')}${PRESET_SRC}${existsSync(join(PRESET_SRC, 'clearai.patch.yml')) ? t('presetOk') : t('presetMissing')}`)
|
|
270
185
|
rows.push(`${t('dshHome')}${DSH_HOME}`)
|
|
271
|
-
const roots = rosterRoots()
|
|
272
|
-
for (const root of roots) {
|
|
273
|
-
const dir = join(root, PRESET_ID)
|
|
274
|
-
const present = existsSync(join(dir, 'agent.cordis.yml'))
|
|
275
|
-
rows.push(`${t('userRoot')}${dir} ${present ? t('rosterVisible') : t('rosterAbsent')}`)
|
|
276
|
-
/**
|
|
277
|
-
* 用户根里那份**会不会被包的 root 遮住**。
|
|
278
|
-
*
|
|
279
|
-
* 名册按 root 顺序先到先得(自带 root → 配置 root → 用户根),所以包一装,用户根里
|
|
280
|
-
* 同 id 的那份副本就**再也读不到**——它会安静地烂在那里,还会把「部署出去的那份」的
|
|
281
|
-
* 自检引到你手改过的旧副本上。判据只取事实:两份 `preset.yml` 的字节是否一致。
|
|
282
|
-
*/
|
|
283
|
-
const mine = join(PRESET_SRC, 'preset.yml')
|
|
284
|
-
const theirs = join(dir, 'preset.yml')
|
|
285
|
-
if (!present || !existsSync(mine) || !existsSync(theirs)) continue
|
|
286
|
-
let same = false
|
|
287
|
-
try {
|
|
288
|
-
same = readFileSync(mine).equals(readFileSync(theirs))
|
|
289
|
-
} catch {
|
|
290
|
-
same = false
|
|
291
|
-
}
|
|
292
|
-
if (!same) rows.push(t('shadowCopy', { path: theirs }))
|
|
293
|
-
}
|
|
294
186
|
const profileDir = join(DSH_HOME, 'profiles', profile)
|
|
295
187
|
rows.push(`${t('profileRow')}${profileDir}${existsSync(profileDir) ? '' : t('profileAbsent', { profile })}`)
|
|
296
188
|
/**
|
|
297
|
-
*
|
|
189
|
+
* 宿主行与预设声明行**问组合**,不问某个文件(2026-09-11 修:装出来的形态下这两行来自
|
|
298
190
|
* **包的补丁层**,不在 profile 的 cordis.patch.yml 里 —— 读文件的写法会误报「还没挂」)。
|
|
299
191
|
* 事实在组合里;问不到就如实说问不到,不猜。
|
|
300
192
|
*/
|
|
@@ -304,12 +196,9 @@ function doctor() {
|
|
|
304
196
|
} else {
|
|
305
197
|
const rowIds = [...composed.matchAll(/^- id: (\S+)$/gm)].map((match) => match[1])
|
|
306
198
|
rows.push(`${t('hostRow')}${rowIds.includes('clearai-host') ? t('hostIn') : t('hostOut', { profile })}`)
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
rows.push(`${t('rosterRootRow')}${expr === null ? t('rosterNoRoots') : t('rosterExpr', { expr })}`)
|
|
199
|
+
/** 名册读的是组合里的 `preset-clearai` 声明行(由包的 `dsh.bundle.patch` 挂进来),不是某个目录。 */
|
|
200
|
+
rows.push(`${t('presetRow')}${rowIds.includes('preset-clearai') ? t('presetIn') : t('presetOut')}`)
|
|
310
201
|
}
|
|
311
|
-
const ledger = readLedger()
|
|
312
|
-
rows.push(`${t('seedLedgerRow')}${Object.keys(ledger).length === 0 ? t('ledgerEmpty') : t('ledgerCount', { count: Object.keys(ledger).length, path: LEDGER })}`)
|
|
313
202
|
for (const row of rows) console.log(` ${row}`)
|
|
314
203
|
console.log(t('doctorHint'))
|
|
315
204
|
}
|
|
@@ -386,99 +275,8 @@ function install() {
|
|
|
386
275
|
console.log(t('uninstall', { profile, name: manifest.name }))
|
|
387
276
|
}
|
|
388
277
|
|
|
389
|
-
function rootYaml() {
|
|
390
|
-
const line = [
|
|
391
|
-
t('rootYamlComment1'),
|
|
392
|
-
'- id: \'@deepseek-ai/dsh-agent-presets\'',
|
|
393
|
-
' config:',
|
|
394
|
-
t('rootYamlComment2'),
|
|
395
|
-
t('rootYamlComment3'),
|
|
396
|
-
' default: standard',
|
|
397
|
-
' includeShippedRoot: true',
|
|
398
|
-
' includeUserRoot: true',
|
|
399
|
-
' roots:',
|
|
400
|
-
` - path: '${join(PKG_DIR, 'presets')}'`,
|
|
401
|
-
' trust: system',
|
|
402
|
-
].join('\n')
|
|
403
|
-
console.log(line)
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function seed() {
|
|
407
|
-
if (!existsSync(join(PRESET_SRC, 'agent.cordis.yml'))) {
|
|
408
|
-
console.error(t('noPresetInPackage', { path: PRESET_SRC }))
|
|
409
|
-
process.exit(1)
|
|
410
|
-
}
|
|
411
|
-
const root = value('root', rosterRoots()[0])
|
|
412
|
-
const dest = join(root, PRESET_ID)
|
|
413
|
-
const next = hashTree(PRESET_SRC)
|
|
414
|
-
const before = readLedger()
|
|
415
|
-
const previous = before[PRESET_ID]?.files ?? {}
|
|
416
|
-
const seeded = []
|
|
417
|
-
const refreshed = []
|
|
418
|
-
const drifted = []
|
|
419
|
-
for (const [rel, hash] of Object.entries(next)) {
|
|
420
|
-
const target = join(dest, rel)
|
|
421
|
-
const onDisk = existsSync(target) ? createHash('sha256').update(readFileSync(target)).digest('hex').slice(0, 16) : null
|
|
422
|
-
if (onDisk === null) {
|
|
423
|
-
mkdirSync(dirname(target), { recursive: true })
|
|
424
|
-
cpSync(join(PRESET_SRC, rel), target)
|
|
425
|
-
seeded.push(rel)
|
|
426
|
-
continue
|
|
427
|
-
}
|
|
428
|
-
if (onDisk === hash) continue
|
|
429
|
-
// 改过的不覆盖:与内核播种模板技能同一条纪律
|
|
430
|
-
if (previous[rel] !== undefined && onDisk !== previous[rel]) {
|
|
431
|
-
drifted.push(rel)
|
|
432
|
-
continue
|
|
433
|
-
}
|
|
434
|
-
cpSync(join(PRESET_SRC, rel), target)
|
|
435
|
-
refreshed.push(rel)
|
|
436
|
-
}
|
|
437
|
-
before[PRESET_ID] = { files: next, at: new Date().toISOString(), dest }
|
|
438
|
-
writeLedger(before)
|
|
439
|
-
console.log(t('seededTo', { dest }))
|
|
440
|
-
console.log(`${t('seedCounts', { seeded: seeded.length, refreshed: refreshed.length })}${drifted.length === 0 ? '' : t('seedDrifted', { count: drifted.length, list: drifted.slice(0, 5).join(lang === 'zh' ? '、' : ', ') })}`)
|
|
441
|
-
console.log(t('seedNext'))
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
function unseed() {
|
|
445
|
-
const ledger = readLedger()
|
|
446
|
-
const entry = ledger[PRESET_ID]
|
|
447
|
-
if (entry === undefined) {
|
|
448
|
-
console.log(t('noSeedLedger'))
|
|
449
|
-
return
|
|
450
|
-
}
|
|
451
|
-
const dest = entry.dest ?? join(rosterRoots()[0], PRESET_ID)
|
|
452
|
-
const removed = []
|
|
453
|
-
const kept = []
|
|
454
|
-
for (const [rel, hash] of Object.entries(entry.files ?? {})) {
|
|
455
|
-
const target = join(dest, rel)
|
|
456
|
-
if (!existsSync(target)) continue
|
|
457
|
-
const onDisk = createHash('sha256').update(readFileSync(target)).digest('hex').slice(0, 16)
|
|
458
|
-
if (onDisk === hash) {
|
|
459
|
-
rmSync(target)
|
|
460
|
-
removed.push(rel)
|
|
461
|
-
} else {
|
|
462
|
-
kept.push(rel)
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
delete ledger[PRESET_ID]
|
|
466
|
-
writeLedger(ledger)
|
|
467
|
-
console.log(t('unseedRemoved', { count: removed.length }))
|
|
468
|
-
if (kept.length > 0) console.log(t('unseedKept', { count: kept.length, list: kept.slice(0, 5).join(lang === 'zh' ? '、' : ', ') }))
|
|
469
|
-
// 空目录收掉(只收我们知道的那些;非空绝不动)
|
|
470
|
-
try {
|
|
471
|
-
if (existsSync(dest) && readdirSync(dest).length === 0) rmSync(dest, { recursive: true })
|
|
472
|
-
} catch {
|
|
473
|
-
/* 收不掉就算了,不影响判定 */
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
278
|
if (command === 'doctor') doctor()
|
|
478
279
|
else if (command === 'install') install()
|
|
479
|
-
else if (command === 'root-yaml') rootYaml()
|
|
480
|
-
else if (command === 'seed') seed()
|
|
481
|
-
else if (command === 'unseed') unseed()
|
|
482
280
|
else if (command === 'version' || flag('version')) console.log(JSON.parse(readFileSync(join(PKG_DIR, 'package.json'), 'utf8')).version)
|
|
483
281
|
else {
|
|
484
282
|
console.error(`${t('unknownCommand', { command })}\n${t('usage')}`)
|
package/cordis.patch.yml
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
- id: clearai-host
|
|
13
13
|
name: 'clearai-dsh'
|
|
14
14
|
|
|
15
|
-
# ── 预设不在这里声明 root
|
|
15
|
+
# ── 预设不在这里声明 root:宿主的名册不扫目录(本包要求宿主 ≥0.2.0-rc.2)──────────
|
|
16
16
|
#
|
|
17
17
|
# 0.2.3 及以前走的是「root 目录」机制:宿主自带 `- id: agent-presets` 行,本文件覆盖它的
|
|
18
18
|
# config,把 root 指到包内 presets/,归属落在 system 信任层。
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
# 依据与实测:`lab/release/0.2.3-release-blocker.md`、`lab/adapter/0.2.4-design.md`。
|
|
29
29
|
#
|
|
30
30
|
# 预设本体现在由 `presets/clearai/clearai.patch.yml` 承载(构建期由 preset/agent.cordis.yml
|
|
31
|
-
# 生成,经 package.json 的 `dsh.bundle.patch` 数组挂上)
|
|
32
|
-
# `clearai-dsh seed`
|
|
31
|
+
# 生成,经 package.json 的 `dsh.bundle.patch` 数组挂上)。想改预设的人:把声明行复制一份、
|
|
32
|
+
# 换一个 id,作为自己的 bundle patch 装(`clearai-dsh seed` 那条播种到用户根的路已随旧名册删掉)。
|
package/lib/client.js
CHANGED
|
@@ -185,8 +185,8 @@ window.__ModuleLoader__.load({
|
|
|
185
185
|
|
|
186
186
|
/** 语言命名空间。表按**源文**索引:键就是中文原文,所以漏翻译一条只会退回中文,不会把 key 显示给人。 */
|
|
187
187
|
const LOCALE_NS = 'clearai'
|
|
188
|
-
const LOCALE_ZH = {":":":"," · 改过 ":" · 改过 "," · 最近一次修订的独立裁决:":" · 最近一次修订的独立裁决:"," 次":" 次"," 次评估者":" 次评估者"," 步":" 步"," 步)":" 步)"," 看核验记录":" 看核验记录"," 看核验过程":" 看核验过程"," 轮":" 轮","(点一下开右栏「世界树」)":"(点一下开右栏「世界树」)","(点一下开右栏「世界树」看拓扑)":"(点一下开右栏「世界树」看拓扑)","(缺)":"(缺)","clearai 面板:右栏页签类型注册失败 ":"clearai 面板:右栏页签类型注册失败 ","clearai-loop: 席位跟着会话预设进出":"clearai-loop: 席位跟着会话预设进出","」相关的":"」相关的","一句话":"一句话","一步检验":"一步检验","上位":"上位","下一步:找一步去检验它":"下一步:找一步去检验它","下一步:换个办法再检验":"下一步:换个办法再检验","下一步:独立核验通过 → 已验证":"下一步:独立核验通过 → 已验证","下一步:结案时写进长期知识":"下一步:结案时写进长期知识","下位":"下位","不确定":"不确定","世界树":"世界树","主语":"主语","事实":"事实","产物":"产物","人撤回":"人撤回","人放行":"人放行","代码":"代码","依据":"依据","值的形态":"值的形态","做什么":"做什么","入本体":"入本体","全屏":"全屏","全文在 ":"全文在 ","公式":"公式","关系":"关系","关闭":"关闭","写进长期知识":"写进长期知识","出自":"出自","切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)":"切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)","判据":"判据","判据:":"判据:","判断":"判断","原生预览打开它":"原生预览打开它","原生预览打开它(计划声明的产物)":"原生预览打开它(计划声明的产物)","取不到":"取不到","取值":"取值","只看与「":"只看与「","只看相关":"只看相关","可信度怎么变的":"可信度怎么变的","可复算":"可复算","命题":"命题","图组件不可用":"图组件不可用","在图上找它":"在图上找它","在检验这一站被推翻,不再往下走。":"在检验这一站被推翻,不再往下走。","实体图":"实体图","实体图还空着。":"实体图还空着。","实例":"实例","审批记录":"审批记录","已交付":"已交付","已作废":"已作废","已推翻":"已推翻","已提出":"已提出","已收尾 · 存档可看":"已收尾 · 存档可看","已替换":"已替换","已被替换,不再往下走。":"已被替换,不再往下走。","已验证":"已验证","引用":"引用","引用已有材料":"引用已有材料","待推进":"待推进","待核验":"待核验","打开「本体」那一格并展开这条结论":"打开「本体」那一格并展开这条结论","打开目标文档(原生预览)":"打开目标文档(原生预览)","打开计划文档(原生预览)":"打开计划文档(原生预览)","推翻":"推翻","提出":"提出","支持":"支持","收起":"收起","收起详情":"收起详情","放行":"放行","数值":"数值","暂无计划。建立后此处显示计划的步骤与闸门。":"暂无计划。建立后此处显示计划的步骤与闸门。","有 ":"有 ","有矛盾":"有矛盾","未声明":"未声明","本体":"本体","本体图":"本体图","查看此步骤的证据":"查看此步骤的证据","查看步骤详情":"查看步骤详情","查看评估者":"查看评估者","检验":"检验","检验结果:":"检验结果:","概念":"概念","正在取…":"正在取…","正在裁决":"正在裁决","步 ":"步 ","清除":"清除","点击查看详情":"点击查看详情","点开看进度和来历":"点开看进度和来历","状态":"状态","独立核验":"独立核验","独立核验:":"独立核验:","用到它的结论":"用到它的结论","盘上没有这个文件":"盘上没有这个文件","目标":"目标","相关":"相关","看核验":"看核验","看记录":"看记录","矛盾":"矛盾","第 n 步":"第 n 步","算错":"算错","类型":"类型","结论":"结论","结论照常可读。":"结论照常可读。","背景(不参与判定):":"背景(不参与判定):","自己推了一遍":"自己推了一遍","自己检验":"自己检验","范围":"范围","范围:":"范围:","补充":"补充","观测":"观测","计划":"计划","计划 ":"计划 ","计划受阻,等人处置":"计划受阻,等人处置","计划已交付 ":"计划已交付 ","计划已收尾(":"计划已收尾(","计划文档":"计划文档","计划的步骤与闸门":"计划的步骤与闸门","证据":"证据","评 ":"评 ","评估":"评估","评估卡":"评估卡","起过 ":"起过 ","还没有内容。发第一条消息后,这里显示本体图和结论。":"还没有内容。发第一条消息后,这里显示本体图和结论。","还没有立目标":"还没有立目标","还没有结论。模型立下判断之后,这里一行一条。":"还没有结论。模型立下判断之后,这里一行一条。","这一项已经不在当前的词里了(可能刚被废止)。":"这一项已经不在当前的词里了(可能刚被废止)。","这个词已废止,旧结论里的用法照样可读。":"这个词已废止,旧结论里的用法照样可读。","进度":"进度","退出全屏":"退出全屏","适配":"适配","释义":"释义","待处理":"待处理","待处理 ":"待处理 ","验证":"验证","验证中":"验证中","展开下一层":"展开下一层","收起下一层":"收起下一层","本体文件有 ":"本体文件有 "," 处问题(这些不进图)":" 处问题(这些不进图)"," 个断言的主语还没写成实体文件。":" 个断言的主语还没写成实体文件。","clear/ontology/entities/ 下的实体文件、写进长期知识的断言会出现在这里。":"clear/ontology/entities/ 下的实体文件、写进长期知识的断言会出现在这里。","本体图还空着。模型在 clear/ontology/concepts/ 和 relations/ 下写概念与关系文件之后,它们会长在这里。":"本体图还空着。模型在 clear/ontology/concepts/ 和 relations/ 下写概念与关系文件之后,它们会长在这里。"}
|
|
189
|
-
const LOCALE_EN = {":":": "," · 改过 ":" · changed "," · 最近一次修订的独立裁决:":" · latest revision decided by an independent verdict: "," 次":" times"," 次评估者":" evaluators"," 步":" steps"," 步)":" steps)"," 看核验记录":" Review record"," 看核验过程":" Watch the review"," 轮":" rounds","(点一下开右栏「世界树」)":" (click to open the World Tree)","(点一下开右栏「世界树」看拓扑)":" (click to see the steps in the World Tree)","(缺)":" (missing)","clearai 面板:右栏页签类型注册失败 ":"clearai panel: failed to register the right-sidebar tab type ","clearai-loop: 席位跟着会话预设进出":"clearai-loop: seats come and go with the session's preset","」相关的":"\"","一句话":"Statement","一步检验":"A test","上位":"Broader","下一步:找一步去检验它":"Next: test it in a step","下一步:换个办法再检验":"Next: test it another way","下一步:独立核验通过 → 已验证":"Next: independent check passes → Verified","下一步:结案时写进长期知识":"Next: written to long-term knowledge at close","下位":"Narrower","不确定":"Uncertain","世界树":"World Tree","主语":"Subject","事实":"Facts","产物":"Deliverables","人撤回":"Withdrawn by a person","人放行":"Released by a person","代码":"Code","依据":"Basis","值的形态":"Value form","做什么":"What it does","入本体":"In ontology","全屏":"Full screen","全文在 ":"Full text at ","公式":"Formula","关系":"Relation","关闭":"Close","写进长期知识":"Written to long-term knowledge","出自":"From","切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)":"Switch back to an earlier World Tree (the plans are all still here, and their documents are archived under clear/goals/plans/)","判据":"Criterion","判据:":"Criterion: ","判断":"Judgment","原生预览打开它":"Open it in the native preview","原生预览打开它(计划声明的产物)":"Open it in the native preview (an artifact declared by the plan)","取不到":"Unavailable","取值":"Value","只看与「":"Only related to \"","只看相关":"Only related","可信度怎么变的":"How trust changed","可复算":"Reproducible","命题":"Propositions","图组件不可用":"The graph component is unavailable","在图上找它":"Find it on the graph","在检验这一站被推翻,不再往下走。":"Refuted at the test stage; it goes no further.","实体图":"Entity graph","实体图还空着。":"The entity graph is empty. ","实例":"Instances","审批记录":"approval record","已交付":"delivered","已作废":"voided","已推翻":"Refuted","已提出":"proposed","已收尾 · 存档可看":"closed · archived and readable","已替换":"Replaced","已被替换,不再往下走。":"Replaced; it goes no further.","已验证":"Verified","引用":"Reference","引用已有材料":"Cites existing material","待推进":"to advance","待核验":"Awaiting check","打开「本体」那一格并展开这条结论":"Open the Ontology pane and expand this conclusion","打开目标文档(原生预览)":"Open the goal document (native preview)","打开计划文档(原生预览)":"Open the plan document (native preview)","推翻":"Refute","提出":"Proposed","支持":"Support","收起":"Collapse","收起详情":"Collapse details","放行":"release","数值":"Quantity","暂无计划。建立后此处显示计划的步骤与闸门。":"No plan yet. Once created, its steps show here.","有 ":"","有矛盾":"Conflicting","未声明":"not declared","本体":"Ontology","本体图":"Ontology graph","查看此步骤的证据":"see the evidence for this step","查看步骤详情":"view step details","查看评估者":"view evaluator","检验":"Test","检验结果:":"Result: ","概念":"concepts","正在取…":"Loading…","正在裁决":"Deciding","步 ":"step ","清除":"Clear","点击查看详情":"click for details","点开看进度和来历":"Open to see progress and history","状态":"Status","独立核验":"Independent check","独立核验:":"Independent check: ","用到它的结论":"Conclusions using it","盘上没有这个文件":"this file is not on disk","目标":"Goal","相关":"Related","看核验":"See check","看记录":"See record","矛盾":"Conflicts","第 n 步":"Step n","算错":"Wrong if","类型":"Type","结论":"CONCLUSIONS","结论照常可读。":"conclusions are still readable.","背景(不参与判定):":"Background (not part of the verdict): ","自己推了一遍":"Reasoned through alone","自己检验":"Self-tested","范围":"Scope","范围:":"Scope: ","补充":"More","观测":"Observation","计划":"Plan","计划 ":"Plan ","计划受阻,等人处置":"plan blocked, waiting for a person","计划已交付 ":"Plan delivered ","计划已收尾(":"Plan closed (","计划文档":"Plan document","计划的步骤与闸门":"Plan steps","证据":"Evidence","评 ":"E","评估":"Evaluation","评估卡":"evaluation card","起过 ":"ran ","还没有内容。发第一条消息后,这里显示本体图和结论。":"Nothing yet. After the first message, the graph and conclusions show here.","还没有立目标":"No goal yet","还没有结论。模型立下判断之后,这里一行一条。":"No conclusions yet. Each judgment gets one line here.","这一项已经不在当前的词里了(可能刚被废止)。":"This item is no longer in the vocabulary (it may have just been deprecated).","这个词已废止,旧结论里的用法照样可读。":"This term is deprecated; older conclusions still read fine.","进度":"Progress","退出全屏":"Exit full screen","适配":"Fit","释义":"Gloss","待处理":"To handle","待处理 ":"to handle ","验证":"Verification","验证中":"Testing","展开下一层":"Expand the next level","收起下一层":"Collapse the next level","本体文件有 ":"Ontology files have "," 处问题(这些不进图)":" problems (these stay off the graph)"," 个断言的主语还没写成实体文件。":" assertion subjects have no entity file yet. ","clear/ontology/entities/ 下的实体文件、写进长期知识的断言会出现在这里。":"Entity files under clear/ontology/entities/ and assertions in long-term knowledge appear here.","本体图还空着。模型在 clear/ontology/concepts/ 和 relations/ 下写概念与关系文件之后,它们会长在这里。":"The ontology graph is empty. Concepts and relations appear once the model writes files under clear/ontology/concepts/ and relations/."}
|
|
188
|
+
const LOCALE_ZH = {":":":"," · 改过 ":" · 改过 "," · 最近一次修订的独立裁决:":" · 最近一次修订的独立裁决:"," 次":" 次"," 次评估者":" 次评估者"," 步":" 步"," 步)":" 步)"," 看核验记录":" 看核验记录"," 看核验过程":" 看核验过程"," 轮":" 轮","(点一下开右栏「世界树」)":"(点一下开右栏「世界树」)","(点一下开右栏「世界树」看拓扑)":"(点一下开右栏「世界树」看拓扑)","(缺)":"(缺)","clearai 面板:右栏页签类型注册失败 ":"clearai 面板:右栏页签类型注册失败 ","clearai-loop: 席位跟着会话预设进出":"clearai-loop: 席位跟着会话预设进出","」相关的":"」相关的","一句话":"一句话","一步检验":"一步检验","上位":"上位","下一步:找一步去检验它":"下一步:找一步去检验它","下一步:换个办法再检验":"下一步:换个办法再检验","下一步:独立核验通过 → 已验证":"下一步:独立核验通过 → 已验证","下一步:结案时写进长期知识":"下一步:结案时写进长期知识","下位":"下位","不确定":"不确定","世界树":"世界树","主语":"主语","事实":"事实","产物":"产物","人撤回":"人撤回","人放行":"人放行","代码":"代码","依据":"依据","值的形态":"值的形态","做什么":"做什么","入本体":"入本体","全屏":"全屏","全文在 ":"全文在 ","公式":"公式","关系":"关系","关闭":"关闭","写进长期知识":"写进长期知识","出自":"出自","切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)":"切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)","判据":"判据","判据:":"判据:","判断":"判断","原生预览打开它":"原生预览打开它","原生预览打开它(计划声明的产物)":"原生预览打开它(计划声明的产物)","取不到":"取不到","取值":"取值","只看与「":"只看与「","只看相关":"只看相关","可信度怎么变的":"可信度怎么变的","可复算":"可复算","命题":"命题","图组件不可用":"图组件不可用","在图上找它":"在图上找它","在检验这一站被推翻,不再往下走。":"在检验这一站被推翻,不再往下走。","实体图":"实体图","实体图还空着。":"实体图还空着。","实例":"实例","审批记录":"审批记录","已交付":"已交付","已作废":"已作废","已推翻":"已推翻","已提出":"已提出","已收尾 · 存档可看":"已收尾 · 存档可看","已替换":"已替换","已被替换,不再往下走。":"已被替换,不再往下走。","已验证":"已验证","引用":"引用","引用已有材料":"引用已有材料","待推进":"待推进","待核验":"待核验","打开「本体」那一格并展开这条结论":"打开「本体」那一格并展开这条结论","打开目标文档(原生预览)":"打开目标文档(原生预览)","打开计划文档(原生预览)":"打开计划文档(原生预览)","推翻":"推翻","提出":"提出","支持":"支持","收起":"收起","收起详情":"收起详情","放行":"放行","未解释":"未解释","数值":"数值","暂无计划。建立后此处显示计划的步骤与闸门。":"暂无计划。建立后此处显示计划的步骤与闸门。","有 ":"有 ","有矛盾":"有矛盾","未声明":"未声明","本体":"本体","本体图":"本体图","查看此步骤的证据":"查看此步骤的证据","查看步骤详情":"查看步骤详情","查看评估者":"查看评估者","检验":"检验","检验结果:":"检验结果:","概念":"概念","正在取…":"正在取…","正在裁决":"正在裁决","步 ":"步 ","清除":"清除","点击查看详情":"点击查看详情","点开看进度和来历":"点开看进度和来历","状态":"状态","独立核验":"独立核验","独立核验:":"独立核验:","用到它的结论":"用到它的结论","盘上没有这个文件":"盘上没有这个文件","目标":"目标","相关":"相关","看核验":"看核验","看记录":"看记录","矛盾":"矛盾","第 n 步":"第 n 步","算错":"算错","类型":"类型","结论":"结论","结论照常可读。":"结论照常可读。","背景(不参与判定):":"背景(不参与判定):","自己推了一遍":"自己推了一遍","自己检验":"自己检验","范围":"范围","范围:":"范围:","补充":"补充","观测":"观测","计划":"计划","计划 ":"计划 ","计划受阻,等人处置":"计划受阻,等人处置","计划已交付 ":"计划已交付 ","计划已收尾(":"计划已收尾(","计划文档":"计划文档","计划的步骤与闸门":"计划的步骤与闸门","证据":"证据","评 ":"评 ","评估":"评估","评估卡":"评估卡","起过 ":"起过 ","还没有内容。发第一条消息后,这里显示本体图和结论。":"还没有内容。发第一条消息后,这里显示本体图和结论。","还没有立目标":"还没有立目标","还没有结论。模型立下判断之后,这里一行一条。":"还没有结论。模型立下判断之后,这里一行一条。","这一项已经不在当前的词里了(可能刚被废止)。":"这一项已经不在当前的词里了(可能刚被废止)。","这个词已废止,旧结论里的用法照样可读。":"这个词已废止,旧结论里的用法照样可读。","进度":"进度","退出全屏":"退出全屏","适配":"适配","释义":"释义","待处理":"待处理","待处理 ":"待处理 ","验证":"验证","验证中":"验证中","展开下一层":"展开下一层","收起下一层":"收起下一层","本体文件有 ":"本体文件有 "," 处问题(这些不进图)":" 处问题(这些不进图)"," 个断言的主语还没写成实体文件。":" 个断言的主语还没写成实体文件。","clear/ontology/entities/ 下的实体文件、写进长期知识的断言会出现在这里。":"clear/ontology/entities/ 下的实体文件、写进长期知识的断言会出现在这里。","本体图还空着。模型在 clear/ontology/concepts/ 和 relations/ 下写概念与关系文件之后,它们会长在这里。":"本体图还空着。模型在 clear/ontology/concepts/ 和 relations/ 下写概念与关系文件之后,它们会长在这里。"}
|
|
189
|
+
const LOCALE_EN = {":":": "," · 改过 ":" · changed "," · 最近一次修订的独立裁决:":" · latest revision decided by an independent verdict: "," 次":" times"," 次评估者":" evaluators"," 步":" steps"," 步)":" steps)"," 看核验记录":" Review record"," 看核验过程":" Watch the review"," 轮":" rounds","(点一下开右栏「世界树」)":" (click to open the World Tree)","(点一下开右栏「世界树」看拓扑)":" (click to see the steps in the World Tree)","(缺)":" (missing)","clearai 面板:右栏页签类型注册失败 ":"clearai panel: failed to register the right-sidebar tab type ","clearai-loop: 席位跟着会话预设进出":"clearai-loop: seats come and go with the session's preset","」相关的":"\"","一句话":"Statement","一步检验":"A test","上位":"Broader","下一步:找一步去检验它":"Next: test it in a step","下一步:换个办法再检验":"Next: test it another way","下一步:独立核验通过 → 已验证":"Next: independent check passes → Verified","下一步:结案时写进长期知识":"Next: written to long-term knowledge at close","下位":"Narrower","不确定":"Uncertain","世界树":"World Tree","主语":"Subject","事实":"Facts","产物":"Deliverables","人撤回":"Withdrawn by a person","人放行":"Released by a person","代码":"Code","依据":"Basis","值的形态":"Value form","做什么":"What it does","入本体":"In ontology","全屏":"Full screen","全文在 ":"Full text at ","公式":"Formula","关系":"Relation","关闭":"Close","写进长期知识":"Written to long-term knowledge","出自":"From","切回历史的世界树(计划都还在,文档也归档在 clear/goals/plans/)":"Switch back to an earlier World Tree (the plans are all still here, and their documents are archived under clear/goals/plans/)","判据":"Criterion","判据:":"Criterion: ","判断":"Judgment","原生预览打开它":"Open it in the native preview","原生预览打开它(计划声明的产物)":"Open it in the native preview (an artifact declared by the plan)","取不到":"Unavailable","取值":"Value","只看与「":"Only related to \"","只看相关":"Only related","可信度怎么变的":"How trust changed","可复算":"Reproducible","命题":"Propositions","图组件不可用":"The graph component is unavailable","在图上找它":"Find it on the graph","在检验这一站被推翻,不再往下走。":"Refuted at the test stage; it goes no further.","实体图":"Entity graph","实体图还空着。":"The entity graph is empty. ","实例":"Instances","审批记录":"approval record","已交付":"delivered","已作废":"voided","已推翻":"Refuted","已提出":"proposed","已收尾 · 存档可看":"closed · archived and readable","已替换":"Replaced","已被替换,不再往下走。":"Replaced; it goes no further.","已验证":"Verified","引用":"Reference","引用已有材料":"Cites existing material","待推进":"to advance","待核验":"Awaiting check","打开「本体」那一格并展开这条结论":"Open the Ontology pane and expand this conclusion","打开目标文档(原生预览)":"Open the goal document (native preview)","打开计划文档(原生预览)":"Open the plan document (native preview)","推翻":"Refute","提出":"Proposed","支持":"Support","收起":"Collapse","收起详情":"Collapse details","放行":"release","未解释":"Unexplained","数值":"Quantity","暂无计划。建立后此处显示计划的步骤与闸门。":"No plan yet. Once created, its steps show here.","有 ":"","有矛盾":"Conflicting","未声明":"not declared","本体":"Ontology","本体图":"Ontology graph","查看此步骤的证据":"see the evidence for this step","查看步骤详情":"view step details","查看评估者":"view evaluator","检验":"Test","检验结果:":"Result: ","概念":"concepts","正在取…":"Loading…","正在裁决":"Deciding","步 ":"step ","清除":"Clear","点击查看详情":"click for details","点开看进度和来历":"Open to see progress and history","状态":"Status","独立核验":"Independent check","独立核验:":"Independent check: ","用到它的结论":"Conclusions using it","盘上没有这个文件":"this file is not on disk","目标":"Goal","相关":"Related","看核验":"See check","看记录":"See record","矛盾":"Conflicts","第 n 步":"Step n","算错":"Wrong if","类型":"Type","结论":"CONCLUSIONS","结论照常可读。":"conclusions are still readable.","背景(不参与判定):":"Background (not part of the verdict): ","自己推了一遍":"Reasoned through alone","自己检验":"Self-tested","范围":"Scope","范围:":"Scope: ","补充":"More","观测":"Observation","计划":"Plan","计划 ":"Plan ","计划受阻,等人处置":"plan blocked, waiting for a person","计划已交付 ":"Plan delivered ","计划已收尾(":"Plan closed (","计划文档":"Plan document","计划的步骤与闸门":"Plan steps","证据":"Evidence","评 ":"E","评估":"Evaluation","评估卡":"evaluation card","起过 ":"ran ","还没有内容。发第一条消息后,这里显示本体图和结论。":"Nothing yet. After the first message, the graph and conclusions show here.","还没有立目标":"No goal yet","还没有结论。模型立下判断之后,这里一行一条。":"No conclusions yet. Each judgment gets one line here.","这一项已经不在当前的词里了(可能刚被废止)。":"This item is no longer in the vocabulary (it may have just been deprecated).","这个词已废止,旧结论里的用法照样可读。":"This term is deprecated; older conclusions still read fine.","进度":"Progress","退出全屏":"Exit full screen","适配":"Fit","释义":"Gloss","待处理":"To handle","待处理 ":"to handle ","验证":"Verification","验证中":"Testing","展开下一层":"Expand the next level","收起下一层":"Collapse the next level","本体文件有 ":"Ontology files have "," 处问题(这些不进图)":" problems (these stay off the graph)"," 个断言的主语还没写成实体文件。":" assertion subjects have no entity file yet. ","clear/ontology/entities/ 下的实体文件、写进长期知识的断言会出现在这里。":"Entity files under clear/ontology/entities/ and assertions in long-term knowledge appear here.","本体图还空着。模型在 clear/ontology/concepts/ 和 relations/ 下写概念与关系文件之后,它们会长在这里。":"The ontology graph is empty. Concepts and relations appear once the model writes files under clear/ontology/concepts/ and relations/."}
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
192
|
* 翻译函数:**由原生 locale 座位绑定**(`ctx.locale.bind`),不是我们自建的一套 i18n。
|
|
@@ -607,6 +607,7 @@ window.__ModuleLoader__.load({
|
|
|
607
607
|
evidence: t('证据'),
|
|
608
608
|
fact: t('事实'),
|
|
609
609
|
release: t('放行'),
|
|
610
|
+
anomaly: t('未解释'),
|
|
610
611
|
}))
|
|
611
612
|
|
|
612
613
|
/**
|
|
@@ -747,7 +748,7 @@ window.__ModuleLoader__.load({
|
|
|
747
748
|
*/
|
|
748
749
|
const TRUST_ORDER = ['credible', 'pending', 'testing', 'unclear', 'refuted', 'replaced']
|
|
749
750
|
const TRUST_WORD = lazyTable(() => ({ credible: t('已验证'), pending: t('待核验'), testing: t('验证中'), unclear: t('不确定'), refuted: t('已推翻'), replaced: t('已替换') }))
|
|
750
|
-
const LEVEL_WORD = lazyTable(() => ({ L0: t('
|
|
751
|
+
const LEVEL_WORD = lazyTable(() => ({ L0: t('自己检验'), L1: t('自己检验'), L2: t('自己检验'), L3: t('独立核验'), L4: t('人放行') }))
|
|
751
752
|
/** 进度轨的四站。顺序即一条结论要走的路。 */
|
|
752
753
|
const STATIONS = () => [t('判断'), t('检验'), t('已验证'), t('入本体')]
|
|
753
754
|
/** 还没走完时,下一步是什么(时间线末尾那条虚点)。 */
|