clearai-dsh 0.3.0 → 0.3.1
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 +15 -0
- package/README.md +4 -4
- package/README.zh-CN.md +4 -4
- package/lib/fold.js +2 -0
- package/package.json +1 -1
- package/presets/clearai/plugins/clearai-kernel.js +30 -5
- package/presets/clearai/skills/clearai-loop/SKILL.md +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
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
|
+
## [0.3.1] — 2026-09-29
|
|
6
|
+
|
|
7
|
+
**两个死结:计划置 blocked 后再也解不开,续跑窗口的阻塞码收不了兵。** 两条都不是措辞问题,是机制自己在文档承诺的出口上焊死了——0.3.0 的「连拦达阈值 ⇒ 置 blocked、停下等人」写得没错,可人按卡上说的三条出路走,一条也走不出去。
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`block/cleared` 只清了连拦计数,没清 `plan.blocked`**:计划一旦置 blocked,`AmendPlan`(换一条能过闸的路)与 `RefinePlan`(补齐判据)把话说得再对也解不开,`plan.blocked` 会一直挂着,收件箱那条等人处置的条目成了死结。现在 `block/cleared` 同时删掉 `blocks[plan:step]` 与指向该步的 `plan.blocked`;三条出路各自**真的**能解拦——`AmendPlan`、`RefinePlan`,以及 `VoidPlanStep`(只作废被拦的那一步时才清)。阻塞守卫的文案也随之只列**可执行**的动词(去掉「让人介入后重开」,补上 `VoidPlanStep`)。
|
|
12
|
+
- **续跑窗口的阻塞码用了下划线**:`clearai_loop_stalled` / `clearai_loop_abandoned` 不合宿主契约 —— `@deepseek-ai/dsh-goal` 要求 lower-kebab-case(`/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/`),`goals.block(...)` 当场拒收 ⇒ 收兵失败,窗口留在 `active` 上继续叫醒一个已经收尾的目标。现在改成 `clearai-loop-stalled` / `clearai-loop-abandoned`。测试桩 `makeHost().block` 也按同一条宿主规则抛错——桩与宿主同形,不然测的只是桩。
|
|
13
|
+
- **目录被声明成物证时报「空目录」**:目录不是空文件,两件事不一样,而错的那句话会把下一步动作指错。准入现在把目录**单独判为不可作为物证**(`verified_by: 'l1'`),并如实报出目录里的**文件数与字节数**;`CreatePlan` 的 `artifacts` 契约描述与 `clearai-loop` 技能文档同步写明「目录不是物证,要声明具体文件」。
|
|
14
|
+
|
|
15
|
+
### Verified
|
|
16
|
+
|
|
17
|
+
- **18 套件 1886 项检查全绿**(内核 834 · 宿主 119 · 客户端 248 · 领域语言 234 · 本体 96 · 长测 41 · 对照 41 · 可读性 35 …);`verify-package` 44 通过 / 1 失败,唯一那条仍是沙箱里 `npm pack` 的 `EROFS`(只读 `~/.npm/_cacache`),与 0.3.0 记录的是同一处环境限制。
|
|
18
|
+
- 续跑码那一条是**拿真宿主的契约核过**的:`node_modules/@deepseek-ai/dsh-goal/lib/index.js` 里就是那条 lower-kebab-case 正则,不是照着测试桩猜的。
|
|
19
|
+
|
|
5
20
|
## [0.3.0] — 2026-09-29
|
|
6
21
|
|
|
7
22
|
**从一次真跑的三条症状出发,把三件事从劝告变成机制。** 一位用户在真实会话里遇到的三个问题——`CloseGoal` 运行失败且要跑很久;命题晦涩、而且**从没走过认识论循环的便宜层级**;本体建得不错、**查到的实体却没进实体图谱**——每一条都追到了代码行:宿主半用**属性式**取服务(宿主 fiber 瞬态掉线就抛,而评估者刚跑完的那两分钟评审随栈帧一起没了);实体层的节点与边**唯一**来自「整条目标被独立裁决判 support」之后的升格;`supportedLevel` 只是支持证据的最大值,跳级**零代价**。这一版不是把话说重一点,而是把这三条各自换成一道**可清点的机制**——并在两场真模型 headless 长测里验过。
|
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.3.
|
|
26
|
-
# or in the app: Plugins → Add plugin → clearai-dsh@0.3.
|
|
25
|
+
dsh plugin --profile web add clearai-dsh@0.3.1
|
|
26
|
+
# or in the app: Plugins → Add plugin → clearai-dsh@0.3.1
|
|
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)
|
|
@@ -78,12 +78,12 @@ ClearAI does **not** claim recursive self-improvement. It provides the epistemic
|
|
|
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.3.
|
|
81
|
+
In the sidebar open **Plugins → Add plugin**, enter `clearai-dsh@0.3.1`, 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.3.
|
|
86
|
+
dsh plugin --profile web add clearai-dsh@0.3.1
|
|
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.
|
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.3.
|
|
26
|
-
# 或在应用里:侧栏「插件」→ 添加插件 → clearai-dsh@0.3.
|
|
25
|
+
dsh plugin --profile web add clearai-dsh@0.3.1
|
|
26
|
+
# 或在应用里:侧栏「插件」→ 添加插件 → clearai-dsh@0.3.1
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
重启 `dsh web`,在新建会话顶部的模式选择器里选 **ClearAI** 即可。这就是全部步骤。[完整安装说明 ↓](#安装与使用)
|
|
@@ -78,12 +78,12 @@ ClearAI **不**声称递归自我改进。它提供的是自我改进系统所
|
|
|
78
78
|
|
|
79
79
|
**推荐——在应用里装,并把版本钉住:**
|
|
80
80
|
|
|
81
|
-
侧栏打开**「插件」→ 添加插件**,填 `clearai-dsh@0.3.
|
|
81
|
+
侧栏打开**「插件」→ 添加插件**,填 `clearai-dsh@0.3.1`,安装。这就是 DSH 自己的插件管理器:它把你填的东西交给 pnpm,校验这个包声明了组合包、与当前宿主兼容,然后当场生效。(设置里的**插件列表**是**只读清单**;安装入口在侧栏那个「插件」页。)
|
|
82
82
|
|
|
83
83
|
**或者开终端——同一次安装:**
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
|
-
dsh plugin --profile web add clearai-dsh@0.3.
|
|
86
|
+
dsh plugin --profile web add clearai-dsh@0.3.1
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
从 npm registry 装预构建产物。本机不跑任何编译,因此不需要批准 `allowBuilds` 授权——命令返回时插件就已经可用。
|
package/lib/fold.js
CHANGED
|
@@ -489,6 +489,8 @@ export function applyMutation(state, mutation) {
|
|
|
489
489
|
}
|
|
490
490
|
case 'block/cleared': {
|
|
491
491
|
delete next.blocks[`${mutation.plan}:${mutation.step}`]
|
|
492
|
+
const plan = planOf(mutation.plan)
|
|
493
|
+
if (plan?.blocked?.step === mutation.step) plan.blocked = undefined
|
|
492
494
|
break
|
|
493
495
|
}
|
|
494
496
|
case 'observation/recorded': {
|
package/package.json
CHANGED
|
@@ -893,7 +893,7 @@ export function apply(ctx, config = {}) {
|
|
|
893
893
|
// 判定树:l1 / l2 / no_anchor / invalid / needs_audit。
|
|
894
894
|
|
|
895
895
|
function admission(cwd, step, artifactsOverride) {
|
|
896
|
-
const result = { ok: false, verified_by: 'invalid', missing: [], empty: [], structural: [], confirmed: [], needs_audit: false, hint: '' }
|
|
896
|
+
const result = { ok: false, verified_by: 'invalid', missing: [], directories: [], empty: [], structural: [], confirmed: [], needs_audit: false, hint: '' }
|
|
897
897
|
if (step === null || typeof step !== 'object') {
|
|
898
898
|
result.missing.push('step')
|
|
899
899
|
return result
|
|
@@ -928,7 +928,24 @@ export function apply(ctx, config = {}) {
|
|
|
928
928
|
continue
|
|
929
929
|
}
|
|
930
930
|
if (stat.isDirectory()) {
|
|
931
|
-
|
|
931
|
+
let files = 0
|
|
932
|
+
let bytes = 0
|
|
933
|
+
const countContents = (directory) => {
|
|
934
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
935
|
+
const entryPath = join(directory, entry.name)
|
|
936
|
+
if (entry.isDirectory()) countContents(entryPath)
|
|
937
|
+
else if (entry.isFile()) {
|
|
938
|
+
files += 1
|
|
939
|
+
bytes += statSync(entryPath).size
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
try {
|
|
944
|
+
countContents(absolute)
|
|
945
|
+
} catch {
|
|
946
|
+
// 目录在读数期间变化时,仍如实说明它不能作为物证。
|
|
947
|
+
}
|
|
948
|
+
result.directories.push(`${artifact}(目录不是物证,含 ${files} 个文件、${bytes} 字节)`)
|
|
932
949
|
continue
|
|
933
950
|
}
|
|
934
951
|
if (stat.size === 0) {
|
|
@@ -963,6 +980,11 @@ export function apply(ctx, config = {}) {
|
|
|
963
980
|
result.hint = `声明的产物没落盘:${result.missing.join(', ')}。三条合法出路:①把产物做出来;②改声明(RefinePlan 改判据、AmendPlan 换产物);③带因作废(VoidPlanStep)。`
|
|
964
981
|
return result
|
|
965
982
|
}
|
|
983
|
+
if (result.directories.length > 0) {
|
|
984
|
+
result.verified_by = 'l1'
|
|
985
|
+
result.hint = `声明的产物是目录:${result.directories.join(', ')}。目录不是物证,请在 artifacts 声明具体文件。`
|
|
986
|
+
return result
|
|
987
|
+
}
|
|
966
988
|
if (result.empty.length > 0) {
|
|
967
989
|
result.verified_by = 'l1'
|
|
968
990
|
result.hint = `产物存在但是空:${result.empty.join(', ')}。空文件不是观测。`
|
|
@@ -2496,7 +2518,7 @@ export function apply(ctx, config = {}) {
|
|
|
2496
2518
|
// 为什么必须是**机制**而不是嘱咐:ClearAI 的无人值守档靠「系统自己开下一阶段」活着,
|
|
2497
2519
|
// 而 DSH 里一个回合结束后想让会话继续,只有宿主的回合驱动能做到。模型自己说"我继续"是无力的。
|
|
2498
2520
|
|
|
2499
|
-
const CONTINUATION_CODES = { stalled: '
|
|
2521
|
+
const CONTINUATION_CODES = { stalled: 'clearai-loop-stalled', abandoned: 'clearai-loop-abandoned' }
|
|
2500
2522
|
|
|
2501
2523
|
/**
|
|
2502
2524
|
* 计划审阅的两个标签:它们是**机制**定义的措辞,不是模型的即兴表达。
|
|
@@ -3861,7 +3883,7 @@ export function apply(ctx, config = {}) {
|
|
|
3861
3883
|
properties: {
|
|
3862
3884
|
id: { type: 'string', description: '稳定 id(字母/数字/下划线/短横)' },
|
|
3863
3885
|
do: { type: 'string', description: '这一步做什么' },
|
|
3864
|
-
artifacts: { type: 'array', items: { type: 'string' }, description: '以何物为证:相对 workspace
|
|
3886
|
+
artifacts: { type: 'array', items: { type: 'string' }, description: '以何物为证:相对 workspace 的具体产物文件路径(目录不是物证)' },
|
|
3865
3887
|
done_criteria: { type: 'string', description: '判定标准:在结果出现之前写下,必须可核对' },
|
|
3866
3888
|
tests: {
|
|
3867
3889
|
type: 'object',
|
|
@@ -4508,6 +4530,7 @@ export function apply(ctx, config = {}) {
|
|
|
4508
4530
|
if (plan.steps.some((step) => step.id === args.step.id)) return fail('duplicate_step', `步骤 id 已存在:${args.step.id}`)
|
|
4509
4531
|
const amended = { id: args.step.id, do: args.step.do, artifacts: args.step.artifacts ?? [], done_criteria: args.step.done_criteria, tests: args.step.tests ?? null }
|
|
4510
4532
|
mutations.push({ t: 'plan/amended', plan: plan.id, step: amended })
|
|
4533
|
+
if (plan.blocked !== undefined) mutations.push({ t: 'block/cleared', plan: plan.id, step: plan.blocked.step })
|
|
4511
4534
|
/**
|
|
4512
4535
|
* **没授权的计划:改完再呈一次**(审阅卡上承诺的就是这句)。
|
|
4513
4536
|
* 已经授权的计划不再打扰人 —— 补一步不是重新立约。
|
|
@@ -4542,6 +4565,7 @@ export function apply(ctx, config = {}) {
|
|
|
4542
4565
|
const selfRef = SELF_REFERENCE.find(([pattern]) => pattern.test(criteria))
|
|
4543
4566
|
if (selfRef !== undefined) return fail('criteria_self_reference', selfRef[1])
|
|
4544
4567
|
mutations.push({ t: 'plan/refined', plan: plan.id, step: step.id, old_criteria: step.done_criteria, new_criteria: criteria, reason: args.reason ?? null })
|
|
4568
|
+
if (plan.blocked !== undefined) mutations.push({ t: 'block/cleared', plan: plan.id, step: plan.blocked.step })
|
|
4545
4569
|
const refinedSteps = plan.steps.map((item) => (item.id === step.id ? { ...item, done_criteria: criteria } : item))
|
|
4546
4570
|
const againRefined = plan.confirmed_at === null ? await reviewExistingPlan(plan, exec, mutations, refinedSteps) : { note: '' }
|
|
4547
4571
|
return done({ ok: true, code: 'plan_refined', progress_changed: false, message: `步骤 ${step.id} 的判据已精化(进度不变,旧判据留痕)。${againRefined.note}` })
|
|
@@ -4591,6 +4615,7 @@ export function apply(ctx, config = {}) {
|
|
|
4591
4615
|
if (step.status === 'advanced') return fail('step_settled', `步骤 ${step.id} 已交付,不能作废(已交付的事实不会被撤销)。`)
|
|
4592
4616
|
if (typeof args.reason !== 'string' || args.reason.trim() === '') return fail('reason_required', '作废必须带原因。')
|
|
4593
4617
|
mutations.push({ t: 'plan/voided', plan: plan.id, step: step.id, reason: args.reason.trim() })
|
|
4618
|
+
if (plan.blocked?.step === step.id) mutations.push({ t: 'block/cleared', plan: plan.id, step: step.id })
|
|
4594
4619
|
/**
|
|
4595
4620
|
* 作废**不动**分叉:作废是承诺层的权威动作,它不改变尝试层已经发生的事实
|
|
4596
4621
|
* ——那些世界线探索过、有的还出了读数。把它们改写成「已放弃」就是改写历史。
|
|
@@ -4712,7 +4737,7 @@ export function apply(ctx, config = {}) {
|
|
|
4712
4737
|
if (plan.blocked !== undefined) {
|
|
4713
4738
|
return fail(
|
|
4714
4739
|
'plan_blocked',
|
|
4715
|
-
`计划 ${plan.id} 已置 blocked(连续 ${plan.blocked.attempts} 次未过闸:${plan.blocked.reason}),停下等人。要接着做:AmendPlan 换一条能过闸的路、RefinePlan
|
|
4740
|
+
`计划 ${plan.id} 已置 blocked(连续 ${plan.blocked.attempts} 次未过闸:${plan.blocked.reason}),停下等人。要接着做:AmendPlan 换一条能过闸的路、RefinePlan 补齐判据,或 VoidPlanStep 作废被拦步骤。`,
|
|
4716
4741
|
)
|
|
4717
4742
|
}
|
|
4718
4743
|
const level = step.tests?.level ?? null
|
|
@@ -36,7 +36,7 @@ description: Use when working inside the ClearAI preset and you need the loop's
|
|
|
36
36
|
|
|
37
37
|
| 拍 | 你做什么 | 系统做什么 |
|
|
38
38
|
|---|---|---|
|
|
39
|
-
| 计划 | `CreatePlan`:每步写 `do`、`artifacts`(
|
|
39
|
+
| 计划 | `CreatePlan`:每步写 `do`、`artifacts`(以具体文件为证,目录不是物证)、`done_criteria`(判定标准) | 强制判据非空、自指检测、≤25 步、步骤 id 唯一 |
|
|
40
40
|
| 执行 | 用文件、bash、公网做实际工作;产物落盘 | 只读并行 / 写入串行;沙箱;每次写入进账 |
|
|
41
41
|
| 观察 | 拿到结果 | 登记观测(只追加) |
|
|
42
42
|
| 反思 | `AdvancePlan` 交付 | 观测准入 → 裁决 → 写证据 → 推进 |
|
|
@@ -52,7 +52,7 @@ description: Use when working inside the ClearAI preset and you need the loop's
|
|
|
52
52
|
交付时系统按这个次序检查(以当前 ClearAI DSH 内核的准入契约为准):
|
|
53
53
|
|
|
54
54
|
1. 声明的产物**存在**吗?不存在 → 硬拦 `l1`,并告诉你三条合法出路(做出来 / 改声明 / 带因作废)。
|
|
55
|
-
2.
|
|
55
|
+
2. 声明的是**目录**吗?目录不是物证;系统报告其中的文件数与字节数,改为声明具体文件。零字节文件同样硬拦:空文件不是观测。
|
|
56
56
|
3. **结构合法**吗?`.json` 必须能解析;`.md` 去掉标题行后实质文本不足 20 字符算「仅有标题」。其他扩展名不做结构判定(不误伤)。
|
|
57
57
|
4. 一个坐标都没声明 → `no_anchor` 硬拦:不改变世界的步骤没有可验收的东西。
|
|
58
58
|
5. 坐标齐备且判据非空 → **不是放行,是送评**(`needs_audit`)。
|