dsh-plugin-prompt-tool 3.0.0 → 3.0.2
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/engine/actions/catalog.mjs +2 -1
- package/engine/actions/shared.mjs +26 -12
- package/engine/actions/tool-visibility.mjs +27 -13
- package/engine/fillers.mjs +26 -2
- package/lib/client.js +4 -4
- package/lib/client.js.map +1 -1
- package/lib/index.mjs +96 -49
- 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 +27 -27
- package/modules/soul/assets/reference/01-criteria.md +32 -32
- package/modules/soul/assets/reference/02-echo.md +161 -158
- 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 +67 -67
- 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 +109 -100
- 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/modules/tool-surface/module.yml +7 -4
- package/package.json +1 -1
- package/skills/dsh-module/reference.md +3 -3
- package/templates/80-tool-surface.yml +7 -6
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
|
+
然后记住:**别让两个地方同时是真相。**
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# ECHO 六层 · 墨账本 · mnemon —— 协同说明书
|
|
2
|
+
|
|
3
|
+
> 2026-10-25 重写。**上一版(`记忆三层联用说明书.md`)写错了骨架**:
|
|
4
|
+
> 它把 ECHO 写成了「体检台」,而体检台只是 ECHO 的**观测面**,不是全部。
|
|
5
|
+
> 这一版按 `docs/ECHO-权威口径.md` 的六层重写,并回答真正要回答的问题:
|
|
6
|
+
> **mnemon 这个外来插件,到底嵌在六层的哪里,它和墨账本怎么互补。**
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 〇、先纠一个最容易错的地方
|
|
11
|
+
|
|
12
|
+
看到 ECHO 面板,很自然会以为「ECHO = 那个体检台」。**不对。**
|
|
13
|
+
|
|
14
|
+
权威口径第 76 行写得很硬:
|
|
15
|
+
|
|
16
|
+
> ★ **哨兵是观测面,不是第七层,也不是「六层之一」。**
|
|
17
|
+
> 它测的是「这六层哪一层坏了」,不产出记忆、不决定保留什么。
|
|
18
|
+
|
|
19
|
+
所以关系是:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
ECHO = 六层骨架(L0–L5) + 六个功能面(机制/中枢/接口/入口/观测/推送)
|
|
23
|
+
↑ 哨兵只是「观测面」这一个面
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**检修表不是引擎。** 把 ECHO 理解成体检台,会漏掉它真正在管的六层。
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 一、六层是什么,以及 mnemon 站在哪两层
|
|
31
|
+
|
|
32
|
+
照抄权威口径(只保留必要列):
|
|
33
|
+
|
|
34
|
+
| 层 | 名字 | 管什么 | **谁在实现它** |
|
|
35
|
+
|---|---|---|---|
|
|
36
|
+
| **L0** | 时钟 + 心跳 | 现在几点、距上轮多久、当前主导、未结;每天 04:00 自动重建索引与自检 | `memq now` · `state.json` · `heartbeat/` |
|
|
37
|
+
| **L1** | 自我 + 热记忆 | ① `SELF.md`:定长骨架,每轮注入(不变量/硬线/约束/门)<br>② 热记忆:`USER.md` + `MEMORY.md` | ① 推送插件 `dsh-agent-memory`<br>② ★★ **mnemon 运行时,装在自己的目录** |
|
|
38
|
+
| **L2** | 工作台 | 当前对话上下文。**六层里唯一允许丢东西的一层** | 会话本身 |
|
|
39
|
+
| **L3** | 一手层 | 会话日志 · **《墨》账本** · 灵魂目录 · 留底库 | 原处,各写各的(只追加) |
|
|
40
|
+
| **L4** | 索引 + 图记忆 | ① 索引:摘要+原话,**每条带 `srcSeqs` 指针**<br>② **图记忆:洞察 + 关系边** | ① `<ECHO_HUB>/index/`<br>② ★★ **mnemon 的记忆空间** |
|
|
41
|
+
| **L5** | 检索 + 门牌 | `memq` 四动词;门牌格式 `log:<会话>#seq=<n>` | `<ECHO_HUB>/memq.mjs` |
|
|
42
|
+
|
|
43
|
+
★★ **注意 L1 和 L4 的右列 —— 那里写着 mnemon。**
|
|
44
|
+
|
|
45
|
+
这正是整套架构最容易被误解的地方:
|
|
46
|
+
|
|
47
|
+
> **mnemon 不是「第六层之外又一个记忆系统」。它横跨两层,是 L1 的载体、L4 图记忆的实现。**
|
|
48
|
+
|
|
49
|
+
而**墨账本是 L3 里的一个具体账本** —— 它不跨层,就老老实实待在 L3。
|
|
50
|
+
|
|
51
|
+
所以三方的关系不是「三个并列的记忆」,是:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
L0 时钟 ──────────────┐
|
|
55
|
+
L1 自我 + 热记忆 ← mnemon ①
|
|
56
|
+
L2 工作台(可丢) │ ← ECHO 管的是这个骨架
|
|
57
|
+
L3 一手 → 《墨》 │
|
|
58
|
+
L4 索引 + 图记忆 ← mnemon ②
|
|
59
|
+
L5 检索(memq)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 二、协同在哪:四个真实的接缝
|
|
65
|
+
|
|
66
|
+
「协同增强」不是一句形容,它有四个可以指出来的接缝。**每一个接缝上,两边干的活不一样,缺一边就会塌。**
|
|
67
|
+
|
|
68
|
+
### 接缝 ①(L1):SELF.md 保底,mnemon 管容量
|
|
69
|
+
|
|
70
|
+
L1 是两样东西合伙:
|
|
71
|
+
|
|
72
|
+
| | 谁提供 | 特性 | 失败形状 |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| **不变量**(我是谁/硬线/门) | `SELF.md` 推送插件 | **每轮注入,不会静默消失**,预算 12288 可以变大 | 不会有「静默丢」 |
|
|
75
|
+
| **热记忆**(USER/MEMORY) | **mnemon** | 有硬容量上限(4096 / 10240 B),**满了会静默丢最宽泛的** | 不报错、不告警、界面什么都不说 |
|
|
76
|
+
|
|
77
|
+
★★ **这就是互补的核心**:
|
|
78
|
+
|
|
79
|
+
爀曦 2026-09-27 定的那句话是这一层的设计原理 ——
|
|
80
|
+
「`agents` 满了就会静默消失,但是 `self` 可以变大」。**AGENTS.md 走指令预算,满了先丢最宽泛的(正是 §0、§7 这类总纲);SELF.md 走推送,不会没掉。**
|
|
81
|
+
|
|
82
|
+
所以在 L1 内部:**最不能丢的东西放 SELF(不会丢),会变长的短名单放热记忆(mnemon 管容量)。**
|
|
83
|
+
**互换就出事** —— 把硬线放热记忆,满了会被静默丢;把日常清单放 SELF,会把推送预算吃光。
|
|
84
|
+
|
|
85
|
+
★ 而 mnemon 那个探针本身就在履行这个职责:`MEMORY 9条/6.9KB(69%) 宽裕`。
|
|
86
|
+
**它在替你量那个「会不会静默丢」的水位。**
|
|
87
|
+
|
|
88
|
+
### 接缝 ②(L4):索引精确,图记忆模糊
|
|
89
|
+
|
|
90
|
+
L4 也是两半:
|
|
91
|
+
|
|
92
|
+
| | 实现 | 强在哪 | 弱在哪 |
|
|
93
|
+
|---|---|---|---|
|
|
94
|
+
| **索引**(摘要 + 原话,带 `srcSeqs`) | `<ECHO_HUB>/index/` + `memq` | **精确**。有关键词就能搜;每条带指针,能一路回原文 | 你**得先想得到那个词** |
|
|
95
|
+
| **图记忆**(洞察 + 关系边) | **mnemon** | **模糊**。想不起词也能搜到「意思相近的」;有关系边可跳 | 它是提炼过的,**没有时间线**,问「那天经过」答不准 |
|
|
96
|
+
|
|
97
|
+
★★ **这一对的互补是整套系统里最实用的**:
|
|
98
|
+
|
|
99
|
+
> **知道要搜什么 → `memq`(精确、带门牌、能回原文)。**
|
|
100
|
+
> **不知道该搜什么 → `mnemon_recall`(语义、跨会话)。**
|
|
101
|
+
|
|
102
|
+
这也是「瓶颈不是检索精度,是触发」那句话的工程解法 ——
|
|
103
|
+
**触发不了精确检索的时候,还有一条模糊的路兜着。**
|
|
104
|
+
|
|
105
|
+
### 接缝 ③(L3 → L4):一手是原料,图记忆是提炼物
|
|
106
|
+
|
|
107
|
+
这条是**单向的、向上的**:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
L3 里发生的事(墨记一条) → 提炼出判据 → 写进 mnemon(L4 图记忆)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
判据("下次怎么判断")和事件("当时发生了什么")是两种东西,**必须分开放**:
|
|
114
|
+
|
|
115
|
+
- 事件进墨:有署名、有 `t`、能 `--since` 切时间线
|
|
116
|
+
- 判据进 mnemon:能被语义搜到,半年后想不起关键词也找得回
|
|
117
|
+
|
|
118
|
+
★ 一条纪律:**同一件事不要写两遍。** 墨里记「从这件事得出一条判据,已入 mnemon」,
|
|
119
|
+
正文只在 mnemon 里存一份。**复制是记忆系统最常见的腐烂方式** —— 两份内容,改一份忘另一份。
|
|
120
|
+
|
|
121
|
+
### 接缝 ④(L5 ↔ L4):门牌是两边共用的接口
|
|
122
|
+
|
|
123
|
+
`log:<会话>#seq=<n>` 这个格式,**索引用它(`srcSeqs`)、检索用它(`memq open`)、压缩用它(摘要首块)**。
|
|
124
|
+
|
|
125
|
+
所以「所有压缩/裁剪的产物都要指向原文」这条规矩,落到工程上就是**门牌必须存在**。
|
|
126
|
+
拿不到精确 seq 时给检索入口(会话号 + `memq <词>`),**绝不猜** —— 错的门牌比没有更坏。
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 三、一个真实的缺口(写出来,因为它在)
|
|
131
|
+
|
|
132
|
+
L4 有一条硬规矩,写在权威口径第 85 行:
|
|
133
|
+
|
|
134
|
+
> **摘要只能是索引,没有指针的摘要不许进 L4。**
|
|
135
|
+
|
|
136
|
+
而 **mnemon 的洞察天然没有 `log:session-…#seq=` 门牌** —— 它是「提炼过的结论」,不是「某段原文的摘要」。
|
|
137
|
+
|
|
138
|
+
**这就是一个真实的结构缺口**:如果把 mnemon 的洞察当成「进 L4 的摘要」,它违反规矩 1;
|
|
139
|
+
如果不让它进 L4,那图记忆那一半就空着。
|
|
140
|
+
|
|
141
|
+
目前的处理(也是我建议继续用的):
|
|
142
|
+
|
|
143
|
+
- **mnemon 的洞察算「图记忆」,不算「摘要」** —— 两类东西,规矩 1 只管后者
|
|
144
|
+
- 但**写洞察时尽量带来源**:哪怕不是精确 seq,也写清「哪次会话/哪个文件/哪一天」
|
|
145
|
+
|
|
146
|
+
★ 这条**不完美,我不打算假装它解决了**。
|
|
147
|
+
写在这里是为了:将来谁想动 mnemon 和 L4 的边界,先看到这个已知缺口,不要重新发现一遍。
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 四、什么时候用哪个(操作判据)
|
|
152
|
+
|
|
153
|
+
| 我要回答的问题 | 去哪 | 为什么 |
|
|
154
|
+
|---|---|---|
|
|
155
|
+
| 「那天到底发生了什么」 | **L3 一手**:`memq <词>` / `memq open <指针>` | 带门牌,能回原文 |
|
|
156
|
+
| 「我们以前对这类问题下过什么结论」 | **L4 图记忆**:`mnemon_recall` | 语义检索,不用想关键词 |
|
|
157
|
+
| 「现在几点、距上轮多久、谁主导、还有什么没结」 | **L0**:`memq now` | 时钟层就管这个 |
|
|
158
|
+
| 「这套东西现在还活着吗、哪层坏了」 | **观测面**:ECHO 面板 / `echo-doctor.mjs` | 六层各自有检测项 |
|
|
159
|
+
| 「一条判据该写哪」 | 判据形状 → **mnemon**;事件形状 → **墨** | 见接缝 ③ |
|
|
160
|
+
| 「某个配置现在是什么值」 | **都不是** —— 去读文件 | 记忆是快照,磁盘才是现在 |
|
|
161
|
+
|
|
162
|
+
★★ 最后一条是硬规矩:**凡是「过去」和「磁盘上」的事实,都不许从记忆里捞。**
|
|
163
|
+
版本号、端口、哈希、某个字段现在是什么 —— 查记忆得到的是「上次它是什么」。
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 五、一个真实案例(这套系统最容易被用错的地方)
|
|
168
|
+
|
|
169
|
+
2026-10-25,要验「路 B 在 rc.3 上到底成没成立」。
|
|
170
|
+
|
|
171
|
+
我的做法:重启七次、写探针包、往已经跑着的压缩包里塞日志 —— **全部失败,拿不到 ctor。**
|
|
172
|
+
|
|
173
|
+
**而观测面早就报了 `doorsign ok seq=125313`。门牌一直是通的。**
|
|
174
|
+
|
|
175
|
+
后来一次真实压缩发生,摘要首块写了:
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
log:session-1099f531-7cac-4989-a14c-7fd499ac1fc0#seq=126331(本段覆盖 126331–126653)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
还带了回取命令。**答案一直在 L3/L4 里,我去造了一个更难的答案。**
|
|
182
|
+
|
|
183
|
+
★ 这条放进说明书,因为它同时说明了两件事:
|
|
184
|
+
|
|
185
|
+
1. **观测面的历史记录本身就是证据。** 它每轮都在采样;需要证据时**先读历史,再决定要不要造新的**
|
|
186
|
+
2. **不要跳过 L5 去发明新的验证通道。** 门牌机制就是为「证明某段原文存在过」而造的;
|
|
187
|
+
为了证明「压缩在工作」而去装探针,等于放着现成的接口不用,另铺一条路
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 六、四个常见误用
|
|
192
|
+
|
|
193
|
+
| 误用 | 后果 | 正确做法 |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| 把事件写进 mnemon | 浪费。它没时间线,问「那天的经过」答不准,而 `memq` 一搜就到 | 事件进墨;mnemon 只收判据 |
|
|
196
|
+
| 技术结论只写一手 | 漏。半年后在别的会话里想不起关键词,一条都搜不到 | 判据必须进 mnemon |
|
|
197
|
+
| 把 ECHO 当记忆用 | 它只有状态没有内容 | 观测面用来**发现问题**,解决问题去 L3 |
|
|
198
|
+
| 为了保险把东西抄进热记忆 | 每轮注入,抄多了挤掉要紧的;满了会**静默丢最宽泛的** | 只放「不看会踩坑」的;不变量放 SELF |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 七、这套东西做不到什么
|
|
203
|
+
|
|
204
|
+
- **mnemon 不是数据库。** 语义检索不是精确匹配;要找某个字符串,去 grep 日志
|
|
205
|
+
- **观测面不修东西。** 它只报警。报警之后要人去查,它没有任何自愈能力
|
|
206
|
+
- **墨只追加,不能改。** 写错了不能回头篡改 —— 那是设计。改主意就再追加一条说明
|
|
207
|
+
- **热记忆会满,而且丢的时候不通知你。** 靠 mnemon 探针量,或者靠人记得去量
|
|
208
|
+
- **L4 那条缺口还在**(第三节)。不假装它不存在
|
|
209
|
+
- **这套东西救不了「根本没记」的。** 它只保证「记过的能找回来」
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 八、一句话
|
|
214
|
+
|
|
215
|
+
**ECHO 是骨架(六层),mnemon 是骨架里两处的实际承重墙(L1 的热记忆、L4 的图记忆),
|
|
216
|
+
墨账本是一手层里那本只追加的账。**
|
|
217
|
+
|
|
218
|
+
协同不是「记忆越多越好」,而是**每一层都有精确和模糊两条腿**:
|
|
219
|
+
L1 有「不会丢的不变量」和「会满的短名单」,
|
|
220
|
+
L4 有「精确的索引」和「模糊的图记忆」,
|
|
221
|
+
L3 有「事件」而 mnemon 有「结论」。
|
|
222
|
+
|
|
223
|
+
**一条腿走路会摔,两条腿才走得远。**
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
> 相关:`docs/ECHO-权威口径.md`(六层唯一口径,冲突以那份为准)·
|
|
228
|
+
> `plugins/echo/README.md`(观测面本身)·
|
|
229
|
+
> 本机另有一份带家底数字的私人版,不随插件发布。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# 13 份 soul
|
|
1
|
+
# 13 份 soul 正文 + 2 份 ECHO 权威文档(外部来源)
|
|
2
2
|
|
|
3
|
-
Source: `D:\AI\GitHub\dsh-agent-soul\soul\`(MIT
|
|
3
|
+
Source: `D:\AI\GitHub\dsh-agent-soul\soul\` 与 `docs\`(MIT;soul 正文 2026-10-24 导入,2026-10-25 同步 ECHO 权威口径,源提交 `b3606be`)
|
|
4
4
|
用途:模块文件工具按需读取的完整知识,例如 `module_file_read` 的 `path: assets/reference/05-doctor.md`。
|
|
5
5
|
|
|
6
6
|
适配边界:
|
|
@@ -8,3 +8,5 @@ Source: `D:\AI\GitHub\dsh-agent-soul\soul\`(MIT,2026-10-24 导入)
|
|
|
8
8
|
- 本项目不安装 dsh-agent-soul 插件,也不分发它的 kit/CLI。正文里出现的 `ECHO_SOUL`、`kit/echo/*.mjs`、`plugins/*` 等路径与命令只描述原项目的运行时;在本模块里,用户数据根是模块目录的 `data/`,读写走 `module_file_read/append`,装配走 `module_manifest`。
|
|
9
9
|
- `04-manifest.json` 与 `07-bundle.json` 是外部安装清单,本项目不使用,只作参考。
|
|
10
10
|
- 正文保持原文,未逐份改写;与模块规则冲突时,以 `module.yml` 与 `assets/manifest.yml` 为准。
|
|
11
|
+
- 2026-10-25 同步:更新 `00-layers`、`02-echo`、`05-doctor`、`10-echo-anatomy`,新增 `ECHO-权威口径.md`(L0–L5 唯一权威)与 `ECHO六层与mnemon协同说明书.md`;源仓库当天删除的错误版《记忆三层联用说明书》不收录。
|
|
12
|
+
- 模块内路径对照:源正文的 `../docs/ECHO-权威口径.md` 对应 `assets/reference/ECHO-权威口径.md`;源账本名 `02-墨.jsonl` 在模块内为 `data/02-soul.jsonl`,以 `module.yml` 与 `assets/manifest.yml` 为准。
|
package/modules/soul/module.yml
CHANGED
|
@@ -5,7 +5,7 @@ id: soul
|
|
|
5
5
|
name: 灵魂架构(判据与推送)
|
|
6
6
|
version: 1.0.0
|
|
7
7
|
engineCompat: ">=0.7.2"
|
|
8
|
-
description: 灵魂架构模块(资产 + 规则):常驻四条判据与子代理硬线,按需注入五层/ECHO/VITAL/账本,压缩后与每 12
|
|
8
|
+
description: 灵魂架构模块(资产 + 规则):常驻四条判据与子代理硬线,按需注入五层/ECHO/VITAL/账本,压缩后与每 12 轮各提醒一次;工具由项目内置引擎提供,本模块分发规则、资产与装配清单。原项目:https://github.com/cyanwell/dsh-agent-soul
|
|
9
9
|
meta:
|
|
10
10
|
source: manual
|
|
11
11
|
modules:
|
|
@@ -307,5 +307,5 @@ rules:
|
|
|
307
307
|
role: user
|
|
308
308
|
text: |-
|
|
309
309
|
账本还有未结事项:回复里逐条收口,或说清为什么先放着。
|
|
310
|
-
需要追加时用 module_file_append(moduleId: soul,path: data/02
|
|
310
|
+
需要追加时用 module_file_append(moduleId: soul,path: data/02-soul.jsonl,entry: {...}),
|
|
311
311
|
只往后加,不改旧行;收口后把 ledger_open 减到 0。
|
|
@@ -18,7 +18,7 @@ id: superpowers
|
|
|
18
18
|
name: Superpowers 技能优先引导(bootstrap)
|
|
19
19
|
version: 1.3.0
|
|
20
20
|
engineCompat: ">=0.4.2"
|
|
21
|
-
description: 常驻注入上游 using-superpowers 技能原文(v7.0.1
|
|
21
|
+
description: 常驻注入上游 using-superpowers 技能原文(v7.0.1):任何回答或动作前先查技能,附技能优先级、英文路由表、红旗清单与用户指令优先级。技能正文留在技能库,本模块不分发技能文件。原项目:https://github.com/obra/superpowers
|
|
22
22
|
meta:
|
|
23
23
|
source: manual
|
|
24
24
|
modules:
|
|
@@ -7,12 +7,15 @@
|
|
|
7
7
|
# 常驻集只在这里写一次;首轮提示由普通注入动作组合。
|
|
8
8
|
#
|
|
9
9
|
# 解锁的生效时机:声明在每个 model step 前重算,解锁在下一步的模型请求里已经可见。
|
|
10
|
-
# `requireMatch: true`
|
|
11
|
-
#
|
|
10
|
+
# `requireMatch: true` 是刻意的,但判据是「名单与装配面整体错位」:常驻名单里的名字
|
|
11
|
+
# **一个都不在**当前装配面时才放弃裁剪、暴露完整目录;只缺一两个(提供方被替换或关闭)
|
|
12
|
+
# 仍照常收窄,缺项只留一条诊断。解锁名不参与这个判定。
|
|
12
13
|
#
|
|
13
14
|
# 工具名必须与**实际装配名**一致:本项目 harness 是 `pwsh`、`edit` + `write`;
|
|
14
15
|
# `bash` 由平台各自提供——Windows 是本模块声明的 `tool-git-bash` 行(Git Bash,`bash -c`),
|
|
15
|
-
# POSIX 是官方持久 bash
|
|
16
|
+
# POSIX 是官方持久 bash。替换提供方(如 dsh-ops 的 `ops_bash`)属于部署事实,不写进随包名单:
|
|
17
|
+
# 加在部署层模块副本(`$DSH_HOME/.prompt-tool/modules/tool-surface/module.yml`)的 allow 即可;
|
|
18
|
+
# 没装该插件的部署里这个名字不存在,不产生任何影响。
|
|
16
19
|
#
|
|
17
20
|
# 停用即回滚:本模块在 config.yml 的 enabled 里删掉即可,重启后工具面完全恢复。
|
|
18
21
|
|
|
@@ -49,7 +52,7 @@ rules:
|
|
|
49
52
|
- skill_search
|
|
50
53
|
- skill_load
|
|
51
54
|
- tool_search
|
|
52
|
-
# 平台各自的 bash
|
|
55
|
+
# 平台各自的 bash 名;替换提供方(如 ops_bash)由部署层名单登记,随包名单只写官方名。
|
|
53
56
|
- bash
|
|
54
57
|
discovery: { kind: tools }
|
|
55
58
|
requireMatch: true
|
package/package.json
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
|---|---|---|---|
|
|
43
43
|
| `inject-text` | 由 config.layer 决定(**六层可注入**,agent-request/llm-stream/tool-pipeline 只作展示归属) | layer、strategy(static/placeholder/context-activation)、position、dedupe、mergeMode、role、order、text/texts、params、templateFile、configKind | 空正文不生成投递;变量赋值模板另按显式求值事务处理 |
|
|
44
44
|
| `assembly` | `system-prompt/assemble` 下游 | `target.sections`(`add`/`remove` **或** `keep`)、`target.contexts`(`add`/`remove` **或** `clear`,二者互斥——并存编译期拒绝);`target.tools` 已移除 | 返回未改动的装配 |
|
|
45
|
-
| `tool-visibility` | system-prompt/assemble 下游 | allow 与/或 deny(先保留再剔除)、requireMatch(仅 allow
|
|
45
|
+
| `tool-visibility` | system-prompt/assemble 下游 | allow 与/或 deny(先保留再剔除)、requireMatch(仅 allow;名单全缺才放宽)、discovery({ kind };tool/key 可选,只作断言);受众归 scope,提示归普通注入动作 | 呈现面失败保留原装配;执行闸失败留痕,不静默放行 |
|
|
46
46
|
| `tool-gate` | tools/pre-execute | decision(allow/deny/ask)、reason;工具名归 names 条件 | 一律放行——裁决 bug 不卡死调用 |
|
|
47
47
|
| `tool-result` | tools/post-execute | action(accept/replace/block)、text(仅 replace/block);工具名归 names 条件 | 一律接受——结果处理 bug 不把调用变成失败 |
|
|
48
48
|
| `append-context` | tools/post-execute | text;续跑用 inject-text 的 turn-stop 层 | 保持原结果 |
|
|
@@ -86,7 +86,7 @@ rules:
|
|
|
86
86
|
requireMatch: true
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
声明 discovery 的模块必须在 modules 里列出对应适配器行(tools → tool-search),缺行在装配准备期失败。discovery 在首次装配时按 agent 解析适配器,并从持久 tool/call 与 PTC tool/ptc-dispatch 参数回收解锁名(只做加法、跨压缩保留);工具由适配器行注册,discovery.tool/key 可选、只作断言。提示用同规则普通 inject-text 组合 count(user-message,max: 1)与 session 去重,采用 strategy: placeholder、fill: tool-catalog、params: { action: narrow }。只读 RESIDENT_TOOLS 是引用动作 allow 去 deny
|
|
89
|
+
声明 discovery 的模块必须在 modules 里列出对应适配器行(tools → tool-search),缺行在装配准备期失败。discovery 在首次装配时按 agent 解析适配器,并从持久 tool/call 与 PTC tool/ptc-dispatch 参数回收解锁名(只做加法、跨压缩保留);工具由适配器行注册,discovery.tool/key 可选、只作断言。提示用同规则普通 inject-text 组合 count(user-message,max: 1)与 session 去重,采用 strategy: placeholder、fill: tool-catalog、params: { action: narrow }。只读 RESIDENT_TOOLS 是引用动作 allow 去 deny、再按当前可见面过滤后的逗号名单(观测不到工具面时回落声明名单;观测到工具面但一个常驻名都不在时跳过提示),DISCOVERY_TOOL 是当前 Agent 的发现适配器工具名;模块 text 控制提示正文,保留自动名单而不复制声明。requireMatch 只在名单里的名字**一个都不存在**时放弃裁剪、暴露完整目录(fail-open);缺一两个提供方只是少一个常驻工具,收窄照常生效,替换提供方(如 dsh-ops 的 ops_bash)写进部署层名单。解锁名不参与放宽判定。allow 的执行面由 guard 兜底,不调用 restrict——restrict 的 allow 只收继承面名字,而全局 schemas 视图会漏预设/祖先层工具,局部 allow 反而会把它们裁掉;deny 才用 restrict + guard。PTC 下 tools 数组只有保留传输 `run_code`,实际可见面是 `tools:sdk` 正文;`run_code` 不写进 allow 也保留,且不参与 requireMatch,因此原生收窄声明可以直接与 PTC 共存。
|
|
90
90
|
|
|
91
91
|
tool-catalog 引用目标必须有 allow;仅支持普通只读插值,`templateEvaluation: true` 拒绝。未知动作引用保存前拒绝,发现适配器不可用则跳过提示并告警。
|
|
92
92
|
|
|
@@ -143,7 +143,7 @@ files:
|
|
|
143
143
|
- from: assets/templates/agents-template.md
|
|
144
144
|
to: data/AGENTS.md
|
|
145
145
|
checks:
|
|
146
|
-
- path: data/02
|
|
146
|
+
- path: data/02-soul.jsonl
|
|
147
147
|
kind: jsonl
|
|
148
148
|
maxBytes: 8388608
|
|
149
149
|
```
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
# `tool-visibility` 声明常驻集、目录与 SDK 正文的呈现、执行闸和发现来源。
|
|
4
4
|
# 首轮提示由同规则的普通注入动作组合;常驻名单只写一次。
|
|
5
5
|
#
|
|
6
|
-
# 本模板只带规则、不带 `modules`
|
|
7
|
-
# `requireMatch`
|
|
8
|
-
#
|
|
9
|
-
#
|
|
6
|
+
# 本模板只带规则、不带 `modules` 声明:用模板建模块时要自己把提供方行带进装配。
|
|
7
|
+
# `requireMatch` 只在名单**全部**缺失时放弃裁剪;缺一两个提供方只是少一个常驻工具,
|
|
8
|
+
# 收窄照常生效(提供方被替换或关闭不是声明错位)。替换提供方的名字写进 allow:
|
|
9
|
+
# 随包模板只写官方名,未安装替换插件的部署里该名字不存在,不产生任何影响。
|
|
10
10
|
#
|
|
11
11
|
# 发现适配器由 `tool-search` 行提供(模块必须列该行);解锁名从持久 `tool/call` 参数回收,
|
|
12
12
|
# 因此下一步请求即可见,压缩遮蔽后仍然保留。
|
|
@@ -27,10 +27,11 @@ then:
|
|
|
27
27
|
- skill_search
|
|
28
28
|
- skill_load
|
|
29
29
|
- tool_search
|
|
30
|
-
# 平台各自的 bash
|
|
30
|
+
# 平台各自的 bash 名;替换提供方(如 ops_bash)登记在部署层名单里。
|
|
31
31
|
- bash
|
|
32
32
|
discovery: { kind: tools }
|
|
33
|
-
#
|
|
33
|
+
# 名单里的名字一个都不存在时才放弃裁剪、暴露完整目录(fail-open);
|
|
34
|
+
# 部分缺失不触发放宽——提供方被替换或关闭是正常部署差异。
|
|
34
35
|
requireMatch: true
|
|
35
36
|
- if:
|
|
36
37
|
count:
|