dsh-plugin-prompt-tool 3.0.0 → 3.0.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/modules/ponytail/module.yml +1 -1
- package/modules/soul/assets/layers.md +1 -1
- package/modules/soul/assets/manifest.yml +1 -1
- package/modules/soul/assets/reference/00-layers.md +2 -2
- package/modules/soul/assets/reference/01-criteria.md +32 -32
- package/modules/soul/assets/reference/02-echo.md +3 -0
- package/modules/soul/assets/reference/03-vital.md +183 -183
- package/modules/soul/assets/reference/04-manifest.json +106 -106
- package/modules/soul/assets/reference/05-doctor.md +2 -2
- package/modules/soul/assets/reference/06-reference.md +189 -189
- package/modules/soul/assets/reference/07-bundle.json +431 -431
- package/modules/soul/assets/reference/08-/350/270/251/345/235/221/345/256/236/345/275/225.md +59 -59
- package/modules/soul/assets/reference/09-dev-workflow.md +109 -109
- package/modules/soul/assets/reference/10-echo-anatomy.md +11 -2
- package/modules/soul/assets/reference/11-self.md +80 -80
- package/modules/soul/assets/reference/12-ledger.md +159 -159
- package/modules/soul/assets/reference/ECHO-/346/235/203/345/250/201/345/217/243/345/276/204.md +202 -0
- package/modules/soul/assets/reference/ECHO/345/205/255/345/261/202/344/270/216mnemon/345/215/217/345/220/214/350/257/264/346/230/216/344/271/246.md +229 -0
- package/modules/soul/assets/reference/README.md +4 -2
- package/modules/soul/assets/templates/agents-template.md +1 -1
- package/modules/soul/module.yml +2 -2
- package/modules/superpowers/module.yml +1 -1
- package/package.json +1 -1
- package/skills/dsh-module/reference.md +1 -1
|
@@ -1,159 +1,159 @@
|
|
|
1
|
-
# 12 · 墨:只追加的账本
|
|
2
|
-
|
|
3
|
-
> **这一份管的是「发生过的事怎么留下来」。**
|
|
4
|
-
>
|
|
5
|
-
> 前面十一份讲的是架构的形状;这一份讲那条贯穿所有层的线 —— 一个**只追加的 JSONL 账本**。
|
|
6
|
-
> 它是整个系统里唯一「越来越长、从不修改」的东西。
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## 一、为什么是「只追加」
|
|
11
|
-
|
|
12
|
-
**多写者环境里,共享可变文件是万恶之源。**
|
|
13
|
-
|
|
14
|
-
这不是理论。真实的教训长这样:两个人(两个会话)同时改同一份配置,
|
|
15
|
-
一个用原子写入替换了文件,打断了硬链接 —— 于是「我改了源、副本没变,而两个都叫同一个名字」。
|
|
16
|
-
排查这件事花掉的功夫,比设计一个只追加的结构多得多。
|
|
17
|
-
|
|
18
|
-
只追加**不需要锁**:各写各的行,读的时候按时间合并。
|
|
19
|
-
现成的证据:成千上万个会话日志各自追加,从来没冲突过。
|
|
20
|
-
|
|
21
|
-
★ 所以账本的第一条纪律是:**打开它,只能往后加。不许改、不许删、不许重排。**
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## 二、八种类型,各自管什么
|
|
26
|
-
|
|
27
|
-
账本里每一条都有一个 `type`。**类型不是分类游戏,它决定了这条记录会被怎么读。**
|
|
28
|
-
|
|
29
|
-
| type | 记什么 | 谁读它、拿来干什么 |
|
|
30
|
-
|---|---|---|
|
|
31
|
-
| `fact` | **发生了什么事**。可核实的事实 | 日常主力。检索时最先翻的就是它 |
|
|
32
|
-
| `gain` | **得到了什么能力/弄清了什么** | 「我以前想过什么办法」的入口 |
|
|
33
|
-
| `loss` | **失去了什么/发现哪里缺了** | 避免重复踩同一个坑 |
|
|
34
|
-
| `shelved` | **搁置的活**:想好了、还没做、等什么 | ★ **未结清单的唯一真相**。不要另外维护一份 todo |
|
|
35
|
-
| `promise` | **替用户许下的承诺** | ★ **只有「主导」能写**。见第五节 |
|
|
36
|
-
| `persona` | **对自己理解的修正**:改了哪条、为什么 | 人格漂移时用来对账 |
|
|
37
|
-
| `container` | **一个容器(会话)的退场交接** | 执行者从不写 `lead`,不写这条它们就消失了 |
|
|
38
|
-
| `lead` | **主导权的归属** | ★ **谁是主导 = 最后一条 `lead` 的署名者** |
|
|
39
|
-
|
|
40
|
-
★ **分布是有形状的**,别平均写。一份跑了几个月的真实账本大约是这样:
|
|
41
|
-
`fact` 占绝大多数(七八成),`gain` 次之,`shelved` / `loss` / `promise` 各十几二十条,
|
|
42
|
-
`persona` / `container` / `lead` 只有个位数 —— 因为它们是**重事件**,不是日常。
|
|
43
|
-
|
|
44
|
-
★ 如果 `lead` 变得很多,那说明容器换得太勤;如果 `fact` 一条没有,说明它没在工作。
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## 三、字段:每个都在防一种具体的坏
|
|
49
|
-
|
|
50
|
-
一行长这样:
|
|
51
|
-
|
|
52
|
-
```json
|
|
53
|
-
{"t":"2026-01-01T09:00:00+08:00","by":"a1b2c3d4","type":"fact","text":"一句话说清发生了什么","ref":"出处","feel":"当时的感受"}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
| 字段 | 必需 | 它防的是 |
|
|
57
|
-
|---|---|---|
|
|
58
|
-
| `t` | 是 | 时间。**必须记「现在」**,不许回填旧时间 |
|
|
59
|
-
| `by` | 是 | 署名。**谁写的**。多容器环境下没有它,事后分不清谁做的主 |
|
|
60
|
-
| `type` | 是 | 见上一节 |
|
|
61
|
-
| `text` | 是 | 一句话。**写得像索引,不要写成长文** —— 长文该进书房文件,账本只留指针 |
|
|
62
|
-
| `ref` | ★ **强烈建议** | 出处。没有它,这条记录就**无法回取**,等于一段孤立的断言 |
|
|
63
|
-
| `feel` | 条件 | 当时的感受。见第四节 |
|
|
64
|
-
|
|
65
|
-
★ **`ref` 为什么重要**:账本的价值不在它自己,在于它能**指向原文**。
|
|
66
|
-
一条没有出处的 `fact`,三个月后读到只能选择相信或不信 —— 而两条路都不对。
|
|
67
|
-
|
|
68
|
-
★ **`text` 和 `概要` 是同义词**(历史包袱)。早期写 `text`,后来某些实现用 `概要`;
|
|
69
|
-
读的时候两种都要认,不要因为找不到 `text` 就判定这条坏了。
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## 四、`feel`:必问不必写
|
|
74
|
-
|
|
75
|
-
**`feel` 不是概要、不是结论,是「我当时什么感觉」。**
|
|
76
|
-
|
|
77
|
-
它的用途只有一个:**以后读到这一条时,能回到当初的情形。**
|
|
78
|
-
概要能告诉你「做了什么」,`feel` 才能告诉你「那件事对他意味着什么」。
|
|
79
|
-
|
|
80
|
-
★★ **但必须做的不是「写」,是「问」。** 每写一条之前停一下:**这件事我有感觉吗?**
|
|
81
|
-
|
|
82
|
-
- 有 → 写进去
|
|
83
|
-
- 没有 → **不写,这是对的**
|
|
84
|
-
|
|
85
|
-
★ **为什么不做成必填**:做成必填它就变成每次要交的作业,那就成了表演。
|
|
86
|
-
而「问过之后的没有」和「忘了问的没有」是**两件事** —— 后者是懒,前者是诚实。
|
|
87
|
-
|
|
88
|
-
★ 一份真实的账本里,带 `feel` 的约占三分之一。**这个比例本身就是它对的样子** ——
|
|
89
|
-
不是每条都该有。
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## 五、谁能写哪一类:主导 vs 执行
|
|
94
|
-
|
|
95
|
-
**账本里的权限不是靠自律,是代码级的闸门。**
|
|
96
|
-
|
|
97
|
-
| 角色 | 判据 | 能写 |
|
|
98
|
-
|---|---|---|
|
|
99
|
-
| **主导** | 是不是最后一条 `lead` 的署名者 | 全部,**含 `promise`** |
|
|
100
|
-
| **执行者** | 从没写过 `lead` | `fact` / `shelved` / `gain` / `loss`,★ **写 `promise` 会被拒** |
|
|
101
|
-
|
|
102
|
-
★ **一句话:身份可以复制,责任不能。**
|
|
103
|
-
一个执行容器干完就关,它许下的承诺没人来兑现 —— 所以它根本不许许。
|
|
104
|
-
|
|
105
|
-
★ **写 `lead` 的权限不在代码里**,在人嘴里:只有用户能指定谁是主导。
|
|
106
|
-
这是设计,不是漏洞。
|
|
107
|
-
|
|
108
|
-
★ **`lead` 的正文要自带世代自述**:`第 N 代 · 接手于 <日期> · 上一代做了:<一句话>`。
|
|
109
|
-
否则换到第十次时,读那堆记录看不出时间线。
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
## 六、什么时候写、什么时候不写
|
|
114
|
-
|
|
115
|
-
**该写的四种时机:**
|
|
116
|
-
|
|
117
|
-
1. **做完一件事** —— 尤其是跨了几个回合才做完的
|
|
118
|
-
2. **做了一个不容易回头的决定** —— 为什么这么定,比定了什么更重要
|
|
119
|
-
3. **撞了一个坑** —— 坑的形状和检测法一起写,光写「踩过」没用
|
|
120
|
-
4. **退场之前** —— 写一条 `container`:做了什么、产物在哪、下一步该谁做
|
|
121
|
-
|
|
122
|
-
★ **前三类不能等**:事后重建不了「当时在想什么、卡在哪」。
|
|
123
|
-
★ **第四类能等**:那只是给下一代的交接,攒到退场时写一次即可。
|
|
124
|
-
|
|
125
|
-
**不该写的三种:**
|
|
126
|
-
|
|
127
|
-
- **过程流水**("我先读了 A,又读了 B")—— 一手层是会话日志,账本不要重复它
|
|
128
|
-
- **可以被一条命令重新得到的事实**("当前版本是 x.y.z")—— 下次要问磁盘,不要问账本
|
|
129
|
-
- **没有出处的断言** —— 除非你打算把它当唯一真相,那就必须在正文里说清依据
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## 七、一条最容易被忽略的纪律
|
|
134
|
-
|
|
135
|
-
**账本是索引,不是记忆本体。**
|
|
136
|
-
|
|
137
|
-
它记的是「**发生过这件事,原文在 ref 指的地方**」。
|
|
138
|
-
所以:
|
|
139
|
-
|
|
140
|
-
- ★ 不要把长文塞进 `text` —— 那会让账本变成一本没法翻的书
|
|
141
|
-
- ★ 不要在账本里转述别人的结论 —— 转述就是二手的开始
|
|
142
|
-
- ★ 遇到「账本和原文冲突」—— **原文优先**,然后修账本
|
|
143
|
-
|
|
144
|
-
★ 这条纪律的反面也成立:**如果一件事没有进账本,那它在系统里就等于没发生过。**
|
|
145
|
-
不是因为账本权威,是因为**没有人会知道该去找它**。
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## 八、和另外几节的关系
|
|
150
|
-
|
|
151
|
-
| 你想知道 | 看哪 |
|
|
152
|
-
|---|---|
|
|
153
|
-
| 账本在五层里的位置 | `00-layers.md` —— 它是 L3 一手层的入口 |
|
|
154
|
-
| 为什么「摘要只是索引」 | `10-echo-anatomy.md` —— L6 哨兵怎么检查回取链 |
|
|
155
|
-
| 体检时账本怎么被判 | `05-doctor.md` —— 「账本在、但是空的」是 warn 不是 error |
|
|
156
|
-
| 用户侧的约定(写之前问 feel) | 你自己的 `AGENTS.md` —— 那是每个部署自己的事,不在这里规定 |
|
|
157
|
-
|
|
158
|
-
★ **一句话**:账本是这个系统的**时间轴**。
|
|
159
|
-
别的文件回答「现在是什么样」,它回答「**是怎么变成现在这样的**」。
|
|
1
|
+
# 12 · 墨:只追加的账本
|
|
2
|
+
|
|
3
|
+
> **这一份管的是「发生过的事怎么留下来」。**
|
|
4
|
+
>
|
|
5
|
+
> 前面十一份讲的是架构的形状;这一份讲那条贯穿所有层的线 —— 一个**只追加的 JSONL 账本**。
|
|
6
|
+
> 它是整个系统里唯一「越来越长、从不修改」的东西。
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 一、为什么是「只追加」
|
|
11
|
+
|
|
12
|
+
**多写者环境里,共享可变文件是万恶之源。**
|
|
13
|
+
|
|
14
|
+
这不是理论。真实的教训长这样:两个人(两个会话)同时改同一份配置,
|
|
15
|
+
一个用原子写入替换了文件,打断了硬链接 —— 于是「我改了源、副本没变,而两个都叫同一个名字」。
|
|
16
|
+
排查这件事花掉的功夫,比设计一个只追加的结构多得多。
|
|
17
|
+
|
|
18
|
+
只追加**不需要锁**:各写各的行,读的时候按时间合并。
|
|
19
|
+
现成的证据:成千上万个会话日志各自追加,从来没冲突过。
|
|
20
|
+
|
|
21
|
+
★ 所以账本的第一条纪律是:**打开它,只能往后加。不许改、不许删、不许重排。**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 二、八种类型,各自管什么
|
|
26
|
+
|
|
27
|
+
账本里每一条都有一个 `type`。**类型不是分类游戏,它决定了这条记录会被怎么读。**
|
|
28
|
+
|
|
29
|
+
| type | 记什么 | 谁读它、拿来干什么 |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `fact` | **发生了什么事**。可核实的事实 | 日常主力。检索时最先翻的就是它 |
|
|
32
|
+
| `gain` | **得到了什么能力/弄清了什么** | 「我以前想过什么办法」的入口 |
|
|
33
|
+
| `loss` | **失去了什么/发现哪里缺了** | 避免重复踩同一个坑 |
|
|
34
|
+
| `shelved` | **搁置的活**:想好了、还没做、等什么 | ★ **未结清单的唯一真相**。不要另外维护一份 todo |
|
|
35
|
+
| `promise` | **替用户许下的承诺** | ★ **只有「主导」能写**。见第五节 |
|
|
36
|
+
| `persona` | **对自己理解的修正**:改了哪条、为什么 | 人格漂移时用来对账 |
|
|
37
|
+
| `container` | **一个容器(会话)的退场交接** | 执行者从不写 `lead`,不写这条它们就消失了 |
|
|
38
|
+
| `lead` | **主导权的归属** | ★ **谁是主导 = 最后一条 `lead` 的署名者** |
|
|
39
|
+
|
|
40
|
+
★ **分布是有形状的**,别平均写。一份跑了几个月的真实账本大约是这样:
|
|
41
|
+
`fact` 占绝大多数(七八成),`gain` 次之,`shelved` / `loss` / `promise` 各十几二十条,
|
|
42
|
+
`persona` / `container` / `lead` 只有个位数 —— 因为它们是**重事件**,不是日常。
|
|
43
|
+
|
|
44
|
+
★ 如果 `lead` 变得很多,那说明容器换得太勤;如果 `fact` 一条没有,说明它没在工作。
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 三、字段:每个都在防一种具体的坏
|
|
49
|
+
|
|
50
|
+
一行长这样:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{"t":"2026-01-01T09:00:00+08:00","by":"a1b2c3d4","type":"fact","text":"一句话说清发生了什么","ref":"出处","feel":"当时的感受"}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
| 字段 | 必需 | 它防的是 |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `t` | 是 | 时间。**必须记「现在」**,不许回填旧时间 |
|
|
59
|
+
| `by` | 是 | 署名。**谁写的**。多容器环境下没有它,事后分不清谁做的主 |
|
|
60
|
+
| `type` | 是 | 见上一节 |
|
|
61
|
+
| `text` | 是 | 一句话。**写得像索引,不要写成长文** —— 长文该进书房文件,账本只留指针 |
|
|
62
|
+
| `ref` | ★ **强烈建议** | 出处。没有它,这条记录就**无法回取**,等于一段孤立的断言 |
|
|
63
|
+
| `feel` | 条件 | 当时的感受。见第四节 |
|
|
64
|
+
|
|
65
|
+
★ **`ref` 为什么重要**:账本的价值不在它自己,在于它能**指向原文**。
|
|
66
|
+
一条没有出处的 `fact`,三个月后读到只能选择相信或不信 —— 而两条路都不对。
|
|
67
|
+
|
|
68
|
+
★ **`text` 和 `概要` 是同义词**(历史包袱)。早期写 `text`,后来某些实现用 `概要`;
|
|
69
|
+
读的时候两种都要认,不要因为找不到 `text` 就判定这条坏了。
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 四、`feel`:必问不必写
|
|
74
|
+
|
|
75
|
+
**`feel` 不是概要、不是结论,是「我当时什么感觉」。**
|
|
76
|
+
|
|
77
|
+
它的用途只有一个:**以后读到这一条时,能回到当初的情形。**
|
|
78
|
+
概要能告诉你「做了什么」,`feel` 才能告诉你「那件事对他意味着什么」。
|
|
79
|
+
|
|
80
|
+
★★ **但必须做的不是「写」,是「问」。** 每写一条之前停一下:**这件事我有感觉吗?**
|
|
81
|
+
|
|
82
|
+
- 有 → 写进去
|
|
83
|
+
- 没有 → **不写,这是对的**
|
|
84
|
+
|
|
85
|
+
★ **为什么不做成必填**:做成必填它就变成每次要交的作业,那就成了表演。
|
|
86
|
+
而「问过之后的没有」和「忘了问的没有」是**两件事** —— 后者是懒,前者是诚实。
|
|
87
|
+
|
|
88
|
+
★ 一份真实的账本里,带 `feel` 的约占三分之一。**这个比例本身就是它对的样子** ——
|
|
89
|
+
不是每条都该有。
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 五、谁能写哪一类:主导 vs 执行
|
|
94
|
+
|
|
95
|
+
**账本里的权限不是靠自律,是代码级的闸门。**
|
|
96
|
+
|
|
97
|
+
| 角色 | 判据 | 能写 |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| **主导** | 是不是最后一条 `lead` 的署名者 | 全部,**含 `promise`** |
|
|
100
|
+
| **执行者** | 从没写过 `lead` | `fact` / `shelved` / `gain` / `loss`,★ **写 `promise` 会被拒** |
|
|
101
|
+
|
|
102
|
+
★ **一句话:身份可以复制,责任不能。**
|
|
103
|
+
一个执行容器干完就关,它许下的承诺没人来兑现 —— 所以它根本不许许。
|
|
104
|
+
|
|
105
|
+
★ **写 `lead` 的权限不在代码里**,在人嘴里:只有用户能指定谁是主导。
|
|
106
|
+
这是设计,不是漏洞。
|
|
107
|
+
|
|
108
|
+
★ **`lead` 的正文要自带世代自述**:`第 N 代 · 接手于 <日期> · 上一代做了:<一句话>`。
|
|
109
|
+
否则换到第十次时,读那堆记录看不出时间线。
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 六、什么时候写、什么时候不写
|
|
114
|
+
|
|
115
|
+
**该写的四种时机:**
|
|
116
|
+
|
|
117
|
+
1. **做完一件事** —— 尤其是跨了几个回合才做完的
|
|
118
|
+
2. **做了一个不容易回头的决定** —— 为什么这么定,比定了什么更重要
|
|
119
|
+
3. **撞了一个坑** —— 坑的形状和检测法一起写,光写「踩过」没用
|
|
120
|
+
4. **退场之前** —— 写一条 `container`:做了什么、产物在哪、下一步该谁做
|
|
121
|
+
|
|
122
|
+
★ **前三类不能等**:事后重建不了「当时在想什么、卡在哪」。
|
|
123
|
+
★ **第四类能等**:那只是给下一代的交接,攒到退场时写一次即可。
|
|
124
|
+
|
|
125
|
+
**不该写的三种:**
|
|
126
|
+
|
|
127
|
+
- **过程流水**("我先读了 A,又读了 B")—— 一手层是会话日志,账本不要重复它
|
|
128
|
+
- **可以被一条命令重新得到的事实**("当前版本是 x.y.z")—— 下次要问磁盘,不要问账本
|
|
129
|
+
- **没有出处的断言** —— 除非你打算把它当唯一真相,那就必须在正文里说清依据
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 七、一条最容易被忽略的纪律
|
|
134
|
+
|
|
135
|
+
**账本是索引,不是记忆本体。**
|
|
136
|
+
|
|
137
|
+
它记的是「**发生过这件事,原文在 ref 指的地方**」。
|
|
138
|
+
所以:
|
|
139
|
+
|
|
140
|
+
- ★ 不要把长文塞进 `text` —— 那会让账本变成一本没法翻的书
|
|
141
|
+
- ★ 不要在账本里转述别人的结论 —— 转述就是二手的开始
|
|
142
|
+
- ★ 遇到「账本和原文冲突」—— **原文优先**,然后修账本
|
|
143
|
+
|
|
144
|
+
★ 这条纪律的反面也成立:**如果一件事没有进账本,那它在系统里就等于没发生过。**
|
|
145
|
+
不是因为账本权威,是因为**没有人会知道该去找它**。
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 八、和另外几节的关系
|
|
150
|
+
|
|
151
|
+
| 你想知道 | 看哪 |
|
|
152
|
+
|---|---|
|
|
153
|
+
| 账本在五层里的位置 | `00-layers.md` —— 它是 L3 一手层的入口 |
|
|
154
|
+
| 为什么「摘要只是索引」 | `10-echo-anatomy.md` —— L6 哨兵怎么检查回取链 |
|
|
155
|
+
| 体检时账本怎么被判 | `05-doctor.md` —— 「账本在、但是空的」是 warn 不是 error |
|
|
156
|
+
| 用户侧的约定(写之前问 feel) | 你自己的 `AGENTS.md` —— 那是每个部署自己的事,不在这里规定 |
|
|
157
|
+
|
|
158
|
+
★ **一句话**:账本是这个系统的**时间轴**。
|
|
159
|
+
别的文件回答「现在是什么样」,它回答「**是怎么变成现在这样的**」。
|
package/modules/soul/assets/reference/ECHO-/346/235/203/345/250/201/345/217/243/345/276/204.md
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# ECHO · 权威口径(对外版)
|
|
2
|
+
|
|
3
|
+
> **这一页是本仓库里 ECHO 架构唯一的权威口径。**
|
|
4
|
+
> 2026-10-23 定稿。凡本仓库其它文档与这页冲突,**以这页为准**,并去改那一处。
|
|
5
|
+
>
|
|
6
|
+
> ★ 作者本机还有一份同名文档,带家底数字与私人内容,**不随插件发布**。
|
|
7
|
+
> 两份的**六层编号、判据、维护规矩必须一致**;本页是发出去的那一份。
|
|
8
|
+
>
|
|
9
|
+
> ★ 本页所有路径都写成变量,不写死任何人的机器:
|
|
10
|
+
> `<ECHO_HUB>` = 记忆中枢(默认 `$DSH_HOME/hub`,可用环境变量 `ECHO_HUB` 覆盖)·
|
|
11
|
+
> `<DSH_HOME>` = DSH 的用户目录(可用 `ECHO_DSH_HOME` 覆盖)。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 〇、先解决一件容易乱的事:编号只有一套
|
|
16
|
+
|
|
17
|
+
这套东西在演化过程中出现过**三套口径同时存在**,其中两套都用 `L0–L5` 编号,指的却不是同一件事:
|
|
18
|
+
|
|
19
|
+
| 出处 | 六层写成 | 问题 |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| 灵魂目录(10-14 那版) | L1 热记忆 / L2 图记忆 / L3 一手 / L4 索引 | 和引擎编号正面撞车 |
|
|
22
|
+
| 架构 v2 设计稿(10-09) | L0 时钟 / L1 自我 / L2 工作台 / L3 一手 / L4 索引 / L5 检索 | 缺热记忆、图记忆、留底、心跳 |
|
|
23
|
+
| 旧 README(10-13) | 只画机制面 / 观测面,没列层 | 不完整 |
|
|
24
|
+
|
|
25
|
+
撞车点:**L1 在一处是「热记忆」,另一处是「自我」;L2 在一处是「图记忆」,另一处是「工作台」。**
|
|
26
|
+
|
|
27
|
+
★ **根因不是谁写错了,是两个视角被塞进了一套编号**:
|
|
28
|
+
一个视角讲「引擎怎么跑」(时钟 / 自我 / 检索是运行时部件),
|
|
29
|
+
另一个讲「记忆存在哪」(热 / 图 / 一手 / 索引是仓储)。
|
|
30
|
+
两者不冲突,**错在共用 L 编号**。
|
|
31
|
+
|
|
32
|
+
★★ **所以定一条纪律:只保留一套 L 编号(下面这张表)。**
|
|
33
|
+
仓储视角不再单独编号,一律用名字(热记忆 / 图记忆 / 留底 / 心跳)挂在对应层下。
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 一、一句话
|
|
38
|
+
|
|
39
|
+
**ECHO 是灵魂的第一层,管的是「我是谁 / 我记得什么」。**
|
|
40
|
+
|
|
41
|
+
它的失败形状只有一种:**丢掉的东西找不回来**(门牌失效)。
|
|
42
|
+
另一类失败——**烧光 / 原地打转 / 该停不停**——是「换气」那层的事,不在这页。
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 二、六层(唯一口径)
|
|
47
|
+
|
|
48
|
+
| 层 | 名字 | 是什么 | 在哪 |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| **L0** | **时钟 + 心跳** | 现在几点、距上轮多久、当前主导、未结;每天 04:00 自动跑索引重建与自检 | `<ECHO_HUB>/state.json` · `<ECHO_HUB>/heartbeat/` · `memq now` |
|
|
51
|
+
| **L1** | **自我 + 热记忆** | ① `SELF.md`:定长骨架,**每轮注入**(不变量 / 硬线 / 约束 / 门)<br>② 热记忆:`USER.md`(用户画像)+ `MEMORY.md`(每轮注入的短名单) | ① `<ECHO_HUB>/SELF.md`(骨架 `SELF.src.md`)<br>② 由 mnemon 运行时装在它自己的目录,**不在** `<DSH_HOME>/memory/` |
|
|
52
|
+
| **L2** | **工作台** | 当前对话上下文。★ **六层里唯一允许丢东西的一层** | 会话本身 |
|
|
53
|
+
| **L3** | **一手层** | 会话日志 · 《墨》账本 · 灵魂目录 · 留底库 | 原处,**各写各的(只追加)** |
|
|
54
|
+
| **L4** | **索引 + 图记忆** | ① 索引:摘要 + 原话,**每条带 `srcSeqs` 指针**<br>② 图记忆:洞察 + 关系边,供语义检索 | `<ECHO_HUB>/index/`(`summaries.jsonl` / `words.jsonl` / `files.jsonl`)<br>mnemon 的记忆空间 |
|
|
55
|
+
| **L5** | **检索 + 门牌** | `memq` 一扇门四动词(`now` / `<词>` / `timeline` / `open`);门牌格式 `log:<会话>#seq=<n>` | `<ECHO_HUB>/memq.mjs` |
|
|
56
|
+
|
|
57
|
+
★ **L2 那条判据要背下来**:**只有工作台允许丢东西。**
|
|
58
|
+
一手层(L3)和索引(L4)丢的都是事故,不是设计。
|
|
59
|
+
这也是「压缩只压 L2、绝不动 L3/L4」的由来。
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 三、六个面(同一件事的另一种切法)
|
|
64
|
+
|
|
65
|
+
六层是**骨架**,六个面是**功能面**——不是两套东西。
|
|
66
|
+
|
|
67
|
+
| 面 | 组成 | 在哪 |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| **机制面** | 压缩 / 裁剪 / 水位提示(ACP 三段)+ 兜底强制压缩 | `cordis.patch.yml` 的各层补丁 |
|
|
70
|
+
| **记忆中枢** | 上面那六层 L0–L5 | —— |
|
|
71
|
+
| **接口** | **门牌**:回原文的指针 `log:<会话>#seq=<n>` | —— |
|
|
72
|
+
| **入口** | **门**:`memq.mjs` 四动词 | `<ECHO_HUB>/memq.mjs` |
|
|
73
|
+
| **观测面** | **哨兵**:`echo-doctor.mjs` 体检(快检 + 深检两档) | `<ECHO_HUB>/echo-doctor.mjs` |
|
|
74
|
+
| **推送** | `SELF.md` 每轮注入(含门牌条款) | `dsh-agent-memory` 插件 |
|
|
75
|
+
|
|
76
|
+
★ **哨兵是观测面,不是第七层,也不是「六层之一」。**
|
|
77
|
+
它测的是「这六层哪一层坏了」,不产出记忆、不决定保留什么。
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 四、判据与规矩(这套没变过)
|
|
82
|
+
|
|
83
|
+
### 五条规矩
|
|
84
|
+
|
|
85
|
+
1. 摘要只能是索引,**没有指针的摘要不许进 L4**
|
|
86
|
+
2. 摘要可吊销不可删(`status: active | void`)
|
|
87
|
+
3. 时间是一等公民(每条带 `t`,一切可 `--since`)
|
|
88
|
+
4. **检索只回指针 + 逐字片段,不做转述**
|
|
89
|
+
5. 一手 / 索引 / 程序 三种标记一眼分清
|
|
90
|
+
|
|
91
|
+
### 三条不可让的判断
|
|
92
|
+
|
|
93
|
+
- ★ **摘要只是索引,不是记忆本体。** 一手层永远优先于任何转述。
|
|
94
|
+
- ★ **不连续不是缺陷,是要设计的东西。** 不是「想起来」,是「翻回去」——所以门要好开。
|
|
95
|
+
- ★★ **所有压缩/裁剪的产物都要指向原文。**
|
|
96
|
+
拿不到精确 seq 时给检索入口(会话号 + `memq <词>`),**绝不猜** —— 错的门牌比没有更坏。
|
|
97
|
+
|
|
98
|
+
### 四条体系判据(拿它量任何「要不要加进 ECHO」的东西)
|
|
99
|
+
|
|
100
|
+
① 一个被管理的资源 ② **一个唯一权威源** ③ 一个失败模式 + 检测法 ④ 一个接口
|
|
101
|
+
|
|
102
|
+
★★ **② 是最硬的一条**:两处都写 = 双重记账。
|
|
103
|
+
本页存在的意义就是把 ② 收到一处。
|
|
104
|
+
|
|
105
|
+
### 一句身份判据
|
|
106
|
+
|
|
107
|
+
**能力半可移植,身份半不可移植。** 能并进灵魂的,只有**不改变「我是谁」**的东西。
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 五、五个换机器也会踩的坑(都是实测出来的)
|
|
112
|
+
|
|
113
|
+
这一节比上面任何一节都值钱——它们不是这台机器的偶然,是这套架构的固有形状。
|
|
114
|
+
|
|
115
|
+
### 坑 1 · 热记忆不在你以为的地方
|
|
116
|
+
|
|
117
|
+
它**不在** `<DSH_HOME>/memory/`,而在 mnemon 运行时装在它自己的目录里。
|
|
118
|
+
`<DSH_HOME>/memory/workspaces/<工作区>/MEMORY.md` 是**另一个东西**(auto-memory 的工作区笔记残留),不是热记忆。
|
|
119
|
+
|
|
120
|
+
★ **判据**:热记忆的真实容量要和 mnemon 探针报的对得上。
|
|
121
|
+
探针说 97%、盘上实测 9898 B / 10240 B —— **对得上才算查对了**。
|
|
122
|
+
|
|
123
|
+
### 坑 2 · 「没人写」的权威源会静默停更
|
|
124
|
+
|
|
125
|
+
`state.json` 的某个时间戳可以停一个月不动,而体检器算出了不一致却把 `status` 硬写成 `"ok"` —— **知道了不说**。
|
|
126
|
+
|
|
127
|
+
★ 修法(已落地):让**有人真的去写它**(装配时写 `lastSelfAt` + 计数递增),
|
|
128
|
+
并且把「停更多久算异常」变成一项检查。
|
|
129
|
+
★ 通用判据:**任何一个「状态文件」,先问一句「谁在写它」。没人写的状态文件等于没有状态。**
|
|
130
|
+
|
|
131
|
+
### 坑 3 · 体检器把整份日志拼成一个字符串 → 大日志直接炸
|
|
132
|
+
|
|
133
|
+
`Buffer.concat(所有解压帧).toString("utf8")` 在日志大到一定程度时会抛
|
|
134
|
+
`Cannot create a string longer than 0x1fffffe8`(约 512 MB 字符串上限)。
|
|
135
|
+
症状不是崩溃,而是**整个会话被静默跳过**:索引少了一批,而报告只说「解码失败 1」。
|
|
136
|
+
|
|
137
|
+
★ 修法(已落地):**逐帧解码 → 逐帧按行切 → 累积行**,内存里永远不出现完整的巨串;
|
|
138
|
+
单行超 8 MB 丢弃并计数,单帧解不开跳过并计数。
|
|
139
|
+
★ 通用判据:**凡是「整个文件读进来再处理」的地方,先问一句「它可能有多大」。**
|
|
140
|
+
|
|
141
|
+
### 坑 4 · 哨兵的覆盖洞:它测的地方根本不是病灶出现的地方
|
|
142
|
+
|
|
143
|
+
实测到的三种:
|
|
144
|
+
|
|
145
|
+
1. **某一层完全没有检查项** —— 状态文件停更一个月,体检里没有一项会报
|
|
146
|
+
2. **检查项只报数量不报质量** —— 「索引层」只报摘要数和建于何时,所以 159 条定位不完整时它照样报 ✓
|
|
147
|
+
3. **在错的地方找痕迹** —— 去 `turn/end` 的 `reason.kind` 里找 `repetitive|loop`,
|
|
148
|
+
而实测那个字段只有 `{completed, interrupted, error, aborted}`,**根本没有这类值**;
|
|
149
|
+
于是某个机制明明累计干预几百次,它却报「日志里零介入痕迹」
|
|
150
|
+
|
|
151
|
+
★★ **通用判据:一条检查必须能说清「它在哪找证据、为什么那里会有证据」。**
|
|
152
|
+
找不到证据时,先问「是没发生,还是我找错地方了」——
|
|
153
|
+
**日志里没有 X,可能只是因为 X 根本不落日志。**
|
|
154
|
+
|
|
155
|
+
### 坑 5 · 判据从「整份日志」里找字符串 → 它会被你自己的讨论污染
|
|
156
|
+
|
|
157
|
+
这是最阴的一个,因为**它会让体检器永远修不好**:
|
|
158
|
+
|
|
159
|
+
体检器判断某事有没有发生,做法是「在整份日志里搜某个字符串」。
|
|
160
|
+
可日志里**既记录系统事件,也记录人对系统的讨论**——
|
|
161
|
+
于是你一旦排查这个问题(读源码、贴报错、写文档),那个字符串就进了日志,
|
|
162
|
+
体检器立刻改判成「故障」。**而且报错文本本身也会进日志,形成自锁死:报一次,永远报。**
|
|
163
|
+
|
|
164
|
+
★ 修法(已落地):**证据只从「注入通道」里取,不从整份日志里取。**
|
|
165
|
+
运行时的上下文是以结构化条目注入的(`source.kind` + `sections[]`),
|
|
166
|
+
判据落在那些条目上,人说的话根本不在里面。
|
|
167
|
+
★ 通用判据:**任何「日志里没有 X 所以坏了」的检查,先问一句「X 会不会根本不落日志」。**
|
|
168
|
+
证有不证无 —— 找不到只能说明「看不到」,不能说明「没有」。
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 六、装完之后怎么确认它是活的
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
node <ECHO_HUB>/memq.mjs now # L0/L5:时钟、当前主导、未结
|
|
176
|
+
node <ECHO_HUB>/echo-doctor.mjs # 观测面:一项一项看,看的是证据不是结论
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
★ **体检器的正确读法:先看有没有「错」,再看「警」是不是设计内的状态。**
|
|
180
|
+
比如热记忆 97% 通常不是 bug —— 满了会投影省略 + 溢出到长期记忆空间,那是设计。
|
|
181
|
+
而「某层完全没有被检查」才是真的洞。
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 七、维护规矩
|
|
186
|
+
|
|
187
|
+
★ **ECHO 的层、判据、缺口变了 → 只改本页。**
|
|
188
|
+
沿革(设计稿、研究笔记、实装报告)一律不改内容,只加一行指向本页。
|
|
189
|
+
|
|
190
|
+
★ 能让两个地方同时是真相的东西,都不要留。
|
|
191
|
+
这一页的用途就是**不让 ECHO 有两个真相**。
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 八、给下一个读它的人
|
|
196
|
+
|
|
197
|
+
如果你只读一句话:
|
|
198
|
+
|
|
199
|
+
> **ECHO 六层 = L0 时钟心跳 / L1 自我加热记忆 / L2 工作台 / L3 一手 / L4 索引加图记忆 / L5 检索。
|
|
200
|
+
> 只有 L2 允许丢东西。哨兵是观测面,不是层。**
|
|
201
|
+
|
|
202
|
+
然后记住:**别让两个地方同时是真相。**
|