@shgroup/dsh-serenity-hooks 1.104.0 → 1.107.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.
@@ -0,0 +1,273 @@
1
+ import { r as cccRootForCwd } from "./ccc-roots-DPMwBywc.js";
2
+ import { m as readTrajectorySubscriptions } from "./ccc-BmpE3cQz.js";
3
+ import { L as localHuman, n as findTrajectoryHolding } from "./bind-file-B0TuOP89.js";
4
+ import { d as registerDisposer } from "./scheduler-B0pB9mxI.js";
5
+ //#region src/trajectory/subscriptions.ts
6
+ /**
7
+ * trajectory/subscriptions.ts — 轨迹消息订阅(v1.107.0,owner 2026-11-01 令)
8
+ *
9
+ * ## 这是什么(一句话)
10
+ *
11
+ * **观察者盯一组成员;任一成员「一轮结束」,观察者被唤醒并收到一条通知。**
12
+ *
13
+ * 🔴 **它是通知,不是控制**(owner 原话「loose notification, not control」):
14
+ * 观察者收到的是「某人刚干完一轮活儿」,**不带他干了什么**(owner:「不需要带它做了什么」),
15
+ * 也不赋予它任何指挥权。要不要看、看了做什么,全由观察者自己决定。
16
+ *
17
+ * ## 与既有机制的关系(⛔ 别混)
18
+ *
19
+ * | 机制 | 主语 | 判据 |
20
+ * |---|---|---|
21
+ * | **CRO** | **自己**决定把自己叫起来(自编程) | `continuous-re-occurrence.ts` 文件存在 |
22
+ * | **本模块** | **别人**干完活了,通知我(互观察) | CCC 配置 `trajectorySubscriptions` |
23
+ * | `send-later` | 我预约未来的某一刻 | `wake-registry.json` 的 `at` |
24
+ *
25
+ * 三者都走唤醒链路,但**主语与判据都不同**。⛔ 本模块**不写 `wake-registry.json`** ——
26
+ * 那会制造第二真相源:订阅是"事件驱动的即时通知",注册表是"时刻驱动的预约",
27
+ * 混在一张表里,"这条条目为什么在等"就再也分不出来了。
28
+ *
29
+ * ## 🔴 「一轮结束」的判据——复用,不新造
30
+ *
31
+ * **`agent.status` 由 running → idle**,且这是**唯一权威**。判据已在 `cro/turns.ts` 的
32
+ * D243/D244 两段付过代价定死:
33
+ * · `agent/created` 证明「载体被发布」,不是「有轮次在跑」(重启会把它打成假在跑);
34
+ * · `agent/turn-stopping` 是「轮末**暂停点**」不是「轮结束」——监听者在里面 `steer` 会让同轮继续跑,
35
+ * 实测导致一条轮连跑 9 分钟而这期间表是空的。
36
+ * ⇒ **本模块直接订阅 `agent/status`**,⛔ 不另立判据(两个判据并存会立刻分叉)。
37
+ *
38
+ * 频率**不设上限**(owner:「不设定上限,结束了就通知」)。之所以不需要额外防抖:
39
+ * `agent/status` **只在真实状态跃迁时发**(宿主 `AgentLoop.setPhase`)。
40
+ *
41
+ * ## 三个失败面(**一个都不许静默**)
42
+ *
43
+ * | # | 失败面 | 形态 | 处置 |
44
+ * |---|---|---|---|
45
+ * | ① | 成员解析不出轨迹 | 会话没绑任何轨迹 / 轨迹编解码不出 | 跳过(**这不是错误**:没绑定的会话不归任何轨迹,它"一轮结束"与订阅无关) |
46
+ * | ② | 观察者唤不醒 | 无载体 / 载体起不来 | **响亮日志**(`console.warn`)——否则"订阅配了但从不生效"与"没人干活"同形 |
47
+ * | ③ | 投递失败 | `sendToCognitiveTrajectory` 返回 `ok:false` | **响亮日志** + 计数(供 `dashboard diag` 后续读) |
48
+ *
49
+ * 🔴 **为什么 ① 不算失败**:一条 CCC 里绝大多数会话**没有**绑轨迹(临时会话、别的 agent 的会话)。
50
+ * 把它们当失败会每天刷出上百条噪声,反而**淹没**②③那种真失败(穷举噪声 = 另一种静默)。
51
+ * ⇒ 判据:**"解析不出"不是错误,"解析出了但送不到"才是**。
52
+ *
53
+ * ## 清理(本容器栽过 5 次"只增不清")
54
+ *
55
+ * 本模块**不持有跨事件的状态表** —— 每次事件现读配置、现解析、现投递,投递完即忘。
56
+ * ⇒ 结构上不可能"只增不清"。⚠️ 唯一的进程态是**投递计数**(诊断用,固定几条键),
57
+ * 它有上界(键 = 订阅数),且随插件卸载清空({@link registerTrajectorySubscriptions} 的拆卸)。
58
+ */
59
+ const stats = /* @__PURE__ */ new Map();
60
+ function statOf(key) {
61
+ const cur = stats.get(key);
62
+ if (cur) return cur;
63
+ const fresh = {
64
+ ok: 0,
65
+ failed: 0,
66
+ lastError: null,
67
+ lastAt: null
68
+ };
69
+ stats.set(key, fresh);
70
+ return fresh;
71
+ }
72
+ /** 投递统计快照(`dashboard diag` 与测试读;空 = 从未有投递尝试) */
73
+ function subscriptionStats() {
74
+ return [...stats].map(([key, v]) => ({
75
+ key,
76
+ ...v
77
+ }));
78
+ }
79
+ /**
80
+ * 从一条「成员一轮结束」事件里,找出**该通知谁**。
81
+ *
82
+ * 纯函数(不读盘、不投递)—— 便于单测"谁该被通知"这件事本身。
83
+ *
84
+ * @param subs 订阅表
85
+ * @param memberDir 刚结束一轮的成员(轨迹**目录名**,非编码)
86
+ * @returns 需要通知的订阅(同一个 watcher 的多条订阅**各自保留**:`note` 不同)
87
+ */
88
+ function pickSubscriptionsFor(subs, memberDir) {
89
+ return subs.filter((s) => s.members.some((m) => m === memberDir));
90
+ }
91
+ /**
92
+ * 通知正文。
93
+ *
94
+ * 🔴 **刻意不带"它干了什么"**(owner:「不需要带它做了什么」)。带上就得先解析对方的产出,
95
+ * 那会让"通知"变成"代它说话"——而本机制明确只是通知。
96
+ * ⚠️ 但**必须**带够定位信息:谁说的、什么时候、是哪条订阅触发的(否则观察者拿到一句话无从查起)。
97
+ *
98
+ * @param memberDir 刚结束一轮的成员目录名
99
+ * @param sub 命中的订阅(用它的 `note` 区分是哪条订阅)
100
+ * @param atMs 事件时刻
101
+ * @param iso 时刻格式化函数(注入便于测试固定时刻)
102
+ */
103
+ function buildSubscriptionText(memberDir, sub, atMs, iso) {
104
+ const lines = [`〔轨迹订阅〕${memberDir} 刚完成一轮工作(${iso(atMs)})。`, `这不是指令,只是通知 —— 要不要看、看了做什么,由你决定。`];
105
+ if (sub.note) lines.push(`订阅说明:${sub.note}`);
106
+ lines.push(`(订阅配置来自 .opencode/serenity.json 的 trajectorySubscriptions;本通知不含它做了什么)`);
107
+ return lines.join("\n");
108
+ }
109
+ /**
110
+ * 处理一次「某会话一轮结束」。
111
+ *
112
+ * 这是本模块**唯一的业务入口**(事件适配在 {@link registerTrajectorySubscriptions} 里)。
113
+ * 分成"事件适配"与"业务处理"两半,是为了让后者**完全可单测**:
114
+ * 不需要真宿主、不需要真 agent,只要喂一个 `sessionId`。
115
+ *
116
+ * @param deps 注入的依赖
117
+ * @param sessionId 刚结束一轮的会话 id
118
+ * @param nowMs 事件时刻
119
+ * @returns 本次处理的结果摘要(**只用于测试与诊断**,生产调用方忽略)
120
+ */
121
+ async function onTurnFinished(deps, sessionId, nowMs) {
122
+ const root = deps.rootForSession(sessionId);
123
+ if (root === null) return {
124
+ skipped: "no-ccc",
125
+ delivered: 0,
126
+ failed: 0
127
+ };
128
+ const { subs, problems } = deps.readSubs(root);
129
+ for (const p of problems) deps.warn(`[serenity-hooks] ✗ 轨迹订阅配置有坏项(${root}):${p}`);
130
+ if (subs.length === 0) return {
131
+ skipped: "no-subscriptions",
132
+ delivered: 0,
133
+ failed: 0
134
+ };
135
+ const memberDir = deps.dirForSession(root, sessionId);
136
+ if (memberDir === null) return {
137
+ skipped: "unbound-member",
138
+ delivered: 0,
139
+ failed: 0
140
+ };
141
+ const hits = pickSubscriptionsFor(subs, memberDir);
142
+ if (hits.length === 0) return {
143
+ skipped: "unbound-member",
144
+ delivered: 0,
145
+ failed: 0
146
+ };
147
+ let delivered = 0;
148
+ let failed = 0;
149
+ for (const sub of hits) {
150
+ const st = statOf(`${sub.watcher}←${memberDir}`);
151
+ st.lastAt = nowMs;
152
+ const text = buildSubscriptionText(memberDir, sub, nowMs, deps.iso);
153
+ let res;
154
+ try {
155
+ res = await deps.deliver(root, sub.watcher, text);
156
+ } catch (err) {
157
+ res = {
158
+ ok: false,
159
+ detail: String(err?.message ?? err)
160
+ };
161
+ }
162
+ if (res.ok) {
163
+ st.ok += 1;
164
+ delivered += 1;
165
+ } else {
166
+ st.failed += 1;
167
+ st.lastError = res.detail ?? "(无说明)";
168
+ failed += 1;
169
+ deps.warn(`[serenity-hooks] ✗ 轨迹订阅投递失败:${memberDir} 一轮结束,但通知不到观察者「${sub.watcher}」:${st.lastError}(订阅配置见 ${root}/.opencode/serenity.json 的 trajectorySubscriptions)`);
170
+ }
171
+ }
172
+ return {
173
+ skipped: null,
174
+ delivered,
175
+ failed
176
+ };
177
+ }
178
+ /**
179
+ * 装配:订阅 `agent/status`,把「running → idle」翻译成一次 {@link onTurnFinished}。
180
+ *
181
+ * 🔴 **只认 `agent/status`**(理由见文件头「一轮结束的判据」)。具体是:
182
+ * 记住上一次观察到的状态,**只在 running → idle 这一次跃迁**上报。
183
+ * ⚠️ 为什么要自己记上一次状态:宿主虽然在**状态变化时**才发事件,但多条订阅/多条轨迹会
184
+ * 各自收到同一事件;更要紧的是**进程刚启动时**可能直接收到 `idle`(载体被载入即 idle),
185
+ * 那不是"一轮结束",那是"它一直闲着"。⇒ **没有前置 running 就不算结束**。
186
+ *
187
+ * @param ctx 插件上下文(结构化访问 `on`)
188
+ * @param deps 依赖(生产实现在 {@link defaultSubscriptionDeps})
189
+ */
190
+ function registerTrajectorySubscriptions(ctx, deps) {
191
+ /** 会话 id → 上一次观察到的状态(只有 `running` 才需要记,idle/未知一律清) */
192
+ const lastStatus = /* @__PURE__ */ new Map();
193
+ try {
194
+ ctx.on("agent/status", (payload) => {
195
+ const p = payload;
196
+ const sessionId = (p?.agent)?.session?.id;
197
+ if (typeof sessionId !== "string" || sessionId === "") return;
198
+ const status = typeof p.status === "string" ? p.status : "";
199
+ if (status === "running") {
200
+ lastStatus.set(sessionId, "running");
201
+ return;
202
+ }
203
+ if (status !== "idle") {
204
+ lastStatus.delete(sessionId);
205
+ return;
206
+ }
207
+ const prev = lastStatus.get(sessionId);
208
+ lastStatus.delete(sessionId);
209
+ if (prev !== "running") return;
210
+ onTurnFinished(deps, sessionId, Date.now()).catch((err) => {
211
+ deps.warn(`[serenity-hooks] ✗ 轨迹订阅处理异常(会话 ${sessionId}):${String(err?.message ?? err)}`);
212
+ });
213
+ });
214
+ } catch (err) {
215
+ deps.warn(`[serenity-hooks] ✗ 轨迹消息订阅未装配(agent/status 不可用):${String(err?.message ?? err)}`);
216
+ }
217
+ registerDisposer(ctx, "trajectory subscriptions", () => {
218
+ lastStatus.clear();
219
+ stats.clear();
220
+ });
221
+ }
222
+ /**
223
+ * 生产依赖:把注入面接到真实现。
224
+ *
225
+ * ⚠️ **动态 import**:本模块被 `index.ts` 静态引入,而 `deliver` 需要调度器
226
+ * (`wake/scheduler.ts` 静态链很重)⇒ 放到调用时再取,避免装配期把整条调度器链路拖进来。
227
+ *
228
+ * 🔴 **根按会话解析**(不是装配期固定):见 {@link SubscriptionDeps.rootForSession} 的理由。
229
+ * 取 cwd 的方式与 `trajectory/live.ts` 同源(`ctx.sessions.list()` 的 `header.cwd`)
230
+ * —— ⛔ 不另写一份"找会话 cwd"的逻辑(会漂)。
231
+ *
232
+ * @param ctx 插件上下文(投递与读会话都用它)
233
+ */
234
+ function defaultSubscriptionDeps(ctx) {
235
+ /** 会话 id → cwd(取不到 ⇒ null)。每次现查,不缓存(缓存会引入"会话关了但缓存还在")。 */
236
+ const cwdOfSession = (sessionId) => {
237
+ try {
238
+ const list = (ctx?.sessions)?.list?.();
239
+ if (!Array.isArray(list)) return null;
240
+ for (const s of list) {
241
+ const rec = s;
242
+ if (rec?.id === sessionId) {
243
+ const cwd = rec.header?.cwd;
244
+ return typeof cwd === "string" && cwd !== "" ? cwd : null;
245
+ }
246
+ }
247
+ return null;
248
+ } catch {
249
+ return null;
250
+ }
251
+ };
252
+ return {
253
+ rootForSession: (sessionId) => {
254
+ const cwd = cwdOfSession(sessionId);
255
+ if (cwd === null) return null;
256
+ return cccRootForCwd(cwd);
257
+ },
258
+ readSubs: (root) => readTrajectorySubscriptions(root),
259
+ dirForSession: (root, sessionId) => findTrajectoryHolding(`${root}/AGENT_SESSIONS`, sessionId),
260
+ deliver: async (root, target, message) => {
261
+ const { sendToCognitiveTrajectory } = await import("./scheduler-B0pB9mxI.js").then((n) => n.n);
262
+ const res = await sendToCognitiveTrajectory(ctx, root, target, message, "trajectory-subscription");
263
+ return {
264
+ ok: res.ok,
265
+ detail: res.detail
266
+ };
267
+ },
268
+ iso: (ms) => localHuman(ms),
269
+ warn: (msg) => console.warn(msg)
270
+ };
271
+ }
272
+ //#endregion
273
+ export { registerTrajectorySubscriptions as n, subscriptionStats as r, defaultSubscriptionDeps as t };
@@ -1,19 +1,32 @@
1
1
  /**
2
- * tools/diag/service.ts — `acc-diag` 报告装配(v1.33,S142 §32.11;2026-09-15 段数收缩)
2
+ * tools/diag/service.ts — 运行态诊断报告装配(原 `acc-diag` 工具;v1.106.0 并入 `dashboard diag`)
3
3
  *
4
- * 为什么单独成模块(R↓):工具面(`tools/diag/index.ts`)只做"取 CCC 根 + 渲染",
5
- * 装配逻辑放这里 ⇒ 纯函数可单测、不依赖 DSH 工具注册。
4
+ * ## 为什么并进 dashboard(owner 2026-11-01 裁「方案 C」)
5
+ *
6
+ * 原 `acc-diag` 是**专属工具**(要 CCC 在 `exclusiveTools` 里逐字点名才可见)。
7
+ * owner 要的是「诊断入口随时可用」,而专属机制让入口本身成了特权的副产品:
8
+ * 换个 CCC 就看不见,且"看不见"与"坏了"在现象上同形。⇒ 并入常驻的 `dashboard`,
9
+ * 并**整体删除 `exclusiveTools` 机制**(那一版永远只有一个成员,机制成本高于收益)。
6
10
  *
7
- * 为什么**无动作参数**:诊断是低频动作(§32.9 收敛取向),一次调用即出全报告,
8
- * 不需要子命令面;动作越多,模型选择成本越高。
11
+ * ⚠️ **代价(owner 已知并确认)**:`dashboard` 常驻 ⇒ 本节对**所有轨迹**可见,
12
+ * 而 ① 段的 live 会话清单是**全部 CCC** 的(跨容器)。这是方案 C 的既定后果,不是缺陷。
13
+ *
14
+ * 为什么单独成模块(R↓):工具面(`tools/kit/index.ts`)只做"取 CCC 根 + 渲染",
15
+ * 装配逻辑放这里 ⇒ 纯函数可单测、不依赖 DSH 工具注册。
9
16
  *
10
- * 三段内容(数据来源各自单一真相源,本模块只聚合不复制语义):
17
+ * 四段内容(数据来源各自单一真相源,本模块只聚合不复制语义):
11
18
  * ① live 运行态 —— 插件进程内 `diagLive(ctx)`(进程 cwd/CCC + live 会话清单)
12
- * ——**独立进程看不到运行时**,这正是本工具存在的理由
19
+ * ——**独立进程看不到运行时**,这正是本段存在的理由
13
20
  * ①b 唤醒时钟 —— `containerClocks().wake`(唤醒调度器进程内快照:武装态/计数/上次跳过原因)
14
- * ③ 唤醒注册表 —— `wake-registry.json` 的**在办条目**(state / at / target / lastResult)+ 补跑窗口
15
- * (🔴 2026-09-19 §0Q 甲案:终态条目**结案即清除** ⇒ 本段只列在办项,不再是"历史全量";
16
- * 历史由 SESSION.md / 工具输出承担——该承诺原本就写在 `wake/registry.ts` 注释里,本次做实)
21
+ * ② CRO 已注册清单 —— `listCroCognitiveTrajectories(root)`(v1.106.0 新增,owner 要求)
22
+ * **CRO 没有注册表**(见 `cro/core.ts` 文件头):`continuous-re-occurrence.ts` 文件存在即启用
23
+ * ⇒ 本段是那个"隐式事实"的**唯一可见出口**。运维看不到它,就只能靠翻目录猜。
24
+ * ③ 唤醒注册表 —— `wake-registry.json` 的**在办条目** + **未来与已过期分开列**(v1.106.0)
25
+ * 🔴 2026-09-19 §0Q 甲案:终态条目**结案即清除** ⇒ 本段只列在办项,不再是"历史全量"。
26
+ * 🔴 v1.106.0 补一条判据(owner 2026-11-01 要"看未来会被唤起的"):
27
+ * **过去的不看** ⇒ `at > now` 单独成组;**已过期但仍在办**的另列一组。
28
+ * 两者必须分开,因为它们的**病情不同**:未来项 = 正常排队;过期项 = 补跑窗口里卡着
29
+ * (调度器没跑 / 目标不可解析),混在一起读会以为"排了好多活儿"。
17
30
  *
18
31
  * ── 2026-09-15:段数由四降为三(S142「ACC 侧 autopilot 退场」§1 二阶裁定)─────────────
19
32
  * ACC 侧 autopilot 整段退场后,报告里两段的**主语消失**,故删除(不是"暂时关掉"):
@@ -27,6 +40,8 @@
27
40
  * 新链的失败形态是"S151 漏了自排下一轮"或"调度器闸关/未 tick",而删掉 ④ 后这两种病因都不可见。
28
41
  * 按所有者裁决本次**不补**(一句话可补,代价 = 一条新条件链:调度器 armed / 闸 / tick 在跑 /
29
42
  * 条目到期 / 补跑窗口 / 目标可解析 / CCC 闸)。**不得**以"顺手保留 ④"的方式把它偷偷带回。
43
+ * ⚠️ v1.106.0 的 ③ 两分组**不是**这条缺口的补丁:分组只把"已过期在办"显形,
44
+ * 没有回答"为什么没 tick"——那是 ①b 的 lastSkipReason 与 tick 次数的事,别混为一谈。
30
45
  *
31
46
  * C5「观察面归一」(2026-09-15):① 走 `diagLive`(那是**live 运行态**的独有取数,没有第二个
32
47
  * 来源);①b 时钟与 ③ 注册表经 `surface/observation.ts` 取(唯一取数出口)——**投影仍在本文件**
@@ -37,7 +52,17 @@ import { type ClockSnapshot } from '../../surface/observation.js';
37
52
  import type { Context } from 'cordis';
38
53
  /** 进程内时钟状态(唤醒调度器;判据单一真相源 = `wake/scheduler.ts`) */
39
54
  type ClockState = ClockSnapshot;
40
- interface AccDiagReport {
55
+ /** 唤醒注册表条目(诊断投影:**不含 `message`**,与面板的投影不同) */
56
+ interface DiagWakeEntry {
57
+ id: string;
58
+ target: string;
59
+ at: string;
60
+ state: string;
61
+ createdBy: string;
62
+ attempts: number;
63
+ lastResult: string | null;
64
+ }
65
+ export interface DiagReport {
41
66
  /** 调用方会话所属 CCC 根(过程内诊断的目标) */
42
67
  ccc: string;
43
68
  live: DiagLiveReport;
@@ -49,28 +74,53 @@ interface AccDiagReport {
49
74
  clocks: {
50
75
  wake: ClockState;
51
76
  };
77
+ /** 启用了 CRO 的轨迹目录名(`continuous-re-occurrence.ts` 存在即启用;CRO 无注册表) */
78
+ cro: string[];
52
79
  wakes: {
53
80
  /** 注册表文件路径问题(读不到时非空——不得静默) */
54
81
  error: string | null;
55
- entries: Array<{
56
- id: string;
57
- target: string;
58
- at: string;
59
- state: string;
60
- createdBy: string;
61
- attempts: number;
62
- lastResult: string | null;
63
- }>;
82
+ /**
83
+ * 未来条目(`at > now`)—— owner 要看的"接下来会被唤起的"。
84
+ * 按 `at` 升序(`listWakes` 已排序)。
85
+ */
86
+ future: DiagWakeEntry[];
87
+ /**
88
+ * 已过期但仍在办(`at <= now`)——**另有病情的**那批:在补跑窗口里卡着。
89
+ * 与 `future` 分开是刻意的:混在一起会被读成"排了很多活儿"。
90
+ */
91
+ overdue: DiagWakeEntry[];
92
+ /** 在办(`state === 'pending'`)条目数,两组合计 */
64
93
  pending: number;
65
94
  };
95
+ /** 报告生成时刻(epoch ms)—— 分组的判据基准,必须与读数一致才可复算 */
96
+ nowMs: number;
97
+ /**
98
+ * 轨迹消息订阅的**投递读数**(v1.107.0):谁在盯谁、成功/失败各几次。
99
+ *
100
+ * 🔴 **只列"发生过投递尝试"的键**(`watcher←member`),不是配置全表 ——
101
+ * 配置全表看 `.opencode/serenity.json` 即可;这里回答的是另一个问题:
102
+ * **「配了的那些订阅,实际上有没有在投?」**
103
+ * 一个**不出现**的键 = 还没触发过;出现且 `failed>0` 的键 = 触发了但送不到(那是要修的)。
104
+ * 两者形态不同,混成一句话就分不出来了。
105
+ */
106
+ subscriptions: Array<{
107
+ key: string;
108
+ ok: number;
109
+ failed: number;
110
+ lastError: string | null;
111
+ lastAt: number | null;
112
+ }>;
113
+ /** 订阅配置本身的**坏项**(配了但不生效的条目 —— 必须显形,否则用户以为它在工作) */
114
+ subscriptionProblems: string[];
66
115
  }
67
116
  /**
68
117
  * 装配报告(一次调用即全报告)。
69
118
  * @param ctx 插件上下文(进程内读 sessions/agents)
70
119
  * @param root 调用方 CCC 根(唤醒注册表取数目标)
71
- * @returns 结构化报告(渲染由 {@link renderAccDiag} 负责)
120
+ * @param nowMs 判"未来 / 已过期"的基准时刻(可注入 ⇒ 可单测,不依赖挂钟)
121
+ * @returns 结构化报告(渲染由 {@link renderDiag} 负责)
72
122
  */
73
- export declare function runAccDiag(ctx: Context, root: string): Promise<AccDiagReport>;
74
- /** 人读渲染(三段;空段也要显式说明"无",避免"沉默 = 一切正常"的误读) */
75
- export declare function renderAccDiag(r: AccDiagReport): string;
123
+ export declare function runDiag(ctx: Context, root: string, nowMs?: number): Promise<DiagReport>;
124
+ /** 人读渲染(四段;空段也要显式说明"无",避免"沉默 = 一切正常"的误读) */
125
+ export declare function renderDiag(r: DiagReport): string;
76
126
  export {};
@@ -20,7 +20,7 @@
20
20
  * ⚠️ wire 形状**逐字不变**(字段名/取值/出现条件都不许动)——C5 是取数归一,不是文案改版。
21
21
  */
22
22
  import type { JsonValue } from '../../kernel/json.js';
23
- type KitAction = 'health' | 'time' | 'wait';
23
+ type KitAction = 'health' | 'time' | 'wait' | 'diag';
24
24
  export declare const KIT_ACTIONS: readonly KitAction[];
25
25
  interface KitArgs {
26
26
  action: KitAction;
@@ -17,7 +17,7 @@ export declare const MSM_ACTIONS: readonly MsmAction[];
17
17
  * `msm catalog` 动作**降为指针**(只指路,不再返回本常量)—— 否则同一份正文会有两个入口,
18
18
  * 而"两个入口返回同一份内容"正是本目录自己反对的形态。
19
19
  */
20
- export declare const ACC_CATALOG = "\u2550\u2550\u2550 ACC Usage Catalog \u2550\u2550\u2550\nDirectory of ACC capabilities \u2014 each area lists where to go for details (guides live with their feature; this catalog only points).\n\n \u2460 \u8F68\u8FF9\u672C\u4F53 \u2192 cognitive_trajectory\uFF08list/show/create/use + rebuild \u8D85\u9650\u91CD\u5EFA + send-now \u5373\u65F6\u6295\u9012 + send-later \u672A\u6765\u4E00\u6B21\u6027\u5524\u9192\n + cro-guide CRO \u7F16\u5199\u6307\u5357\uFF09\n \u539F logbook \u5DF2\u5E76\u5165\uFF08v1.33 \u7528\u6237\u88C1\u51B3\uFF1A\u5E9F\u9664 logbook \u8BCD\uFF09\uFF1Bclose/archive \u5220\uFF08\u5F52\u6863\u8D70 container_fs mv\uFF09\uFF0C\n health/qa/summary \u5206\u522B\u5E76\u5165 use / list\uFF0Chook-develop-guide \u5E76\u8FDB container_admin msm guide\n \u2461 \u8BA4\u77E5\u8D28\u91CF\u6846\u67B6 \u2192 praxis\uFF08eap/neat/cce/ontology \u56DB\u5408\u4E00\u2014\u2014\u53EF\u5B9E\u8DF5\u7406\u8BBA\u6CE8\u5165\uFF0Csection \u6E10\u8FDB\u62AB\u9732\uFF0C\u65E0\u53C2\u5373\u76EE\u5F55\uFF09\n ontology\uFF08v1.52 D121\uFF1A\u672C\u4F53\u5DE5\u7A0B**\u5F15\u64CE**\u2014\u2014init/check/explain/verify/review/compliance\uFF1B\n \u4E0E praxis ontology \u7684\u5206\u5DE5 = \u90A3\u4E2A\u662F**\u65B9\u6CD5\u6587\u672C**\u3001\u8FD9\u4E2A\u662F**\u80FD\u8DD1\u7684\u90A3\u4E2A**\uFF09\n \u2462 \u5DE5\u5177\u4E0E\u6267\u884C \u2192 container_fs\uFF08\u5BB9\u5668\u6587\u4EF6\u7CFB\u7EDF 15 \u5B50\u547D\u4EE4\uFF09/ container_git\uFF08git\uFF09/ dashboard\uFF08health \u542B\u6CE8\u518C\u8868\u68C0\u67E5/time/wait\uFF09\n acc_msm \u5DF2\u5E76\u5165 msm\uFF08\u6267\u884C+\u53D1\u73B0\uFF09\u4E0E container_admin\uFF08\u7BA1\u7406\uFF09\u2014\u2014msm(\"<name>\", [\"<args>\"])\uFF1Binspect=true \u67E5\u7528\u6CD5\n \u4E13\u5C5E\u5DE5\u5177\uFF08**\u9ED8\u8BA4\u5BF9\u6240\u6709 CCC \u9690\u85CF**\uFF0C\u53EA\u6709\u5728\u81EA\u5DF1 exclusiveTools \u91CC\u70B9\u540D\u7684 CCC \u53EF\u89C1\uFF09\u2192 acc-diag\uFF08\u8FD0\u884C\u6001\u8BCA\u65AD\uFF09\n \u2463 \u8F68\u8FF9\u7EA6\u675F\u4E0E\u5BF9\u5916\u9762 \u2192 container_admin config\uFF08\u8F68\u8FF9\u7EA6\u675F\u56DB\u52A8\u4F5C guide/validate/apply/list\u2014\u2014**\u539F role \u57DF\u5DF2\u5E76\u5165 config**\uFF0C\u65E7\u540D\u4F5C\u8FC7\u6E21\u522B\u540D\u4ECD\u53EF\u7528\uFF1B\u8BF4\u660E\u7C7B\u914D\u7F6E\u8D70**\u4E24\u5C42\u83DC\u5355** config docs \u76EE\u5F55 \uFF0F config docs <\u7AE0\u8282> \u8BE6\u60C5\uFF09\n \u5916\u90E8\u7A0B\u5E8F\u5316\u63A5\u5165\u7528\u5B98\u65B9 dsh --profile acp\n \uFF0B \u73B0\u6210 ACP \u5BA2\u6237\u7AEF\uFF1B\u672C\u63D2\u4EF6\u4E0D\u63D0\u4F9B ACP \u9762\n \u2464 \u81EA\u4E3B\u4E0E\u63A5\u5165 \u2192 cognitive_trajectory send-now\uFF08\u8DE8\u8F68\u8FF9\u7684**\u5373\u65F6**\u9012\u9001\uFF0C**\u4E0D\u6392\u961F**\uFF1Alive \u76EE\u6807\u5728\u8DD1\u5C31\u5F53\u573A\u6CE8\u5165\u5F53\u524D\u8F6E\u3001\u7A7A\u95F2\u5219\u7ACB\u5373\u8D77\u8F6E\uFF1B\u975E live \u51B7\u8F7D\u5165\u2014\u2014\u7B49\u6548\u4E8E\u76F4\u63A5 wake\uFF1B**\u6709\u540C\u6B65\u56DE\u6267**\uFF09\n cognitive_trajectory send-later\uFF08\u8DE8\u8F68\u8FF9\u7684\"\u672A\u6765\u65F6\u523B + \u4E00\u6761 message\"\uFF1Bfire-and-forget\uFF0C\u65E0\u56DE\u6267\u65E0\u56DE\u6536\uFF09\n weixin \u5FAE\u4FE1\u6865\uFF08\u914D\u7F6E/\u626B\u7801/\u8DEF\u7531/\u6D88\u606F hook\u2014\u2014CCC \u4FA7 weixin-doctor MSM\uFF1Amsm(\"weixin-doctor\", [\"guide\"])\uFF09\n \u2465 CCC \u914D\u7F6E\u603B\u89C8 \u2192 container_admin config docs config\uFF08\u6309\u7AE0\u8BE6\u60C5\u2014\u20148 \u6BB5\u5168\u8868\uFF09\n \u6216 container_admin msm ccc-config\uFF08\u540C\u4E00\u4EFD\u6B63\u6587\u7684\u65E7\u5165\u53E3\uFF0C\u4FDD\u7559\uFF09\n \u2466 \u6CE8\u518C\u8868\u4E0E\u5B89\u5168 \u2192 mech-registry.json \u7531 container_admin msm register/deregister \u7BA1\u7406\uFF08\u5199\u4FDD\u62A4\u2014\u2014\u4E0D\u53EF\u76F4\u63A5\u7F16\u8F91\uFF09\n dashboard health \u8F93\u51FA registry \u5B8C\u6574\u6027\u68C0\u67E5\uFF1B\u635F\u574F\u6062\u590D\u6307\u5F15\u89C1 health registry.issues\n CCC \u7EA7\u5F00\u5173\uFF1AexclusiveTools\uFF08\u58F0\u660E\u4E13\u5C5E\u5DE5\u5177\uFF09/ safeMode.blacklist\uFF08\u5199\u8DEF\u5F84\u9ED1\u540D\u5355\uFF09\n / safeMode.hiddenTools\uFF08**\u5B89\u5168\u6A21\u5F0F\u5F00\u542F\u671F\u95F4**\u989D\u5916\u9690\u85CF\u7684\u5DE5\u5177\uFF0Cv1.51.4\uFF09\n CCC \u7EA7 skill \u4F9B\u7ED9\uFF1AcognitiveTrajectory.skills\uFF08v1.44.0\u2014\u2014**\u672C CCC \u6BCF\u6761\u8F68\u8FF9\u90FD\u5E26**\uFF0C\u542B \u8F68\u8FF9\u7EA6\u675F\u4F1A\u8BDD\uFF1B\u4E0E\u8F68\u8FF9\u81EA\u5DF1\u7684 frontmatter \u58F0\u660E\u53D6\u5E76\u96C6\uFF09\n\n\u6BCF\u533A\uFF1A\u4E00\u53E5\u8BDD\u5B9A\u4F4D + \u8BE6\u7EC6\u5165\u53E3\uFF08\u5DE5\u5177\u540D / guide \u5B50\u547D\u4EE4\uFF09\u3002\u8BE6\u60C5\u6C38\u8FDC\u4EE5\u5BF9\u5E94\u5DE5\u5177\u7684 guide/ccc-config \u4E3A\u5355\u4E00\u771F\u76F8\u6E90\u3002\n";
20
+ export declare const ACC_CATALOG = "\u2550\u2550\u2550 ACC Usage Catalog \u2550\u2550\u2550\nDirectory of ACC capabilities \u2014 each area lists where to go for details (guides live with their feature; this catalog only points).\n\n \u2460 \u8F68\u8FF9\u672C\u4F53 \u2192 cognitive_trajectory\uFF08list/show/create/use + rebuild \u8D85\u9650\u91CD\u5EFA + send-now \u5373\u65F6\u6295\u9012 + send-later \u672A\u6765\u4E00\u6B21\u6027\u5524\u9192\n + cro-guide CRO \u7F16\u5199\u6307\u5357\uFF09\n \u539F logbook \u5DF2\u5E76\u5165\uFF08v1.33 \u7528\u6237\u88C1\u51B3\uFF1A\u5E9F\u9664 logbook \u8BCD\uFF09\uFF1Bclose/archive \u5220\uFF08\u5F52\u6863\u8D70 container_fs mv\uFF09\uFF0C\n health/qa/summary \u5206\u522B\u5E76\u5165 use / list\uFF0Chook-develop-guide \u5E76\u8FDB container_admin msm guide\n \u2461 \u8BA4\u77E5\u8D28\u91CF\u6846\u67B6 \u2192 praxis\uFF08eap/neat/cce/ontology \u56DB\u5408\u4E00\u2014\u2014\u53EF\u5B9E\u8DF5\u7406\u8BBA\u6CE8\u5165\uFF0Csection \u6E10\u8FDB\u62AB\u9732\uFF0C\u65E0\u53C2\u5373\u76EE\u5F55\uFF09\n ontology\uFF08v1.52 D121\uFF1A\u672C\u4F53\u5DE5\u7A0B**\u5F15\u64CE**\u2014\u2014init/check/explain/verify/review/compliance\uFF1B\n \u4E0E praxis ontology \u7684\u5206\u5DE5 = \u90A3\u4E2A\u662F**\u65B9\u6CD5\u6587\u672C**\u3001\u8FD9\u4E2A\u662F**\u80FD\u8DD1\u7684\u90A3\u4E2A**\uFF09\n \u2462 \u5DE5\u5177\u4E0E\u6267\u884C \u2192 container_fs\uFF08\u5BB9\u5668\u6587\u4EF6\u7CFB\u7EDF 15 \u5B50\u547D\u4EE4\uFF09/ container_git\uFF08git\uFF09/ dashboard\uFF08health \u542B\u6CE8\u518C\u8868\u68C0\u67E5/time/wait\uFF09\n acc_msm \u5DF2\u5E76\u5165 msm\uFF08\u6267\u884C+\u53D1\u73B0\uFF09\u4E0E container_admin\uFF08\u7BA1\u7406\uFF09\u2014\u2014msm(\"<name>\", [\"<args>\"])\uFF1Binspect=true \u67E5\u7528\u6CD5\n \uFF08v1.106.0 \u5DF2\u5220 exclusiveTools \u673A\u5236\uFF1A\u539F\u4E13\u5C5E\u5DE5\u5177 acc-diag **\u5DF2\u5E76\u5165 dashboard diag**\uFF09\n \u2463 \u8F68\u8FF9\u7EA6\u675F\u4E0E\u5BF9\u5916\u9762 \u2192 container_admin config\uFF08\u8F68\u8FF9\u7EA6\u675F\u56DB\u52A8\u4F5C guide/validate/apply/list\u2014\u2014**\u539F role \u57DF\u5DF2\u5E76\u5165 config**\uFF0C\u65E7\u540D\u4F5C\u8FC7\u6E21\u522B\u540D\u4ECD\u53EF\u7528\uFF1B\u8BF4\u660E\u7C7B\u914D\u7F6E\u8D70**\u4E24\u5C42\u83DC\u5355** config docs \u76EE\u5F55 \uFF0F config docs <\u7AE0\u8282> \u8BE6\u60C5\uFF09\n \u5916\u90E8\u7A0B\u5E8F\u5316\u63A5\u5165\u7528\u5B98\u65B9 dsh --profile acp\n \uFF0B \u73B0\u6210 ACP \u5BA2\u6237\u7AEF\uFF1B\u672C\u63D2\u4EF6\u4E0D\u63D0\u4F9B ACP \u9762\n \u2464 \u81EA\u4E3B\u4E0E\u63A5\u5165 \u2192 cognitive_trajectory send-now\uFF08\u8DE8\u8F68\u8FF9\u7684**\u5373\u65F6**\u9012\u9001\uFF0C**\u4E0D\u6392\u961F**\uFF1Alive \u76EE\u6807\u5728\u8DD1\u5C31\u5F53\u573A\u6CE8\u5165\u5F53\u524D\u8F6E\u3001\u7A7A\u95F2\u5219\u7ACB\u5373\u8D77\u8F6E\uFF1B\u975E live \u51B7\u8F7D\u5165\u2014\u2014\u7B49\u6548\u4E8E\u76F4\u63A5 wake\uFF1B**\u6709\u540C\u6B65\u56DE\u6267**\uFF09\n cognitive_trajectory send-later\uFF08\u8DE8\u8F68\u8FF9\u7684\"\u672A\u6765\u65F6\u523B + \u4E00\u6761 message\"\uFF1Bfire-and-forget\uFF0C\u65E0\u56DE\u6267\u65E0\u56DE\u6536\uFF09\n weixin \u5FAE\u4FE1\u6865\uFF08\u914D\u7F6E/\u626B\u7801/\u8DEF\u7531/\u6D88\u606F hook\u2014\u2014CCC \u4FA7 weixin-doctor MSM\uFF1Amsm(\"weixin-doctor\", [\"guide\"])\uFF09\n \u2465 CCC \u914D\u7F6E\u603B\u89C8 \u2192 container_admin config docs config\uFF08\u6309\u7AE0\u8BE6\u60C5\u2014\u20148 \u6BB5\u5168\u8868\uFF09\n \u6216 container_admin msm ccc-config\uFF08\u540C\u4E00\u4EFD\u6B63\u6587\u7684\u65E7\u5165\u53E3\uFF0C\u4FDD\u7559\uFF09\n \u2466 \u6CE8\u518C\u8868\u4E0E\u5B89\u5168 \u2192 mech-registry.json \u7531 container_admin msm register/deregister \u7BA1\u7406\uFF08\u5199\u4FDD\u62A4\u2014\u2014\u4E0D\u53EF\u76F4\u63A5\u7F16\u8F91\uFF09\n dashboard health \u8F93\u51FA registry \u5B8C\u6574\u6027\u68C0\u67E5\uFF1B\u635F\u574F\u6062\u590D\u6307\u5F15\u89C1 health registry.issues\n CCC \u7EA7\u5F00\u5173\uFF1AsafeMode.blacklist\uFF08\u5199\u8DEF\u5F84\u9ED1\u540D\u5355\uFF09\n / safeMode.hiddenTools\uFF08**\u5B89\u5168\u6A21\u5F0F\u5F00\u542F\u671F\u95F4**\u989D\u5916\u9690\u85CF\u7684\u5DE5\u5177\uFF0Cv1.51.4\uFF09\n CCC \u7EA7 skill \u4F9B\u7ED9\uFF1AcognitiveTrajectory.skills\uFF08v1.44.0\u2014\u2014**\u672C CCC \u6BCF\u6761\u8F68\u8FF9\u90FD\u5E26**\uFF0C\u542B \u8F68\u8FF9\u7EA6\u675F\u4F1A\u8BDD\uFF1B\u4E0E\u8F68\u8FF9\u81EA\u5DF1\u7684 frontmatter \u58F0\u660E\u53D6\u5E76\u96C6\uFF09\n\n\u6BCF\u533A\uFF1A\u4E00\u53E5\u8BDD\u5B9A\u4F4D + \u8BE6\u7EC6\u5165\u53E3\uFF08\u5DE5\u5177\u540D / guide \u5B50\u547D\u4EE4\uFF09\u3002\u8BE6\u60C5\u6C38\u8FDC\u4EE5\u5BF9\u5E94\u5DE5\u5177\u7684 guide/ccc-config \u4E3A\u5355\u4E00\u771F\u76F8\u6E90\u3002\n";
21
21
  export declare const MSM_GUIDE = "MSM Development Manual (Mech & Semi-Mech framework)\n\n## What it is\nMSM = the executable-unit layer. Mech is pure TS with zero LLM reasoning; Semi-Mech is a TS framework + LLM decision points.\nMSM is ACC's deterministic executable-unit layer \u2014 all shell/exec operations go through MSM and cannot be bypassed.\n\n## Registering a new MSM (container_admin msm register)\n1. Write the script under <skill>/scripts/ (runnable via tsx; must include a main() CLI guard with an import.meta.url check)\n2. container_admin msm register --domain msm --action register <name> --skill <s> --path <script path relative to root> --category <mech|semi-mech> --description <desc>\n3. Auto-writes mech-registry.json (preserving the original format) + git commit (commits only the registry file)\n4. Validation: path must be inside root, script must exist, name must be globally unique\n\n## flag schema (v1)\nflags is a new-style object array for parameter validation and path-escape guarding:\n [{\"name\":\"output\",\"type\":\"string\",\"description\":\"output path\"},\n {\"name\":\"target\",\"type\":\"path\",\"description\":\"operation target (type:path enables in-root validation + symlink defense)\"},\n {\"name\":\"force\",\"type\":\"boolean\",\"description\":\"force mode\",\"default\":false}]\n- {name, type} format \u2014 new style, type:\"path\" enables the path-escape guard\n- {flag, description} format \u2014 old style, CLI flag description string\n- On registration, flags are passed via container_admin msm register --flags '<json>'\n\n## Script conventions\n- Top-of-file documentation: purpose / usage / exit codes\n- Exit codes: 0 success / 1 user / 2 system / 3 operator (per ACC protocol classification)\n- main() CLI guard (DC-M2): the script must start with\n if (import.meta.url === `file://${process.argv[1]}`) { main() }\n or an equivalent isMain / require.main === check \u2014 so vitest imports never trigger top-level code\n- A paired .test.ts or .spec.ts (DC-M1, vitest)\n- Business subprocess environment: SERENITY_ROOT / SERENITY_CCC / SERENITY_VERSION injected\n\n## Interaction & confirmation conventions (no blocking confirmation)\n- MSMs run in **user-less subprocesses** (spawn/execFile, 600s timeout) \u2014 **never** use\n readline / prompt / process.stdin etc. to block waiting for user input (it would hang until killed by the timeout)\n- When a second confirmation is needed: **directly return the confirmation request** (list the operation to perform and its impact + how to retry with the confirmation flag),\n returning a non-zero exit code (or an explicit hint)\n- After the agent confirms, **re-invoke the MSM with the confirmation flag** (e.g. --confirm / --yes / --force) to retry\n- Standard mode (two-phase):\n 1. First call: destructive/confirmation-requiring operation detected and no confirmation flag present \u2192 output the confirmation request (list operation/impact/rollback),\n exit non-zero (e.g. 1 user), **perform no changes**\n 2. After the agent evaluates, re-invoke: with the confirmation flag \u2192 execute and output the result\n- Applies to: delete/overwrite/push/batch operations and other irreversible or wide-impact operations\n- Anti-example (forbidden): readline waiting for user input, process.stdin.on('data') blocking waits\n (MSMs have no stdin interaction channel \u2014 they hang until the 600s timeout)\n\n## Quality checks (container_admin msm check, DC-M1~M4)\nDC-M1 has .test.ts/.spec.ts; DC-M2 has a main() guard (function main( / isMain / require.main === / import.meta.url);\nDC-M3 bidirectional: scripts unregistered + registry references missing scripts; DC-M4 path-type flags marked type:\"path\"\n\n## Self-description (protocol flags, first argument only)\nmsm(\"<name>\", [\"--list\"]) \u2014 list all MSMs\nmsm(\"<name>\", [\"--schema\", \"<n>\"]) \u2014 view a specific MSM's parameter schema\nmsm(\"<name>\", [\"--format=json\"]) \u2014 JSON output mode (remaining args passed through losslessly)\n";
22
22
  /**
23
23
  * CCC 配置参考(对齐 osp ccc-config action)。
@@ -25,7 +25,7 @@ export declare const MSM_GUIDE = "MSM Development Manual (Mech & Semi-Mech frame
25
25
  * 🔴 **2026-10-19 起导出**:`container_admin config docs config` 的两层菜单把它作为
26
26
  * 「config」章正文返回。**不另写一份**——同一段说明有第二份副本就会漂(本轨反复踩过)。
27
27
  */
28
- export declare const CCC_CONFIG_REFERENCE = "\u2550\u2550\u2550 CCC Configuration Reference \u2550\u2550\u2550\n\nCCC-level features are configured in .opencode/serenity.json.\nBelow are all available configuration sections.\n\n\u2500\u2500 1. sessionKeeper.threshold / sessionKeeper.sessionMdMaxKB \u2500\u2500\ncognitive-trajectory-assistant\uFF08COGNITIVE-TRAJECTORY-ASSISTANT \u00B7 CHECKPOINT\uFF09\u63D0\u9192\u673A\u5236\u7684\u79EF\u5206\u9608\u503C\uFF08\u975E headless \u4E3B agent\uFF09\u3002\n\u6309\u5DE5\u5177\u8C03\u7528\u52A0\u6743 + \u8017\u65F6\u8BA1\u5206\uFF1B\u8FBE\u5230\u9608\u503C\u6CE8\u5165\u63D0\u9192\uFF0C\u8981\u6C42\u6A21\u578B\u56DE\u590D ACK \u7801\u3002\n\n Config:\n { \"sessionKeeper\": { \"threshold\": 150, \"sessionMdMaxKB\": 100 } }\n\n \u8BA1\u5206\uFF1Awrite/edit = 3\uFF0Ctask = 10\uFF0Cread/grep/glob/msm \u7B49 = 1\uFF0C\u65F6\u95F4 = 1/\u5206\u949F\n \u9ED8\u8BA4\uFF1A150\n\n \u25B8 sessionMdMaxKB\uFF08v1.31.1 \u65B0\u589E\uFF1Bv1.31.2 100\u2192200\uFF1B\uD83D\uDD34 v1.84.0 200\u2192100\uFF09\uFF1A\n **\u6D3B\u8DC3 SESSION.md \u4F53\u79EF\u4E0A\u9650\uFF08KB\uFF0C\u7F3A\u7701 100\uFF1B0 = \u5173\u95ED\uFF09**\u3002\n \u8D85\u8FC7 \u2192 \u6CE8\u5165 [COGNITIVE-TRAJECTORY-ASSISTANT \u00B7 LOGBOOK COMPACTION] \u63D0\u9192\uFF1A\u6682\u505C\u5F53\u524D\u5DE5\u4F5C \u2192\n \u52A0\u8F7D eap\uFF08praxis eap\uFF09\u2192 **\u6309 EAP \u91CD\u6784\u6574\u4E2A SESSION.md**\uFF08v1.84.0 \u8D77\uFF1B\u65E7\u7248\u662F\u56DB\u6761\u91CD\u5199\u539F\u5219\uFF09\u3002\n \u5224\u636E = EAP \u4E09\u4E2A\u53D8\u91CF\uFF1AE\u2191 \u53D8\u91CF/\u8FB9\u754C/\u6709\u5411\u5173\u7CFB\u5168\u663E\u5F0F \uFF5C R\u2193 \u5E26\u7406\u7531\u4E0E\u88AB\u5426\u9879\uFF0C\u957F\u8BC1\u636E\u94FE\u5916\u79FB\u5230\n references/*.md\uFF08SESSION.md \u7559\u94FE\u63A5\uFF09\uFF5C S\u2191 \u7ED3\u6784\u6BCF\u6B21\u540C\u6837\u91CD\u5EFA\uFF0C\u4E0D\u662F\u65F6\u95F4\u6D41\u6C34\u8D26\u3002\n \u4E24\u6761\u786C\u7EA6\u675F\u968F\u63D0\u9192\u7ED9\u51FA\uFF1A\u4FDD\u7559\u56FA\u5B9A\u6BB5\u843D\u7684**\u987A\u5E8F\u4E0E\u6807\u9898**\uFF08\u4E0E\u7CFB\u7EDF\u63D0\u793A\u8BCD\u5BF9\u9F50\uFF09+ \u4FDD\u7559\u9876\u90E8 frontmatter\u3002\n \u8D85\u9650\u540E\u6BCF\u6B21\u5DE5\u5177\u8C03\u7528\u90FD\u63D0\u9192\uFF1B\u8FDE\u7EED 3 \u6B21\u672A\u91CD\u5199 \u2192 \u5347\u7EA7\u5F3A\u5236\u8BED\u6C14\uFF1B\n \u6587\u4EF6\u56DE\u5230\u9650\u5185 \u2192 \u81EA\u52A8\u505C\u6B62\uFF08\u81EA\u6108\uFF09\u3002\u8F68\u8FF9\u63D0\u9192**\u4E0D\u673A\u68B0\u963B\u65AD\u5DE5\u4F5C**\uFF08\u4E0E rebuild \u63D0\u9192\u540C\u65CF\uFF09\u3002\n\n\u2500\u2500 2. localstore.gitTrack \u2500\u2500\nlocalstore.json \u7684 git \u7B56\u7565\uFF1Aallow \u53EF\u63D0\u4EA4 / deny \u7981\u63D0\u4EA4\uFF08\u9ED8\u8BA4 deny\uFF09\u3002\ndeny \u65F6\u5199\u5165\u81EA\u52A8\u786E\u4FDD .gitignore \u542B\u8BE5\u6587\u4EF6\uFF08\u7269\u7406\u4FDD\u8BC1\uFF09\uFF0Ccontainer_git commit \u4F1A\u68C0\u67E5\u62D2\u7EDD\u3002\n\n Config:\n { \"localstore\": { \"gitTrack\": \"allow\" } }\n\n\u2500\u2500 3. hooks.autoRestoreSession \u2500\u2500\n\u4F1A\u8BDD\u81EA\u52A8\u6062\u590D\uFF08\u9ED8\u8BA4 true\uFF1B\u53D7 events \u95E8\u63A7\u2014\u2014\u4EC5\u6839\u4F1A\u8BDD + \u5DF2\u6709\u5BF9\u8BDD\u5386\u53F2\u624D\u6062\u590D\uFF09\u3002\n\n Config:\n { \"hooks\": { \"autoRestoreSession\": false } }\n\n\u2500\u2500 4. safeMode\uFF08\u9ED1\u540D\u5355 \uFF0B \u5F00\u542F\u671F\u95F4\u9690\u85CF\u7684\u5DE5\u5177\uFF09\u2500\u2500\nsafe-mode \u7531 WebUI \u5F00\u5173\u63A7\u5236\uFF08\u5199 .serenity-safe-on \u6807\u8BB0\uFF09\uFF1B\u9ED1\u540D\u5355\u8DEF\u5F84\u53D7 guards seam \u62E6\u622A\u3002\n\n \u25B8 blacklist\uFF1A\u5199\u8DEF\u5F84\u9ED1\u540D\u5355\uFF08\u540C\u4E0B Config\uFF09\u3002\n \u25B8 hiddenTools\uFF08v1.51.4\uFF0Cowner 2026-10-09 \u4EE4\uFF09\uFF1A**\u4EC5\u5728\u5B89\u5168\u6A21\u5F0F\u5F00\u542F\u671F\u95F4**\u989D\u5916\u4ECE\u6A21\u578B\u5DE5\u5177\n \u6E05\u5355\u9690\u85CF\u7684\u5DE5\u5177\uFF08ACC \u57FA\u7840\u8868\u6052\u9690 bash\uFF09\u3002\u6253\u5F00 safe-mode \u751F\u6548\u3001**\u5173\u6389\u5373\u5168\u90E8\u6062\u590D**\uFF1B\n \u6539\u672C\u952E**\u70ED\u751F\u6548**\uFF08\u4E0B\u4E00\u4E2A pre-step \u91CD\u7B97\uFF0C\u65E0\u9700\u91CD\u542F\uFF09\u3002\u58F0\u660E\u5728 CCC\uFF08D23\uFF09\u2014\u2014ACC \u4EE3\u7801\u91CC\n \u4E0D\u51FA\u73B0\u4EFB\u4F55\u5177\u4F53\u5DE5\u5177\u540D\u3002\n \u26A0\uFE0F \u5199\u4E00\u4E2A**\u672C CCC \u672A\u6CE8\u518C**\u7684\u540D\u5B57\u4F1A\u8BA9**\u6574\u6B21 restrict \u5931\u8D25**\uFF08DSH \u5951\u7EA6\u9010\u5B57\uFF1A\"unknown\n names \u2026 fail\"\uFF09\u21D2 \u6B64\u65F6**\u9000\u5316\u4E3A\u53EA\u9690\u85CF\u57FA\u7840\u8868**\u5E76\u5728\u65E5\u5FD7\u54CD\u4EAE\u62A5\u9519\uFF08\u7EDD\u4E0D\u56E0\u4E00\u4E2A\u9519\u540D\u4E22\u6389\n safe-mode \u7684\u6838\u5FC3\u9690\u85CF\uFF09\u3002\u8BCA\u65AD\uFF1A`AGENT_SESSIONS/.restrict-diag.json` \u7684 `denyByKey`\u3002\n \u26A0\uFE0F \u9690\u85CF = **\u4ECE schema \u79FB\u9664**\uFF08agent \u6839\u672C\u770B\u4E0D\u5230\u8BE5\u5DE5\u5177\uFF09\u21D2 \u522B\u628A skill/\u6587\u6863\u8FD8\u5728\u6559\u7684\u5DE5\u5177\u5199\u8FDB\u6765\u3002\n\n Config:\n { \"safeMode\": { \"blacklist\": [\".secrets/\"], \"hiddenTools\": [\"workflow\", \"job_kill\"] } }\n\n\u2500\u2500 5. \u8F68\u8FF9\u7EA6\u675F.roles\uFF08F4 \u8BA4\u77E5\u5B50\u96C6\u89D2\u8272\uFF09\u2500\u2500\n\u8F68\u8FF9\u7EA6\u675F\u89D2\u8272 = \u5168\u77E5\u5168\u80FD cognitive trajectory \u7684\u4EFB\u610F\u5B50\u96C6\uFF08CCC \u5B9A\u4E49\uFF09\u3002\u6BCF\u89D2\u8272\u72EC\u7ACB\u6A21\u578B + \u53CC\u767D\u540D\u5355\n\uFF08MSM \u767D\u540D\u5355 msms[] \u4E0E\u975E MSM \u5DE5\u5177\u767D\u540D\u5355 tools[]\uFF0C\u767D\u540D\u5355\u5916\u5168\u9690\u85CF\uFF1Bskill \u52A0\u8F7D\u6052\u53EF\u7528\uFF09\u3002\ncognitive trajectory \u7EAA\u5F8B\u5B50\u96C6\uFF08session/keeper/rebuild \u53C2\u4E0E\u9879\uFF09\u9ED8\u8BA4\u5168\u5173 = \u5B8C\u5168\u72EC\u7ACB\u3002\nsystemPrompt \u5185\u8054 \u6216 systemPromptFile\uFF08.md \u5F15\u7528\uFF0C\u63A8\u8350\uFF09\u2014\u2014\u89D2\u8272\u4F1A\u8BDD\u7684\u5B8C\u6574\u4EBA\u683C/\u8FB9\u754C\u63D0\u793A\u8BCD\u3002\nvalidate \u6821\u9A8C / apply \u751F\u6548 / list \u67E5\u770B\uFF1Acontainer_admin config <guide|validate|apply|list>\uFF08\u539F role \u57DF\u5DF2\u5E76\u5165 config\uFF0C\u65E7\u540D\u4F5C\u8FC7\u6E21\u522B\u540D\u4ECD\u53EF\u7528\uFF09\u3002\n\n Config:\n { \"\u8F68\u8FF9\u7EA6\u675F\": { \"roles\": {\n \"qa\": {\n \"model\": \"provider/model\",\n \"msms\": [\"web-search\", \"vlm-describe\"],\n \"tools\": [\"read\", \"grep\", \"glob\"],\n \"systemPromptFile\": \".opencode/skiff/qa.md\"\n } } } }\n\n\u2500\u2500 6. cognitive_trajectory\uFF08\u8F68\u8FF9 + \u5524\u9192\u6CE8\u518C\u8868\uFF0CD58\uFF09\u2500\u2500\nCCC \u7684\u4E00\u6761 cognitive trajectory = \u6301\u4E45\u8EAB\u4F53\uFF08SESSION.md\uFF09+ \u65F6\u95F4\u8F74\uFF08AGENT_SESSIONS/ \u76EE\u5F55 + \u5524\u9192\u6CE8\u518C\u8868\uFF09\u3002\n\u4E00\u4E2A CCC \u5185\u53EF\u591A\u6761\u5E76\u884C\uFF1B\u6761\u76EE\u5168\u90E8\u7531\u4EBA\u7C7B/agent \u663E\u5F0F\u767B\u8BB0\u3002\n\u26A0\uFE0F ACC \u4E0D\u518D\u63D0\u4F9B**\u5468\u671F\u81EA\u5524\u9192**\uFF08\u539F autopilot\uFF0C2026-09-15 \u6574\u6BB5\u9000\u573A\uFF1A\u673A\u5236/\u65F6\u949F/container_admin autopilot\n\u57DF/\u9762\u677F\u533A\u5757\u4E00\u5E76\u5220\u9664\uFF09\u3002\u81EA\u4E3B\u5DE1\u822A\u6539\u7531 CCC \u81EA\u5DF1\u9A71\u52A8\uFF08home-serenity \u4FA7 msm autopilot-round \u6BCF\u8F6E\u81EA\u6392\u4E0B\u4E00\u8F6E\uFF0C\n\u771F\u76F8\u6E90 = S151 SESSION.md \u00A71/\u00A71b/\u00A71c\uFF09\u3002**\u672C\u8F6E\u7684 cognitiveTrajectory.autopilot \u914D\u7F6E\u6BB5\u4FDD\u7559**\uFF08\u89C1\u4E0B\u8868\uFF09\u2014\u2014\n\u5B83\u73B0\u7531 **CCC \u4FA7\u811A\u672C**\u8BFB\u53D6\uFF0CACC \u4E0D\u518D\u6D88\u8D39\u8BE5\u6BB5\u3002\n\u5524\u9192\u6CE8\u518C\u8868\uFF08cognitive_trajectory send-later\uFF09\uFF1A\u5524\u9192 = \u672A\u6765\u65F6\u523B + \u4E00\u6761 message\uFF0C\u53EF\u5524\u9192\u81EA\u5DF1\u6216\u522B\u7684 cognitive trajectory\uFF1B\n\u843D\u70B9 AGENT_SESSIONS/wake-registry.json\uFF0C\u4E2D\u5FC3\u8C03\u5EA6\u5668\u5230\u70B9\u6295\u9012\uFF08fire-and-forget\uFF1B\u65E0\u56DE\u6267\u3001\u65E0\u56DE\u6536\uFF09\u3002\n\u8FD0\u884C\u6001\u8BCA\u65AD\uFF08ACC \u8D1F\u8D23\u4EBA\u4E13\u7528\uFF09\uFF1Aacc-diag\uFF08\u2460 live \u8FD0\u884C\u6001 / \u2460b \u5524\u9192\u65F6\u949F / \u2462 \u5524\u9192\u6CE8\u518C\u8868\uFF09\u3002\n\n\u25B8 cognitiveTrajectory.skills\uFF08v1.44.0\uFF0C**CCC \u7EA7 skill \u4F9B\u7ED9**\uFF1Bowner \u4EE4 2026-09-20\u300C\u8981\u6C42\u5B9E\u73B0\u6211\u7684\u8BC9\u6C42\u2026\u2026\n \u6CE8\u5165\u662F\u52A8\u6001\u6CE8\u5165\u5C31\u884C\uFF1Bcreate \u5148\u4E0D\u89E6\u53D1\u5427\uFF1B**\u8F68\u8FF9\u7EA6\u675F\u4E5F\u652F\u6301**\u300D\uFF09\uFF1A\n **\u672C CCC \u7684\u6BCF\u6761\u8F68\u8FF9\u90FD\u5E26\u8FD9\u4E9B skill**\u2014\u2014\u58F0\u660E\u7684 skill \u5168\u6587\u5728\u8BE5\u8F68\u8FF9**\u88AB\u7ED1\u5B9A\u671F\u95F4**\u6CE8\u5165\u7CFB\u7EDF\u63D0\u793A\u8BCD\n \uFF08**\u52A8\u6001\u6CE8\u5165**\uFF1A\u6BCF\u8BF7\u6C42\u91CD\u65B0\u6C42\u503C\u3001\u4E0D\u7F13\u5B58 \u21D2 \u6539\u914D\u7F6E\u6216\u6539 frontmatter **\u5373\u65F6\u751F\u6548**\uFF0C\u65E0\u9700\u91CD\u65B0 use\u3001\u65E0\u9700\u91CD\u542F\uFF09\u3002\n \u4E24\u6761\u58F0\u660E\u6765\u6E90**\u5E76\u96C6**\uFF08\u4E0D\u662F\u4E8C\u9009\u4E00\uFF09\uFF1A\u672C\u952E **cognitiveTrajectory.skills**\uFF08\u5BB9\u5668\u7ED9\u7684\u5E95\u5EA7\uFF0C**\u5728\u524D**\uFF09\n \uFF0B \u8F68\u8FF9\u81EA\u5DF1 SESSION.md \u9876\u90E8 frontmatter \u7684 skills:\uFF08\u8FD9\u6761\u8F68\u8FF9\u989D\u5916\u7684\uFF0C**\u8FFD\u52A0**\uFF1B\u540C\u540D\u53BB\u91CD\uFF09\u3002\n \u2705 **\u542B \u8F68\u8FF9\u7EA6\u675F\u89D2\u8272\u4F1A\u8BDD**\uFF08\u65C1\u8DEF\u7684\u662F ACC \u8EAB\u4EFD\u4E0E\u7EAA\u5F8B\uFF1Bskill \u662F\"\u5DE5\u4F5C\u8D44\u6599\"\uFF0C\u7167\u7ED9\uFF09\u3002\n \u5B88\u536B\uFF1A\u540D\u5B57\u5148\u8FC7\u5B89\u5168\u6821\u9A8C\u624D\u7528\u4E8E\u62FC\u8DEF\u5F84\uFF08\u9632\u7A7F\u8D8A\uFF09\uFF5C**\u5408\u5E76\u540E**\u7EDF\u4E00 32 KB \u4E0A\u9650\u622A\u65AD\uFF5C\u627E\u4E0D\u5230\u54CD\u4EAE\u5199 [\u7F3A\u5931]\u3002\n \u26A0\uFE0F \u4E0E create **\u65E0\u5173**\uFF08create \u523B\u610F\u4E0D\u593A\u7ED1\u5B9A\uFF0CU6\uFF09\u21D2 \u6CE8\u5165\u7684\u95E8\u662F\"**\u5B58\u5728\u7ED1\u5B9A**\"\uFF08cognitive_trajectory use\uFF09\u3002\n \u5931\u8D25\u8BED\u4E49\uFF1A\u672A\u914D\u7F6E / \u5B57\u6BB5\u7F3A\u5931 / \u914D\u7F6E\u635F\u574F \u21D2 **\u7A7A\u6570\u7EC4**\uFF08= \u65E0 CCC \u7EA7\u4F9B\u7ED9\uFF1B\u8F68\u8FF9\u7EA7\u58F0\u660E\u7167\u65E7\u751F\u6548\uFF09\u3002\n \u5F52\u5C5E\uFF08D23\uFF09\uFF1A**\u673A\u5236\u5728 ACC**\uFF08\u8BFB\u53D6 + \u5408\u5E76 + \u6CE8\u5165 + \u5B88\u536B\uFF09\uFF0C**\u58F0\u660E\u5728 CCC**\uFF08\u672C\u952E\uFF09\u3002\n\n Config:\n { \"cognitiveTrajectory\": {\n \"skills\": [\"acc-session\", \"cce\"], // v1.44.0\uFF1A\u672C CCC \u7684\u6BCF\u6761\u8F68\u8FF9\u90FD\u5E26\uFF08\u542B \u8F68\u8FF9\u7EA6\u675F\u4F1A\u8BDD\uFF09\n \"autopilot\": { // \u539F autopilotTrajectory \u6BB5\uFF0C\u5B57\u6BB5\u4E0D\u53D8\uFF08\u65E7\u952E\u4ECD\u56DE\u9000\u8BFB\uFF09\n \"enabled\": true,\n \"intervalHours\": 2,\n \"session\": \"S151\",\n \"biasProvider\": \"autopilot-bias.ts\",\n \"topPrompt\": \"\u672C\u8F68\u8FF9\u6838\u5FC3\u76EE\u6807/\u7EAA\u5F8B/\u8D28\u91CF\u8981\u6C42\uFF08CCC \u81EA\u586B\uFF0C\u9632\u6F02\u79FB\uFF09\",\n \"avoidWakeHours\": { \"start\": 8, \"end\": 18 }\n } } }\n\n\u2500\u2500 7. weixin\uFF08\u5FAE\u4FE1\u6865 F4c-3\uFF0C\u542B\u6D88\u606F\u8BB0\u5F55 hook\uFF09\u2500\u2500\nCCC \u7EA7\u5FAE\u4FE1\u4E2A\u4EBA\u53F7\u63A5\u5165\uFF08iLink \u534F\u8BAE\uFF09\uFF1Adsh \u4E00\u8FDB\u7A0B\u591A CCC\uFF0C\u6BCF CCC \u72EC\u7ACB\u5BF9\u63A5\u5FAE\u4FE1\u6865\u3002\n\u8D26\u53F7/\u8DEF\u7531/\u5F00\u5173\u5728\u6B64\u6587\u4EF6\uFF1B**bot_token \u51ED\u636E\u5728 CCC localstore credential scope**\n\uFF08\u626B\u7801\u7ED1\u5B9A\u540E\u81EA\u52A8\u5199\u5165\uFF0C\u6C38\u4E0D\u8FDB git \u660E\u6587\u9762\uFF09\u3002\n\u8DEF\u7531 user \u2192 role\uFF1Aexact \u4F18\u5148\uFF0C* \u901A\u914D\u515C\u5E95\uFF1Brole \u5FC5\u987B \u2208 \u8BE5 CCC \u8F68\u8FF9\u7EA6\u675F.roles\u3002\n\u9762\u677F\uFF08WebUI \u8BBE\u7F6E \u2192 \u5FAE\u4FE1\u6865\uFF09\u53EF\u626B\u7801\u7ED1\u5B9A/\u79FB\u9664\u8D26\u53F7/\u7F16\u8F91\u8DEF\u7531\uFF1Bmsm(\"weixin-doctor\", [\"status\"|\"diag\"|\"verify\"|\"guide\"]) \u6392\u67E5 + \u5927\u800C\u5168\u6307\u5357\u3002\u51ED\u636E\u4E3B\u52A8\u67E5\u770B\uFF1Alocalstore get WEIXIN_<ACCOUNT>_TOKEN\u3002\n \u25B8 \u4E3B\u52A8\u53D1\u9001\uFF08v1.31.0\uFF1A**ACC \u5DE5\u5177 im-bridge**\uFF09\uFF1A\u8C03\n im-bridge({channel:\"weixin\", action:\"send\", user:\"<\u522B\u540D|id>\", text:\"<\u6587\u672C>\"}) \u7ED9\u7528\u6237\u53D1\u6D88\u606F\u2014\u2014\n **\u5DE5\u5177\u53EA\u80FD\u64CD\u4F5C\u672C\u4F1A\u8BDD CCC**\uFF08\u65E0 ccc \u53C2\u6570\uFF0C\u9632\u8BEF\u53D1\u4ED6\u5BB9\u5668\uFF09\u2192 weixin-bridge.sendProactiveText \u2192\n \u6210\u529F\u540E\u89E6\u53D1 outgoing hook\uFF08source=\"proactive\"\uFF09\u3002\u6587\u4EF6\u7528 action:\"send-file\" + file:\"<CCC \u5185\u8DEF\u5F84>\"\n \uFF08\u9003\u9038/\u7F3A\u5931/\u8D85 20MB \u62D2\u7EDD\uFF09+ \u53EF\u9009 caption\u3002**\u53EF\u89C1\u6027**\uFF1A\u672C CCC \u914D\u7F6E\u4E86 IM \u901A\u9053\n \uFF08weixin.enabled=true\uFF09\u624D\u51FA\u73B0\u5728\u6A21\u578B\u5DE5\u5177\u6E05\u5355\u91CC\uFF1B\u672A\u914D\u7F6E \u2192 \u7531 guards \u9010 agent\n tools.restrict({deny:['im-bridge']}) \u79FB\u9664\uFF08\u4E0D\u662F\"\u770B\u5F97\u5230\u4F46\u88AB\u62D2\"\uFF09\u3002\u8F68\u8FF9\u7EA6\u675F\u89D2\u8272\u53E6\u9700\u5728\n roles.<role>.tools \u767D\u540D\u5355\u5217\u51FA im-bridge\u3002\n \u5386\u53F2\uFF08v1.30.9~v1.30.x\uFF09\uFF1ACCC \u4FA7 MSM weixin-send\uFF08\u8D70 loopback HTTP \u5165\u53E3 3082\uFF09\u2014\u2014\n v1.31.0 \u5DF2\u9000\u5F79\uFF08\u811A\u672C\u5220\u9664 + \u6CE8\u518C\u8868\u6CE8\u9500\uFF09\uFF1B3082 \u5165\u53E3\u4FDD\u7559\u7ED9**\u975E agent \u8C03\u7528\u8005**\u3002\n\n \u25B8 \uD83D\uDD34\uD83D\uDD34 **\u51FA\u7AD9\u53EA\u6709\u4E00\u6761\u8DEF\uFF1Aagent \u81EA\u5DF1\u8C03 im-bridge**\uFF082026-10-24 \u8D77\uFF0Cowner \u4EE4\uFF09\u3002\n \u6865**\u6C38\u4E0D**\u66FF\u4F60\u56DE\u53D1\u6700\u7EC8\u6587\u672C \u2014\u2014 \u4F60\u8BF4\u4EC0\u4E48\u3001\u8BF4\u51E0\u6761\u3001\u4EC0\u4E48\u65F6\u5019\u8BF4\u3001\u8981\u4E0D\u8981\u4E0D\u8BF4\uFF0C\u5168\u7531\u4F60\u51B3\u5B9A\u3002\n \u26D4 \u4E0D\u8981\u6307\u671B\"\u6211\u628A\u8BDD\u5199\u8FDB\u56DE\u7B54\u91CC\u5C31\u4F1A\u81EA\u52A8\u53D1\u51FA\u53BB\"\uFF1A**\u4E0D\u4F1A**\u3002\u5FC5\u987B\u771F\u7684\u8C03\u5DE5\u5177\u3002\n \u21D2 \u6BCF\u8F6E\u7528\u6237\u6D88\u606F\u672B\u5C3E\u90FD\u4F1A\u9644\u4E00\u884C**\u5DF2\u586B\u597D\u53C2\u6570**\u7684 im-bridge \u8C03\u7528\u6A21\u677F\uFF08\u673A\u5236\u6807\u8BB0\n [serenity:weixin-manual-output]\uFF09\uFF0C\u7167\u5B83\u6539 text \u5373\u53EF\u3002\n \u21D2 \u672C\u8F6E\u7ED3\u675F\u4ECD\u672A\u6210\u529F\u8C03\u7528\uFF08send / send-file\uFF09\u2192 \u4F60\u4F1A\u88AB\u6253\u56DE\uFF08\u22642 \u6B21\uFF0C\u63D0\u793A = \u6807\u8BB0 + \u4E8B\u5B9E\uFF09\uFF1B\n \u8FBE\u4E0A\u9650\u540E**\u7528\u6237\u5C06\u6536\u4E0D\u5230\u4EFB\u4F55\u6D88\u606F**\uFF08\u6CA1\u6709\u4EFB\u4F55\u515C\u5E95\u8F6C\u53D1\uFF09\u3002\n \u21D2 \u6210\u529F\u8C03\u7528\u624D\u7B97\u9001\u8FBE\uFF1B\u5931\u8D25\u8C03\u7528\u4E0D\u7B97\uFF08\u4E0D\u4F1A\u88AB\u5F53\u6210\u672C\u8F6E\u5DF2\u53D1\u9001\uFF09\u3002\n \u26A0\uFE0F **\u524D\u63D0**\uFF1A\u672C\u8F68\u8FF9\u5FC5\u987B\u5728 `.opencode/serenity.json` \u7684 `im.routes` \u91CC\u88AB\u70B9\u540D\uFF0C\u5426\u5219 `im-bridge`\n \u5BF9\u4F60\u4E0D**\u53EF\u89C1**\u2014\u2014\u90A3\u79CD\u60C5\u51B5\u4E0B\u95F8\u95E8\u4E0D\u4F1A\u6253\u56DE\u4F60\uFF08\u6539\u6210\u4E00\u6761\u54CD\u4EAE\u544A\u8B66\uFF0C\u6307\u660E\"\u8BE5\u8F68\u8FF9\u65E0\u53D1\u9001\u6743\"\uFF09\uFF0C\n \u56E0\u4E3A\u6253\u56DE\u4E00\u4E2A\u4F60\u6839\u672C\u6EE1\u8DB3\u4E0D\u4E86\u7684\u8981\u6C42\u53EA\u4F1A\u7A7A\u8F6C\u3002\n\n \u25B8 **\u5DF2\u9000\u5F79\uFF08\u4E0D\u8981\u518D\u914D\uFF0C\u914D\u4E86\u4E5F\u4E0D\u751F\u6548\uFF09**\uFF1A\n \u00B7 `weixin.autoReplyWithLastMessage`\uFF08v1.30.10~2026-10-24\uFF09= \u6865\u66FF agent \u56DE\u53D1\u6700\u7EC8\u6587\u672C\u3002\n **\u88AB\u5426\u7406\u7531**\uFF08owner \u539F\u8BDD\uFF09\uFF1A\u300CautoReply \u5E76\u4E0D\u5408\u9002\uFF0C\u4E3B\u52A8\u6027\u7684 imBridge \u4ECD\u7136\u662F\u66F4\u597D\u7684\u300D\u2014\u2014\n \u5B83\u8BA9 agent \u5931\u53BB\"\u8BF4\u51E0\u6761/\u4F55\u65F6\u8BF4/\u8981\u4E0D\u8981\u4E0D\u8BF4\"\u7684\u51B3\u5B9A\u6743\uFF0C\u800C\u90A3\u6B63\u662F\u4E3B\u52A8\u53D1\u9001\u7684\u4EF7\u503C\u3002\n \u00B7 `weixin.fallbackOnNoSend`\uFF08v1.30.17~2026-10-24\uFF09= \u624B\u52A8\u6A21\u5F0F\u4E0B agent \u6CA1\u53D1\u6210\u529F\u65F6\u6865\u515C\u5E95\u8F6C\u53D1\u3002\n \u5B83\u53EA\u5728\u4E0A\u9762\u90A3\u4E2A\u5F00\u5173 =false \u65F6\u624D\u6709\u610F\u4E49 \u21D2 \u4E00\u8D77\u9000\u5F79\u3002\n \u26A0\uFE0F \u65E7\u914D\u7F6E\u91CC\u6B8B\u7559\u8FD9\u4E24\u4E2A\u952E**\u9759\u9ED8\u5FFD\u7565**\uFF08\u4E0D\u4F1A\u62A5\u9519\uFF0C\u4E5F\u4E0D\u4F1A\u751F\u6548\uFF09\u3002\n\n Config:\n { \"weixin\": {\n \"enabled\": true,\n \"hook\": \"scripts/weixin-message-hook.ts\",\n \"accounts\": [{ \"accountId\": \"wechat-1\", \"name\": \"\u5BB6\u5EAD\u52A9\u624B\", \"enabled\": true }],\n \"routes\": [{ \"user\": \"*\", \"role\": \"my-role\" }]\n } }\n\n \u25B8 weixin.hook\uFF08\u6D88\u606F\u8BB0\u5F55 hook\uFF0Cv1.27.13\uFF09\uFF1A\n \u5FAE\u4FE1\u6865\u6BCF\u6536/\u53D1\u4E00\u6761\u6D88\u606F\u89E6\u53D1\u4E00\u6B21 CCC \u81EA\u5199\u811A\u672C\uFF0C\u7531 CCC \u81EA\u884C\u6301\u4E45\u5316\u4FDD\u5B58\uFF08\u5B58\u54EA/\u5B58\u6210\u4EC0\u4E48\n /\u662F\u5426\u5165\u5E93\u5168\u5F52 CCC\u2014\u2014ACC \u4E0D\u7ED1\u5B9A\u5B58\u50A8\uFF09\u3002\u672A\u914D\u7F6E hook \u2192 \u96F6\u53D8\u5316\uFF08\u4E0D\u89E6\u53D1\uFF09\u3002\n\n \u89E6\u53D1\uFF08\u53CC\u5411\uFF09\uFF1A\n incoming = \u7528\u6237 \u2192 bot\uFF1A\u8DEF\u7531\u547D\u4E2D\u540E\u3001\u5A92\u4F53\u843D\u76D8\u540E\u89E6\u53D1\uFF08\u6587\u672C\u542B\u8BED\u97F3\u8F6C\u5199\uFF1B\u5A92\u4F53\u5E26\u843D\u76D8 relPath\uFF09\n outgoing = bot \u2192 \u7528\u6237\uFF1A\u53D1\u9001\u6210\u529F\u540E\u89E6\u53D1\uFF08reply = \u7528\u6237\u5B9E\u9645\u6536\u5230\u7684\u7EAF\u6587\u672C\uFF0C\u5DF2\u5265\u79BB think\uFF09\n \u00B7 source=\"proactive\" = agent \u7ECF im-bridge \u4E3B\u52A8\u53D1\u8D77\uFF08**2026-10-24 \u8D77\u8FD9\u662F\u552F\u4E00\u503C**\uFF09\n \u00B7 \u5386\u53F2\u503C reply / reply-fallback\uFF08\u6865\u81EA\u52A8\u56DE\u53D1 / \u6865\u515C\u5E95\u8F6C\u53D1\uFF09\u5DF2\u968F\u4E24\u4E2A\u5F00\u5173\u4E00\u8D77\u9000\u5F79\uFF1B\n \u5B58\u91CF\u65E5\u5FD7\u91CC\u4ECD\u80FD\u770B\u5230\u5B83\u4EEC\uFF0C\u90A3\u662F\u5386\u53F2\u4E8B\u5B9E\uFF0C\u4E0D\u662F\u5F53\u524D\u884C\u4E3A\n \u00B7 file\uFF08\u4EC5 send-file \u8865\u8BB0\uFF09\uFF1A{ \"name\": \"\u62A5\u544A.pdf\", \"size\": 12345, \"caption\": \"\u53EF\u9009\" }\n\n \u811A\u672C\u7EA6\u5B9A\uFF08\u4E8B\u4EF6 JSON \u5355\u884C\u7ECF stdin \u4F20\u5165\uFF1Bbun \u4F18\u5148 node \u515C\u5E95\uFF09\uFF1A\n #!/usr/bin/env bun \u6216 node script.js \u2014\u2014 \u8BFB process.stdin \u6574\u6BB5 JSON.parse\n const ev = JSON.parse(await new Response(process.stdin).text())\n ev.event === 'incoming' | 'outgoing'\n\n \u4E8B\u4EF6 schema\uFF08**\u4E0D\u542B\u4EFB\u4F55\u4F1A\u8BDD\u51ED\u636E**\u2014\u2014context_token/bot_token/token/aes_key \u5747\u4E0D\u51FA\u73B0\uFF09\uFF1A\n { \"event\": \"incoming\", \"ts\": 1788359941488, \"cccRoot\": \"/path/ccc\",\n \"accountId\": \"wechat-1\", \"userId\": \"u1@im.wechat\",\n \"sessionId\": \"skiff-weixin-xxx\", \"role\": \"my-role\",\n \"message\": { \"text\": \"\u4F60\u597D\", \"media\": [{ \"kind\": \"image\", \"relPath\": \"_tmp/weixin-inbound/<hash>/img_x.jpg\" }] } }\n { \"event\": \"outgoing\", \"ts\": ..., \"cccRoot\": ..., \"accountId\": ...,\n \"userId\": ..., \"sessionId\": ..., \"role\": ...,\n \"reply\": \"\u5DF2\u8BB0\u5F55\uFF08\u7EAF\u6587\u672C\uFF09\", \"source\": \"proactive\" }\n\n \u793A\u4F8B\u811A\u672C\uFF08\u8FFD\u52A0\u5230\u6309\u65E5\u6587\u4EF6\u2014\u2014\u6301\u4E45\u5316\u5F52 CCC \u81EA\u9009\uFF1A\u6587\u4EF6/DB/\u8FDC\u7AEF\u5747\u53EF\uFF09\uFF1A\n const fs = require('node:fs'); const p = '/path/ccc/AGENT_SESSIONS/_weixin-log.jsonl';\n fs.appendFileSync(p, JSON.stringify(ev) + '\\n');\n\n \u6267\u884C\u8BED\u4E49\uFF08\u65C1\u8DEF\u5BB9\u5FCD\uFF09\uFF1A\u5F02\u6B65 fire-and-forget + 15s \u8D85\u65F6 kill + \u5931\u8D25\u4EC5\u65E5\u5FD7\u2014\u2014\n \u5FAE\u4FE1\u6865\u6D88\u606F\u5904\u7406/\u56DE\u590D\u4E0D\u53D7 hook \u5F71\u54CD\uFF1B\u811A\u672C\u987B\u5728 CCC \u6839\u5185\uFF08\u8DEF\u5F84\u9003\u9038\u62D2\u7EDD\uFF09\u3002\n \u5A92\u4F53 relPath \u6307\u5411 _tmp/weixin-inbound/\uFF08\u4E34\u65F6\u76EE\u5F55\uFF09\u2014\u2014\u9700\u6301\u4E45\u4FDD\u5B58\u5A92\u4F53\u6587\u4EF6\u8BF7\u81EA\u884C copy\u3002\n\n\u2500\u2500 8. exclusiveTools\uFF08\u4E13\u5C5E\u5DE5\u5177\u58F0\u660E\uFF0Cv1.33\uFF09\u2500\u2500\n**ACC \u6CE8\u518C\u4F46\u9ED8\u8BA4\u5BF9\u6240\u6709 CCC \u9690\u85CF**\u7684\u5DE5\u5177\uFF0C\u53EA\u6709\u5728\u81EA\u5DF1\u8FD9\u91CC**\u70B9\u540D**\u7684 CCC \u53EF\u89C1\u3002\n\u8FD9\u662F\u901A\u7528\u673A\u5236\uFF08\u4EFB\u4F55\u5DE5\u5177\u540D\u7686\u53EF\uFF09\uFF0C\u5224\u636E\u7531 CCC \u58F0\u660E\u2014\u2014ACC \u4EE3\u7801\u91CC\u4E0D\u51FA\u73B0\u4EFB\u4F55\u5177\u4F53 CCC \u7684\u540D\u5B57\u3002\n\u5F53\u524D\u4E13\u5C5E\u5DE5\u5177\uFF1Aacc-diag\uFF08\u8FD0\u884C\u6001\u8BCA\u65AD\u2014\u2014live \u4F1A\u8BDD / agent \u5B9A\u4F4D / \u5524\u9192\u6CE8\u518C\u8868 / \u5524\u8D77\u6761\u4EF6\u94FE\uFF09\u3002\n\n \u25B8 \u53EF\u89C1\u6027\u8BED\u4E49\uFF1A\u672A\u58F0\u660E \u21D2 \u7531 guards \u9010 agent tools.restrict({deny:[tool]}) \u4ECE**\u6A21\u578B\u5DE5\u5177\u6E05\u5355\u79FB\u9664**\n \uFF08\u4E0D\u662F\"\u770B\u5F97\u5230\u4F46\u88AB\u62D2\"\uFF09\u3002\u914D\u7F6E\u70ED\u66F4\u65B0\uFF1A\u6539\u672C\u6587\u4EF6\u5373\u65F6\u751F\u6548\uFF08\u65E0\u9700\u91CD\u542F\uFF09\u3002\n \u25B8 \u5931\u8D25\u65B9\u5411 **fail-closed**\uFF1A\u672A\u914D\u7F6E / \u5B57\u6BB5\u7F3A\u5931 / \u914D\u7F6E\u635F\u574F\uFF08JSON \u574F\uFF09\u21D2 \u4E00\u5F8B\u6309\"\u672A\u58F0\u660E\"\u5904\u7406\n \uFF08\u4E13\u5C5E\u5DE5\u5177\u4FDD\u6301\u9690\u85CF\uFF1B\u914D\u7F6E\u635F\u574F\u672C\u8EAB\u53E6\u6709\u54CD\u4EAE\u544A\u8B66\uFF09\u3002\u4E0E im-bridge \u76F8\u53CD\u2014\u2014\u9690\u85CF\u4E00\u4E2A**\u5DF2\u5728\u4F7F\u7528**\n \u7684\u901A\u9053\u624D\u4F1A\u9759\u9ED8\u635F\u5BB3\u80FD\u529B\uFF0C\u800C\u4E13\u5C5E\u5DE5\u5177\u7684\u9ED8\u8BA4\u6001\u672C\u5C31\u662F\u9690\u85CF\u3002\n \u25B8 \u914D\u7F6E\u635F\u574F\u7684\u54CD\u4EAE\u544A\u8B66\u53EA\u51FA\u73B0\u4E00\u6B21\uFF08\u6BCF\u8DEF\u5F84\uFF09\uFF0Cdashboard health \u540C\u6837\u80FD\u770B\u5230\u3002\n\n Config:\n { \"exclusiveTools\": [\"acc-diag\"] }\n";
28
+ export declare const CCC_CONFIG_REFERENCE = "\u2550\u2550\u2550 CCC Configuration Reference \u2550\u2550\u2550\n\nCCC-level features are configured in .opencode/serenity.json.\nBelow are all available configuration sections.\n\n\u2500\u2500 1. sessionKeeper.threshold / sessionKeeper.sessionMdMaxKB \u2500\u2500\ncognitive-trajectory-assistant\uFF08COGNITIVE-TRAJECTORY-ASSISTANT \u00B7 CHECKPOINT\uFF09\u63D0\u9192\u673A\u5236\u7684\u79EF\u5206\u9608\u503C\uFF08\u975E headless \u4E3B agent\uFF09\u3002\n\u6309\u5DE5\u5177\u8C03\u7528\u52A0\u6743 + \u8017\u65F6\u8BA1\u5206\uFF1B\u8FBE\u5230\u9608\u503C\u6CE8\u5165\u63D0\u9192\uFF0C\u8981\u6C42\u6A21\u578B\u56DE\u590D ACK \u7801\u3002\n\n Config:\n { \"sessionKeeper\": { \"threshold\": 150, \"sessionMdMaxKB\": 100 } }\n\n \u8BA1\u5206\uFF1Awrite/edit = 3\uFF0Ctask = 10\uFF0Cread/grep/glob/msm \u7B49 = 1\uFF0C\u65F6\u95F4 = 1/\u5206\u949F\n \u9ED8\u8BA4\uFF1A150\n\n \u25B8 sessionMdMaxKB\uFF08v1.31.1 \u65B0\u589E\uFF1Bv1.31.2 100\u2192200\uFF1B\uD83D\uDD34 v1.84.0 200\u2192100\uFF09\uFF1A\n **\u6D3B\u8DC3 SESSION.md \u4F53\u79EF\u4E0A\u9650\uFF08KB\uFF0C\u7F3A\u7701 100\uFF1B0 = \u5173\u95ED\uFF09**\u3002\n \u8D85\u8FC7 \u2192 \u6CE8\u5165 [COGNITIVE-TRAJECTORY-ASSISTANT \u00B7 LOGBOOK COMPACTION] \u63D0\u9192\uFF1A\u6682\u505C\u5F53\u524D\u5DE5\u4F5C \u2192\n \u52A0\u8F7D eap\uFF08praxis eap\uFF09\u2192 **\u6309 EAP \u91CD\u6784\u6574\u4E2A SESSION.md**\uFF08v1.84.0 \u8D77\uFF1B\u65E7\u7248\u662F\u56DB\u6761\u91CD\u5199\u539F\u5219\uFF09\u3002\n \u5224\u636E = EAP \u4E09\u4E2A\u53D8\u91CF\uFF1AE\u2191 \u53D8\u91CF/\u8FB9\u754C/\u6709\u5411\u5173\u7CFB\u5168\u663E\u5F0F \uFF5C R\u2193 \u5E26\u7406\u7531\u4E0E\u88AB\u5426\u9879\uFF0C\u957F\u8BC1\u636E\u94FE\u5916\u79FB\u5230\n references/*.md\uFF08SESSION.md \u7559\u94FE\u63A5\uFF09\uFF5C S\u2191 \u7ED3\u6784\u6BCF\u6B21\u540C\u6837\u91CD\u5EFA\uFF0C\u4E0D\u662F\u65F6\u95F4\u6D41\u6C34\u8D26\u3002\n \u4E24\u6761\u786C\u7EA6\u675F\u968F\u63D0\u9192\u7ED9\u51FA\uFF1A\u4FDD\u7559\u56FA\u5B9A\u6BB5\u843D\u7684**\u987A\u5E8F\u4E0E\u6807\u9898**\uFF08\u4E0E\u7CFB\u7EDF\u63D0\u793A\u8BCD\u5BF9\u9F50\uFF09+ \u4FDD\u7559\u9876\u90E8 frontmatter\u3002\n \u8D85\u9650\u540E\u6BCF\u6B21\u5DE5\u5177\u8C03\u7528\u90FD\u63D0\u9192\uFF1B\u8FDE\u7EED 3 \u6B21\u672A\u91CD\u5199 \u2192 \u5347\u7EA7\u5F3A\u5236\u8BED\u6C14\uFF1B\n \u6587\u4EF6\u56DE\u5230\u9650\u5185 \u2192 \u81EA\u52A8\u505C\u6B62\uFF08\u81EA\u6108\uFF09\u3002\u8F68\u8FF9\u63D0\u9192**\u4E0D\u673A\u68B0\u963B\u65AD\u5DE5\u4F5C**\uFF08\u4E0E rebuild \u63D0\u9192\u540C\u65CF\uFF09\u3002\n\n\u2500\u2500 2. localstore.gitTrack \u2500\u2500\nlocalstore.json \u7684 git \u7B56\u7565\uFF1Aallow \u53EF\u63D0\u4EA4 / deny \u7981\u63D0\u4EA4\uFF08\u9ED8\u8BA4 deny\uFF09\u3002\ndeny \u65F6\u5199\u5165\u81EA\u52A8\u786E\u4FDD .gitignore \u542B\u8BE5\u6587\u4EF6\uFF08\u7269\u7406\u4FDD\u8BC1\uFF09\uFF0Ccontainer_git commit \u4F1A\u68C0\u67E5\u62D2\u7EDD\u3002\n\n Config:\n { \"localstore\": { \"gitTrack\": \"allow\" } }\n\n\u2500\u2500 3. hooks.autoRestoreSession \u2500\u2500\n\u4F1A\u8BDD\u81EA\u52A8\u6062\u590D\uFF08\u9ED8\u8BA4 true\uFF1B\u53D7 events \u95E8\u63A7\u2014\u2014\u4EC5\u6839\u4F1A\u8BDD + \u5DF2\u6709\u5BF9\u8BDD\u5386\u53F2\u624D\u6062\u590D\uFF09\u3002\n\n Config:\n { \"hooks\": { \"autoRestoreSession\": false } }\n\n\u2500\u2500 4. safeMode\uFF08\u9ED1\u540D\u5355 \uFF0B \u5F00\u542F\u671F\u95F4\u9690\u85CF\u7684\u5DE5\u5177\uFF09\u2500\u2500\nsafe-mode \u7531 WebUI \u5F00\u5173\u63A7\u5236\uFF08\u5199 .serenity-safe-on \u6807\u8BB0\uFF09\uFF1B\u9ED1\u540D\u5355\u8DEF\u5F84\u53D7 guards seam \u62E6\u622A\u3002\n\n \u25B8 blacklist\uFF1A\u5199\u8DEF\u5F84\u9ED1\u540D\u5355\uFF08\u540C\u4E0B Config\uFF09\u3002\n \u25B8 hiddenTools\uFF08v1.51.4\uFF0Cowner 2026-10-09 \u4EE4\uFF09\uFF1A**\u4EC5\u5728\u5B89\u5168\u6A21\u5F0F\u5F00\u542F\u671F\u95F4**\u989D\u5916\u4ECE\u6A21\u578B\u5DE5\u5177\n \u6E05\u5355\u9690\u85CF\u7684\u5DE5\u5177\uFF08ACC \u57FA\u7840\u8868\u6052\u9690 bash\uFF09\u3002\u6253\u5F00 safe-mode \u751F\u6548\u3001**\u5173\u6389\u5373\u5168\u90E8\u6062\u590D**\uFF1B\n \u6539\u672C\u952E**\u70ED\u751F\u6548**\uFF08\u4E0B\u4E00\u4E2A pre-step \u91CD\u7B97\uFF0C\u65E0\u9700\u91CD\u542F\uFF09\u3002\u58F0\u660E\u5728 CCC\uFF08D23\uFF09\u2014\u2014ACC \u4EE3\u7801\u91CC\n \u4E0D\u51FA\u73B0\u4EFB\u4F55\u5177\u4F53\u5DE5\u5177\u540D\u3002\n \u26A0\uFE0F \u5199\u4E00\u4E2A**\u672C CCC \u672A\u6CE8\u518C**\u7684\u540D\u5B57\u4F1A\u8BA9**\u6574\u6B21 restrict \u5931\u8D25**\uFF08DSH \u5951\u7EA6\u9010\u5B57\uFF1A\"unknown\n names \u2026 fail\"\uFF09\u21D2 \u6B64\u65F6**\u9000\u5316\u4E3A\u53EA\u9690\u85CF\u57FA\u7840\u8868**\u5E76\u5728\u65E5\u5FD7\u54CD\u4EAE\u62A5\u9519\uFF08\u7EDD\u4E0D\u56E0\u4E00\u4E2A\u9519\u540D\u4E22\u6389\n safe-mode \u7684\u6838\u5FC3\u9690\u85CF\uFF09\u3002\u8BCA\u65AD\uFF1A`AGENT_SESSIONS/.restrict-diag.json` \u7684 `denyByKey`\u3002\n \u26A0\uFE0F \u9690\u85CF = **\u4ECE schema \u79FB\u9664**\uFF08agent \u6839\u672C\u770B\u4E0D\u5230\u8BE5\u5DE5\u5177\uFF09\u21D2 \u522B\u628A skill/\u6587\u6863\u8FD8\u5728\u6559\u7684\u5DE5\u5177\u5199\u8FDB\u6765\u3002\n\n Config:\n { \"safeMode\": { \"blacklist\": [\".secrets/\"], \"hiddenTools\": [\"workflow\", \"job_kill\"] } }\n\n\u2500\u2500 5. \u8F68\u8FF9\u7EA6\u675F.roles\uFF08F4 \u8BA4\u77E5\u5B50\u96C6\u89D2\u8272\uFF09\u2500\u2500\n\u8F68\u8FF9\u7EA6\u675F\u89D2\u8272 = \u5168\u77E5\u5168\u80FD cognitive trajectory \u7684\u4EFB\u610F\u5B50\u96C6\uFF08CCC \u5B9A\u4E49\uFF09\u3002\u6BCF\u89D2\u8272\u72EC\u7ACB\u6A21\u578B + \u53CC\u767D\u540D\u5355\n\uFF08MSM \u767D\u540D\u5355 msms[] \u4E0E\u975E MSM \u5DE5\u5177\u767D\u540D\u5355 tools[]\uFF0C\u767D\u540D\u5355\u5916\u5168\u9690\u85CF\uFF1Bskill \u52A0\u8F7D\u6052\u53EF\u7528\uFF09\u3002\ncognitive trajectory \u7EAA\u5F8B\u5B50\u96C6\uFF08session/keeper/rebuild \u53C2\u4E0E\u9879\uFF09\u9ED8\u8BA4\u5168\u5173 = \u5B8C\u5168\u72EC\u7ACB\u3002\nsystemPrompt \u5185\u8054 \u6216 systemPromptFile\uFF08.md \u5F15\u7528\uFF0C\u63A8\u8350\uFF09\u2014\u2014\u89D2\u8272\u4F1A\u8BDD\u7684\u5B8C\u6574\u4EBA\u683C/\u8FB9\u754C\u63D0\u793A\u8BCD\u3002\nvalidate \u6821\u9A8C / apply \u751F\u6548 / list \u67E5\u770B\uFF1Acontainer_admin config <guide|validate|apply|list>\uFF08\u539F role \u57DF\u5DF2\u5E76\u5165 config\uFF0C\u65E7\u540D\u4F5C\u8FC7\u6E21\u522B\u540D\u4ECD\u53EF\u7528\uFF09\u3002\n\n Config:\n { \"\u8F68\u8FF9\u7EA6\u675F\": { \"roles\": {\n \"qa\": {\n \"model\": \"provider/model\",\n \"msms\": [\"web-search\", \"vlm-describe\"],\n \"tools\": [\"read\", \"grep\", \"glob\"],\n \"systemPromptFile\": \".opencode/skiff/qa.md\"\n } } } }\n\n\u2500\u2500 6. cognitive_trajectory\uFF08\u8F68\u8FF9 + \u5524\u9192\u6CE8\u518C\u8868\uFF0CD58\uFF09\u2500\u2500\nCCC \u7684\u4E00\u6761 cognitive trajectory = \u6301\u4E45\u8EAB\u4F53\uFF08SESSION.md\uFF09+ \u65F6\u95F4\u8F74\uFF08AGENT_SESSIONS/ \u76EE\u5F55 + \u5524\u9192\u6CE8\u518C\u8868\uFF09\u3002\n\u4E00\u4E2A CCC \u5185\u53EF\u591A\u6761\u5E76\u884C\uFF1B\u6761\u76EE\u5168\u90E8\u7531\u4EBA\u7C7B/agent \u663E\u5F0F\u767B\u8BB0\u3002\n\u26A0\uFE0F ACC \u4E0D\u518D\u63D0\u4F9B**\u5468\u671F\u81EA\u5524\u9192**\uFF08\u539F autopilot\uFF0C2026-09-15 \u6574\u6BB5\u9000\u573A\uFF1A\u673A\u5236/\u65F6\u949F/container_admin autopilot\n\u57DF/\u9762\u677F\u533A\u5757\u4E00\u5E76\u5220\u9664\uFF09\u3002\u81EA\u4E3B\u5DE1\u822A\u6539\u7531 CCC \u81EA\u5DF1\u9A71\u52A8\uFF08home-serenity \u4FA7 msm autopilot-round \u6BCF\u8F6E\u81EA\u6392\u4E0B\u4E00\u8F6E\uFF0C\n\u771F\u76F8\u6E90 = S151 SESSION.md \u00A71/\u00A71b/\u00A71c\uFF09\u3002**\u672C\u8F6E\u7684 cognitiveTrajectory.autopilot \u914D\u7F6E\u6BB5\u4FDD\u7559**\uFF08\u89C1\u4E0B\u8868\uFF09\u2014\u2014\n\u5B83\u73B0\u7531 **CCC \u4FA7\u811A\u672C**\u8BFB\u53D6\uFF0CACC \u4E0D\u518D\u6D88\u8D39\u8BE5\u6BB5\u3002\n\u5524\u9192\u6CE8\u518C\u8868\uFF08cognitive_trajectory send-later\uFF09\uFF1A\u5524\u9192 = \u672A\u6765\u65F6\u523B + \u4E00\u6761 message\uFF0C\u53EF\u5524\u9192\u81EA\u5DF1\u6216\u522B\u7684 cognitive trajectory\uFF1B\n\u843D\u70B9 AGENT_SESSIONS/wake-registry.json\uFF0C\u4E2D\u5FC3\u8C03\u5EA6\u5668\u5230\u70B9\u6295\u9012\uFF08fire-and-forget\uFF1B\u65E0\u56DE\u6267\u3001\u65E0\u56DE\u6536\uFF09\u3002\n\u8FD0\u884C\u6001\u8BCA\u65AD\uFF08ACC \u8D1F\u8D23\u4EBA\u4E13\u7528\uFF09\uFF1Aacc-diag\uFF08\u2460 live \u8FD0\u884C\u6001 / \u2460b \u5524\u9192\u65F6\u949F / \u2462 \u5524\u9192\u6CE8\u518C\u8868\uFF09\u3002\n\n\u25B8 cognitiveTrajectory.skills\uFF08v1.44.0\uFF0C**CCC \u7EA7 skill \u4F9B\u7ED9**\uFF1Bowner \u4EE4 2026-09-20\u300C\u8981\u6C42\u5B9E\u73B0\u6211\u7684\u8BC9\u6C42\u2026\u2026\n \u6CE8\u5165\u662F\u52A8\u6001\u6CE8\u5165\u5C31\u884C\uFF1Bcreate \u5148\u4E0D\u89E6\u53D1\u5427\uFF1B**\u8F68\u8FF9\u7EA6\u675F\u4E5F\u652F\u6301**\u300D\uFF09\uFF1A\n **\u672C CCC \u7684\u6BCF\u6761\u8F68\u8FF9\u90FD\u5E26\u8FD9\u4E9B skill**\u2014\u2014\u58F0\u660E\u7684 skill \u5168\u6587\u5728\u8BE5\u8F68\u8FF9**\u88AB\u7ED1\u5B9A\u671F\u95F4**\u6CE8\u5165\u7CFB\u7EDF\u63D0\u793A\u8BCD\n \uFF08**\u52A8\u6001\u6CE8\u5165**\uFF1A\u6BCF\u8BF7\u6C42\u91CD\u65B0\u6C42\u503C\u3001\u4E0D\u7F13\u5B58 \u21D2 \u6539\u914D\u7F6E\u6216\u6539 frontmatter **\u5373\u65F6\u751F\u6548**\uFF0C\u65E0\u9700\u91CD\u65B0 use\u3001\u65E0\u9700\u91CD\u542F\uFF09\u3002\n \u4E24\u6761\u58F0\u660E\u6765\u6E90**\u5E76\u96C6**\uFF08\u4E0D\u662F\u4E8C\u9009\u4E00\uFF09\uFF1A\u672C\u952E **cognitiveTrajectory.skills**\uFF08\u5BB9\u5668\u7ED9\u7684\u5E95\u5EA7\uFF0C**\u5728\u524D**\uFF09\n \uFF0B \u8F68\u8FF9\u81EA\u5DF1 SESSION.md \u9876\u90E8 frontmatter \u7684 skills:\uFF08\u8FD9\u6761\u8F68\u8FF9\u989D\u5916\u7684\uFF0C**\u8FFD\u52A0**\uFF1B\u540C\u540D\u53BB\u91CD\uFF09\u3002\n \u2705 **\u542B \u8F68\u8FF9\u7EA6\u675F\u89D2\u8272\u4F1A\u8BDD**\uFF08\u65C1\u8DEF\u7684\u662F ACC \u8EAB\u4EFD\u4E0E\u7EAA\u5F8B\uFF1Bskill \u662F\"\u5DE5\u4F5C\u8D44\u6599\"\uFF0C\u7167\u7ED9\uFF09\u3002\n \u5B88\u536B\uFF1A\u540D\u5B57\u5148\u8FC7\u5B89\u5168\u6821\u9A8C\u624D\u7528\u4E8E\u62FC\u8DEF\u5F84\uFF08\u9632\u7A7F\u8D8A\uFF09\uFF5C**\u5408\u5E76\u540E**\u7EDF\u4E00 32 KB \u4E0A\u9650\u622A\u65AD\uFF5C\u627E\u4E0D\u5230\u54CD\u4EAE\u5199 [\u7F3A\u5931]\u3002\n \u26A0\uFE0F \u4E0E create **\u65E0\u5173**\uFF08create \u523B\u610F\u4E0D\u593A\u7ED1\u5B9A\uFF0CU6\uFF09\u21D2 \u6CE8\u5165\u7684\u95E8\u662F\"**\u5B58\u5728\u7ED1\u5B9A**\"\uFF08cognitive_trajectory use\uFF09\u3002\n \u5931\u8D25\u8BED\u4E49\uFF1A\u672A\u914D\u7F6E / \u5B57\u6BB5\u7F3A\u5931 / \u914D\u7F6E\u635F\u574F \u21D2 **\u7A7A\u6570\u7EC4**\uFF08= \u65E0 CCC \u7EA7\u4F9B\u7ED9\uFF1B\u8F68\u8FF9\u7EA7\u58F0\u660E\u7167\u65E7\u751F\u6548\uFF09\u3002\n \u5F52\u5C5E\uFF08D23\uFF09\uFF1A**\u673A\u5236\u5728 ACC**\uFF08\u8BFB\u53D6 + \u5408\u5E76 + \u6CE8\u5165 + \u5B88\u536B\uFF09\uFF0C**\u58F0\u660E\u5728 CCC**\uFF08\u672C\u952E\uFF09\u3002\n\n Config:\n { \"cognitiveTrajectory\": {\n \"skills\": [\"acc-session\", \"cce\"], // v1.44.0\uFF1A\u672C CCC \u7684\u6BCF\u6761\u8F68\u8FF9\u90FD\u5E26\uFF08\u542B \u8F68\u8FF9\u7EA6\u675F\u4F1A\u8BDD\uFF09\n \"autopilot\": { // \u539F autopilotTrajectory \u6BB5\uFF0C\u5B57\u6BB5\u4E0D\u53D8\uFF08\u65E7\u952E\u4ECD\u56DE\u9000\u8BFB\uFF09\n \"enabled\": true,\n \"intervalHours\": 2,\n \"session\": \"S151\",\n \"biasProvider\": \"autopilot-bias.ts\",\n \"topPrompt\": \"\u672C\u8F68\u8FF9\u6838\u5FC3\u76EE\u6807/\u7EAA\u5F8B/\u8D28\u91CF\u8981\u6C42\uFF08CCC \u81EA\u586B\uFF0C\u9632\u6F02\u79FB\uFF09\",\n \"avoidWakeHours\": { \"start\": 8, \"end\": 18 }\n } } }\n\n\u2500\u2500 7. weixin\uFF08\u5FAE\u4FE1\u6865 F4c-3\uFF0C\u542B\u6D88\u606F\u8BB0\u5F55 hook\uFF09\u2500\u2500\nCCC \u7EA7\u5FAE\u4FE1\u4E2A\u4EBA\u53F7\u63A5\u5165\uFF08iLink \u534F\u8BAE\uFF09\uFF1Adsh \u4E00\u8FDB\u7A0B\u591A CCC\uFF0C\u6BCF CCC \u72EC\u7ACB\u5BF9\u63A5\u5FAE\u4FE1\u6865\u3002\n\u8D26\u53F7/\u8DEF\u7531/\u5F00\u5173\u5728\u6B64\u6587\u4EF6\uFF1B**bot_token \u51ED\u636E\u5728 CCC localstore credential scope**\n\uFF08\u626B\u7801\u7ED1\u5B9A\u540E\u81EA\u52A8\u5199\u5165\uFF0C\u6C38\u4E0D\u8FDB git \u660E\u6587\u9762\uFF09\u3002\n\u8DEF\u7531 user \u2192 role\uFF1Aexact \u4F18\u5148\uFF0C* \u901A\u914D\u515C\u5E95\uFF1Brole \u5FC5\u987B \u2208 \u8BE5 CCC \u8F68\u8FF9\u7EA6\u675F.roles\u3002\n\u9762\u677F\uFF08WebUI \u8BBE\u7F6E \u2192 \u5FAE\u4FE1\u6865\uFF09\u53EF\u626B\u7801\u7ED1\u5B9A/\u79FB\u9664\u8D26\u53F7/\u7F16\u8F91\u8DEF\u7531\uFF1Bmsm(\"weixin-doctor\", [\"status\"|\"diag\"|\"verify\"|\"guide\"]) \u6392\u67E5 + \u5927\u800C\u5168\u6307\u5357\u3002\u51ED\u636E\u4E3B\u52A8\u67E5\u770B\uFF1Alocalstore get WEIXIN_<ACCOUNT>_TOKEN\u3002\n \u25B8 \u4E3B\u52A8\u53D1\u9001\uFF08v1.31.0\uFF1A**ACC \u5DE5\u5177 im-bridge**\uFF09\uFF1A\u8C03\n im-bridge({channel:\"weixin\", action:\"send\", user:\"<\u522B\u540D|id>\", text:\"<\u6587\u672C>\"}) \u7ED9\u7528\u6237\u53D1\u6D88\u606F\u2014\u2014\n **\u5DE5\u5177\u53EA\u80FD\u64CD\u4F5C\u672C\u4F1A\u8BDD CCC**\uFF08\u65E0 ccc \u53C2\u6570\uFF0C\u9632\u8BEF\u53D1\u4ED6\u5BB9\u5668\uFF09\u2192 weixin-bridge.sendProactiveText \u2192\n \u6210\u529F\u540E\u89E6\u53D1 outgoing hook\uFF08source=\"proactive\"\uFF09\u3002\u6587\u4EF6\u7528 action:\"send-file\" + file:\"<CCC \u5185\u8DEF\u5F84>\"\n \uFF08\u9003\u9038/\u7F3A\u5931/\u8D85 20MB \u62D2\u7EDD\uFF09+ \u53EF\u9009 caption\u3002**\u53EF\u89C1\u6027**\uFF1A\u672C CCC \u914D\u7F6E\u4E86 IM \u901A\u9053\n \uFF08weixin.enabled=true\uFF09\u624D\u51FA\u73B0\u5728\u6A21\u578B\u5DE5\u5177\u6E05\u5355\u91CC\uFF1B\u672A\u914D\u7F6E \u2192 \u7531 guards \u9010 agent\n tools.restrict({deny:['im-bridge']}) \u79FB\u9664\uFF08\u4E0D\u662F\"\u770B\u5F97\u5230\u4F46\u88AB\u62D2\"\uFF09\u3002\u8F68\u8FF9\u7EA6\u675F\u89D2\u8272\u53E6\u9700\u5728\n roles.<role>.tools \u767D\u540D\u5355\u5217\u51FA im-bridge\u3002\n \u5386\u53F2\uFF08v1.30.9~v1.30.x\uFF09\uFF1ACCC \u4FA7 MSM weixin-send\uFF08\u8D70 loopback HTTP \u5165\u53E3 3082\uFF09\u2014\u2014\n v1.31.0 \u5DF2\u9000\u5F79\uFF08\u811A\u672C\u5220\u9664 + \u6CE8\u518C\u8868\u6CE8\u9500\uFF09\uFF1B3082 \u5165\u53E3\u4FDD\u7559\u7ED9**\u975E agent \u8C03\u7528\u8005**\u3002\n\n \u25B8 \uD83D\uDD34\uD83D\uDD34 **\u51FA\u7AD9\u53EA\u6709\u4E00\u6761\u8DEF\uFF1Aagent \u81EA\u5DF1\u8C03 im-bridge**\uFF082026-10-24 \u8D77\uFF0Cowner \u4EE4\uFF09\u3002\n \u6865**\u6C38\u4E0D**\u66FF\u4F60\u56DE\u53D1\u6700\u7EC8\u6587\u672C \u2014\u2014 \u4F60\u8BF4\u4EC0\u4E48\u3001\u8BF4\u51E0\u6761\u3001\u4EC0\u4E48\u65F6\u5019\u8BF4\u3001\u8981\u4E0D\u8981\u4E0D\u8BF4\uFF0C\u5168\u7531\u4F60\u51B3\u5B9A\u3002\n \u26D4 \u4E0D\u8981\u6307\u671B\"\u6211\u628A\u8BDD\u5199\u8FDB\u56DE\u7B54\u91CC\u5C31\u4F1A\u81EA\u52A8\u53D1\u51FA\u53BB\"\uFF1A**\u4E0D\u4F1A**\u3002\u5FC5\u987B\u771F\u7684\u8C03\u5DE5\u5177\u3002\n \u21D2 \u6BCF\u8F6E\u7528\u6237\u6D88\u606F\u672B\u5C3E\u90FD\u4F1A\u9644\u4E00\u884C**\u5DF2\u586B\u597D\u53C2\u6570**\u7684 im-bridge \u8C03\u7528\u6A21\u677F\uFF08\u673A\u5236\u6807\u8BB0\n [serenity:weixin-manual-output]\uFF09\uFF0C\u7167\u5B83\u6539 text \u5373\u53EF\u3002\n \u21D2 \u672C\u8F6E\u7ED3\u675F\u4ECD\u672A\u6210\u529F\u8C03\u7528\uFF08send / send-file\uFF09\u2192 \u4F60\u4F1A\u88AB\u6253\u56DE\uFF08\u22642 \u6B21\uFF0C\u63D0\u793A = \u6807\u8BB0 + \u4E8B\u5B9E\uFF09\uFF1B\n \u8FBE\u4E0A\u9650\u540E**\u7528\u6237\u5C06\u6536\u4E0D\u5230\u4EFB\u4F55\u6D88\u606F**\uFF08\u6CA1\u6709\u4EFB\u4F55\u515C\u5E95\u8F6C\u53D1\uFF09\u3002\n \u21D2 \u6210\u529F\u8C03\u7528\u624D\u7B97\u9001\u8FBE\uFF1B\u5931\u8D25\u8C03\u7528\u4E0D\u7B97\uFF08\u4E0D\u4F1A\u88AB\u5F53\u6210\u672C\u8F6E\u5DF2\u53D1\u9001\uFF09\u3002\n \u26A0\uFE0F **\u524D\u63D0**\uFF1A\u672C\u8F68\u8FF9\u5FC5\u987B\u5728 `.opencode/serenity.json` \u7684 `im.routes` \u91CC\u88AB\u70B9\u540D\uFF0C\u5426\u5219 `im-bridge`\n \u5BF9\u4F60\u4E0D**\u53EF\u89C1**\u2014\u2014\u90A3\u79CD\u60C5\u51B5\u4E0B\u95F8\u95E8\u4E0D\u4F1A\u6253\u56DE\u4F60\uFF08\u6539\u6210\u4E00\u6761\u54CD\u4EAE\u544A\u8B66\uFF0C\u6307\u660E\"\u8BE5\u8F68\u8FF9\u65E0\u53D1\u9001\u6743\"\uFF09\uFF0C\n \u56E0\u4E3A\u6253\u56DE\u4E00\u4E2A\u4F60\u6839\u672C\u6EE1\u8DB3\u4E0D\u4E86\u7684\u8981\u6C42\u53EA\u4F1A\u7A7A\u8F6C\u3002\n\n \u25B8 **\u5DF2\u9000\u5F79\uFF08\u4E0D\u8981\u518D\u914D\uFF0C\u914D\u4E86\u4E5F\u4E0D\u751F\u6548\uFF09**\uFF1A\n \u00B7 `weixin.autoReplyWithLastMessage`\uFF08v1.30.10~2026-10-24\uFF09= \u6865\u66FF agent \u56DE\u53D1\u6700\u7EC8\u6587\u672C\u3002\n **\u88AB\u5426\u7406\u7531**\uFF08owner \u539F\u8BDD\uFF09\uFF1A\u300CautoReply \u5E76\u4E0D\u5408\u9002\uFF0C\u4E3B\u52A8\u6027\u7684 imBridge \u4ECD\u7136\u662F\u66F4\u597D\u7684\u300D\u2014\u2014\n \u5B83\u8BA9 agent \u5931\u53BB\"\u8BF4\u51E0\u6761/\u4F55\u65F6\u8BF4/\u8981\u4E0D\u8981\u4E0D\u8BF4\"\u7684\u51B3\u5B9A\u6743\uFF0C\u800C\u90A3\u6B63\u662F\u4E3B\u52A8\u53D1\u9001\u7684\u4EF7\u503C\u3002\n \u00B7 `weixin.fallbackOnNoSend`\uFF08v1.30.17~2026-10-24\uFF09= \u624B\u52A8\u6A21\u5F0F\u4E0B agent \u6CA1\u53D1\u6210\u529F\u65F6\u6865\u515C\u5E95\u8F6C\u53D1\u3002\n \u5B83\u53EA\u5728\u4E0A\u9762\u90A3\u4E2A\u5F00\u5173 =false \u65F6\u624D\u6709\u610F\u4E49 \u21D2 \u4E00\u8D77\u9000\u5F79\u3002\n \u26A0\uFE0F \u65E7\u914D\u7F6E\u91CC\u6B8B\u7559\u8FD9\u4E24\u4E2A\u952E**\u9759\u9ED8\u5FFD\u7565**\uFF08\u4E0D\u4F1A\u62A5\u9519\uFF0C\u4E5F\u4E0D\u4F1A\u751F\u6548\uFF09\u3002\n\n Config:\n { \"weixin\": {\n \"enabled\": true,\n \"hook\": \"scripts/weixin-message-hook.ts\",\n \"accounts\": [{ \"accountId\": \"wechat-1\", \"name\": \"\u5BB6\u5EAD\u52A9\u624B\", \"enabled\": true }],\n \"routes\": [{ \"user\": \"*\", \"role\": \"my-role\" }]\n } }\n\n \u25B8 weixin.hook\uFF08\u6D88\u606F\u8BB0\u5F55 hook\uFF0Cv1.27.13\uFF09\uFF1A\n \u5FAE\u4FE1\u6865\u6BCF\u6536/\u53D1\u4E00\u6761\u6D88\u606F\u89E6\u53D1\u4E00\u6B21 CCC \u81EA\u5199\u811A\u672C\uFF0C\u7531 CCC \u81EA\u884C\u6301\u4E45\u5316\u4FDD\u5B58\uFF08\u5B58\u54EA/\u5B58\u6210\u4EC0\u4E48\n /\u662F\u5426\u5165\u5E93\u5168\u5F52 CCC\u2014\u2014ACC \u4E0D\u7ED1\u5B9A\u5B58\u50A8\uFF09\u3002\u672A\u914D\u7F6E hook \u2192 \u96F6\u53D8\u5316\uFF08\u4E0D\u89E6\u53D1\uFF09\u3002\n\n \u89E6\u53D1\uFF08\u53CC\u5411\uFF09\uFF1A\n incoming = \u7528\u6237 \u2192 bot\uFF1A\u8DEF\u7531\u547D\u4E2D\u540E\u3001\u5A92\u4F53\u843D\u76D8\u540E\u89E6\u53D1\uFF08\u6587\u672C\u542B\u8BED\u97F3\u8F6C\u5199\uFF1B\u5A92\u4F53\u5E26\u843D\u76D8 relPath\uFF09\n outgoing = bot \u2192 \u7528\u6237\uFF1A\u53D1\u9001\u6210\u529F\u540E\u89E6\u53D1\uFF08reply = \u7528\u6237\u5B9E\u9645\u6536\u5230\u7684\u7EAF\u6587\u672C\uFF0C\u5DF2\u5265\u79BB think\uFF09\n \u00B7 source=\"proactive\" = agent \u7ECF im-bridge \u4E3B\u52A8\u53D1\u8D77\uFF08**2026-10-24 \u8D77\u8FD9\u662F\u552F\u4E00\u503C**\uFF09\n \u00B7 \u5386\u53F2\u503C reply / reply-fallback\uFF08\u6865\u81EA\u52A8\u56DE\u53D1 / \u6865\u515C\u5E95\u8F6C\u53D1\uFF09\u5DF2\u968F\u4E24\u4E2A\u5F00\u5173\u4E00\u8D77\u9000\u5F79\uFF1B\n \u5B58\u91CF\u65E5\u5FD7\u91CC\u4ECD\u80FD\u770B\u5230\u5B83\u4EEC\uFF0C\u90A3\u662F\u5386\u53F2\u4E8B\u5B9E\uFF0C\u4E0D\u662F\u5F53\u524D\u884C\u4E3A\n \u00B7 file\uFF08\u4EC5 send-file \u8865\u8BB0\uFF09\uFF1A{ \"name\": \"\u62A5\u544A.pdf\", \"size\": 12345, \"caption\": \"\u53EF\u9009\" }\n\n \u811A\u672C\u7EA6\u5B9A\uFF08\u4E8B\u4EF6 JSON \u5355\u884C\u7ECF stdin \u4F20\u5165\uFF1Bbun \u4F18\u5148 node \u515C\u5E95\uFF09\uFF1A\n #!/usr/bin/env bun \u6216 node script.js \u2014\u2014 \u8BFB process.stdin \u6574\u6BB5 JSON.parse\n const ev = JSON.parse(await new Response(process.stdin).text())\n ev.event === 'incoming' | 'outgoing'\n\n \u4E8B\u4EF6 schema\uFF08**\u4E0D\u542B\u4EFB\u4F55\u4F1A\u8BDD\u51ED\u636E**\u2014\u2014context_token/bot_token/token/aes_key \u5747\u4E0D\u51FA\u73B0\uFF09\uFF1A\n { \"event\": \"incoming\", \"ts\": 1788359941488, \"cccRoot\": \"/path/ccc\",\n \"accountId\": \"wechat-1\", \"userId\": \"u1@im.wechat\",\n \"sessionId\": \"skiff-weixin-xxx\", \"role\": \"my-role\",\n \"message\": { \"text\": \"\u4F60\u597D\", \"media\": [{ \"kind\": \"image\", \"relPath\": \"_tmp/weixin-inbound/<hash>/img_x.jpg\" }] } }\n { \"event\": \"outgoing\", \"ts\": ..., \"cccRoot\": ..., \"accountId\": ...,\n \"userId\": ..., \"sessionId\": ..., \"role\": ...,\n \"reply\": \"\u5DF2\u8BB0\u5F55\uFF08\u7EAF\u6587\u672C\uFF09\", \"source\": \"proactive\" }\n\n \u793A\u4F8B\u811A\u672C\uFF08\u8FFD\u52A0\u5230\u6309\u65E5\u6587\u4EF6\u2014\u2014\u6301\u4E45\u5316\u5F52 CCC \u81EA\u9009\uFF1A\u6587\u4EF6/DB/\u8FDC\u7AEF\u5747\u53EF\uFF09\uFF1A\n const fs = require('node:fs'); const p = '/path/ccc/AGENT_SESSIONS/_weixin-log.jsonl';\n fs.appendFileSync(p, JSON.stringify(ev) + '\\n');\n\n \u6267\u884C\u8BED\u4E49\uFF08\u65C1\u8DEF\u5BB9\u5FCD\uFF09\uFF1A\u5F02\u6B65 fire-and-forget + 15s \u8D85\u65F6 kill + \u5931\u8D25\u4EC5\u65E5\u5FD7\u2014\u2014\n \u5FAE\u4FE1\u6865\u6D88\u606F\u5904\u7406/\u56DE\u590D\u4E0D\u53D7 hook \u5F71\u54CD\uFF1B\u811A\u672C\u987B\u5728 CCC \u6839\u5185\uFF08\u8DEF\u5F84\u9003\u9038\u62D2\u7EDD\uFF09\u3002\n \u5A92\u4F53 relPath \u6307\u5411 _tmp/weixin-inbound/\uFF08\u4E34\u65F6\u76EE\u5F55\uFF09\u2014\u2014\u9700\u6301\u4E45\u4FDD\u5B58\u5A92\u4F53\u6587\u4EF6\u8BF7\u81EA\u884C copy\u3002\n\n\u2500\u2500 8. \uFF08\u5DF2\u5220\u9664\uFF09exclusiveTools\uFF08\u4E13\u5C5E\u5DE5\u5177\u58F0\u660E\uFF0Cv1.33 \u2192 v1.106.0 \u5220\u9664\uFF09\u2500\u2500\n\uD83D\uDD34 **\u672C\u952E\u5DF2\u4E0D\u5B58\u5728**\uFF08owner 2026-11-01 \u88C1\u300C\u673A\u5236\u6574\u4F53\u5220\u300D\uFF09\u3002\n\u539F\u8BED\u4E49\uFF1AACC \u6CE8\u518C\u4F46\u9ED8\u8BA4\u5BF9\u6240\u6709 CCC \u9690\u85CF\u7684\u5DE5\u5177\uFF0C\u53EA\u6709\u5728 CCC \u914D\u7F6E\u91CC\u70B9\u540D\u624D\u53EF\u89C1\uFF08fail-closed\uFF09\u3002\n**\u5220\u9664\u7406\u7531**\uFF1A\u90A3\u5F20\u8868\u6C38\u8FDC\u53EA\u6709\u4E00\u4E2A\u6210\u5458 acc-diag\uFF0C\u800C\u5B83\u5DF2\u5E76\u5165**\u5E38\u9A7B**\u7684 dashboard \u7684 diag \u52A8\u4F5C\u3002\n\u8868\u7A7A\u4E4B\u540E\u90A3\u4E2A filter \u6052\u56DE\u7A7A\u6570\u7EC4 \u21D2 \u673A\u5236**\u9759\u9ED8\u7A7A\u8F6C\u3001\u4E14\u4EFB\u4F55\u6D4B\u8BD5\u90FD\u8BC1\u4F2A\u4E0D\u4E86\u5B83**\n\uFF08\u4E00\u4E2A\u9A8C\u4E0D\u51FA\u6B7B\u6D3B\u7684\u673A\u5236\u6BD4\u6CA1\u6709\u5B83\u66F4\u574F\uFF1A\u5B83\u63D0\u4F9B\"\u8FD9\u91CC\u8FD8\u6709\u4E00\u5C42\u4FDD\u62A4\"\u7684\u9519\u89C9\uFF09\u3002\n\n \u25B8 \u8981\u8FD0\u884C\u6001\u8BCA\u65AD \u21D2 \u76F4\u63A5\u7528 dashboard \u7684 diag \u52A8\u4F5C\uFF08**\u65E0\u9700\u4EFB\u4F55\u58F0\u660E\uFF0C\u6240\u6709\u8F68\u8FF9\u53EF\u89C1**\uFF09\u3002\n \u25B8 \u65E7\u914D\u7F6E\u91CC\u6B8B\u7559 exclusiveTools \u21D2 **\u9759\u9ED8\u5FFD\u7565**\uFF08schemastery \u975E strict\uFF09\uFF0C\u4E0D\u5F71\u54CD\u52A0\u8F7D\u3002\n \u25B8 \u26A0\uFE0F \u8FDE\u5E26\u540E\u679C\uFF08owner \u5DF2\u77E5\u5E76\u786E\u8BA4\uFF09\uFF1Adashboard \u662F\u5E38\u9A7B\u5DE5\u5177 \u21D2 diag \u6BB5\u5BF9**\u6240\u6709\u8F68\u8FF9**\u53EF\u89C1\uFF0C\n \u800C\u5B83\u7684 live \u4F1A\u8BDD\u6E05\u5355\u662F**\u5168\u90E8 CCC** \u7684\uFF08\u8DE8\u5BB9\u5668\uFF09\u3002\u8FD9\u662F\u300C\u65B9\u6848 C\u300D\u7684\u65E2\u5B9A\u4EE3\u4EF7\uFF0C\u4E0D\u662F\u7F3A\u9677\u3002\n";
29
29
  interface MsmFlag {
30
30
  name: string;
31
31
  type?: string;