@shgroup/dsh-serenity-hooks 1.74.0 → 1.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -7
- package/dsh.plugin.json +2 -2
- package/lib/{ccc-roots-B2t_aM8L.js → ccc-roots-BVxn97dY.js} +1 -1
- package/lib/cro/core.d.ts +10 -0
- package/lib/cro/log.d.ts +54 -4
- package/lib/index.js +387 -97
- package/lib/kernel/ccc.d.ts +3 -2
- package/lib/{message-source-DCpoRHP3.js → message-source-JhN-qyfn.js} +2 -2
- package/lib/{profile-BVt84mbi.js → profile-Cz4oBXlI.js} +148 -16
- package/lib/{settings-D8hlqxua.js → settings-CII0Y597.js} +1 -1
- package/lib/tools/config-docs.d.ts +18 -0
- package/lib/tools/container-admin.d.ts +5 -0
- package/lib/tools/msm/service.d.ts +11 -0
- package/lib/tools/trajectory-constraint-admin.d.ts +2 -2
- package/lib/trajectory/core.d.ts +10 -0
- package/lib/trajectory/policy/files.d.ts +75 -0
- package/lib/trajectory/policy/profile.d.ts +7 -2
- package/lib/trajectory/policy/window.d.ts +4 -4
- package/lib/trajectory/session.d.ts +10 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -252,21 +252,23 @@ my-workspace/ ← 工作区根目录(放一个 .serenity
|
|
|
252
252
|
`source: "reply-fallback"` 表示"AI 没发、插件兜底发的"。
|
|
253
253
|
- **排障**:`msm("weixin-doctor", ["status"|"diag"|"verify"|"guide"])`
|
|
254
254
|
|
|
255
|
-
### 6.3
|
|
255
|
+
### 6.3 轨迹声明(trajectory declaration)
|
|
256
256
|
|
|
257
|
-
|
|
258
|
-
放进去,这条轨迹立刻受约束;删掉它,当场恢复成普通轨迹。
|
|
257
|
+
**轨迹的"声明"只有一个文件**:`trajectory.json`。**目录里有它 ⇒ 这条轨迹受约束**;删掉它,当场恢复成普通轨迹。
|
|
259
258
|
|
|
260
259
|
```jsonc
|
|
261
260
|
// AGENT_SESSIONS/2026-10-19--qa--问答/ ← 轨迹目录(编码 = 目录名固定位置那一段)
|
|
262
|
-
// ├─ SESSION.md
|
|
263
|
-
// ├─ PROMPT.md
|
|
264
|
-
// ├─ trajectory
|
|
261
|
+
// ├─ SESSION.md ← 它自己的身体(工作台就是它,不另建)
|
|
262
|
+
// ├─ PROMPT.md ← 它的章程(推荐;所有轨迹都适用,不限于受约束的轨迹)
|
|
263
|
+
// ├─ trajectory.json ← 声明面(这个文件的存在,就是判据)
|
|
264
|
+
// └─ cro-wake-log.log ← CRO 流水(纯文本;只有真的唤起过才会有)
|
|
265
265
|
{
|
|
266
266
|
"model": "provider/model", // 这条轨迹单独用哪个模型
|
|
267
267
|
"msms": ["web-search", "vlm-describe"], // 它能调哪些小工具(MSM)
|
|
268
268
|
"tools": ["read", "grep", "glob"], // 它能用哪些平台工具
|
|
269
|
-
"cognitiveTrajectory": { "session": true, "keeper": true, "rebuild": true } // 缺省即全 true
|
|
269
|
+
"cognitiveTrajectory": { "session": true, "keeper": true, "rebuild": true }, // 缺省即全 true
|
|
270
|
+
"uid": "my-handle", // 可选:旧的只读标识(身份已归轨迹编码)
|
|
271
|
+
"cro": { "host": "<机器名>" } // 可选:本轨迹的 CRO 程序只许哪台机器跑
|
|
270
272
|
}
|
|
271
273
|
```
|
|
272
274
|
|
|
@@ -275,6 +277,9 @@ my-workspace/ ← 工作区根目录(放一个 .serenity
|
|
|
275
277
|
- 章程写在轨迹目录的 **`PROMPT.md`** 里(跟着轨迹走,归档时一起搬);旧的 `systemPromptFile` 仍被读取,但 `PROMPT.md` 优先
|
|
276
278
|
- `container_admin config validate` 校验,`apply` 才真正生效;两者都**实时读盘**,改完下一轮即生效
|
|
277
279
|
- 微信路由也指向它:`routes: [{ "user": "*", "trajectory": "qa" }]`(**user → 轨迹编码**)
|
|
280
|
+
- 🔴 **旧文件名仍被读取**:`trajectory-constraint.json`(v1.74)/ `skiff.json`(v1.71)都在**读取族**里,
|
|
281
|
+
**写只写 `trajectory.json`**,旧文件**永不自动删**。判据 = **认族不认名**(上游改名、下游写死旧名
|
|
282
|
+
是本仓反复发生的失效形态)。详见 [`docs/trajectory-declaration-file.md`](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/docs/trajectory-declaration-file.md)。
|
|
278
283
|
|
|
279
284
|
### 6.4 对外接入(官方 ACP)
|
|
280
285
|
|
package/dsh.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.75.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
|
-
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 认知轨迹日志与原地重建 + 网页登录入口/IM
|
|
5
|
+
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 认知轨迹日志与原地重建 + 网页登录入口/IM 桥/认知轨迹唤醒注册表。轨迹声明 = 轨迹目录下的 trajectory.json(约束面 + 旧标识 uid + CRO 机器绑定 cro.host;旧名 trajectory-constraint.json / skiff.json 仍在读取族里);轨迹提示词 = 轨迹目录下的 PROMPT.md(一条轨迹「是谁、按什么章程工作」,所有轨迹通用,追加在容器层与质量层之后,不替换它们)。适配 DSH 0.1.7-rc.1 / 0.2.0-rc.1 / 0.2.1-rc.1(三档,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
|
7
7
|
"dsh": ">=0.1.7-rc.1"
|
|
8
8
|
},
|
|
@@ -227,7 +227,7 @@ async function listCccs(ctx, opts = {}) {
|
|
|
227
227
|
if (typeof defaultRoot === "string" && defaultRoot !== "" && !c.roots.includes(defaultRoot)) c.roots.unshift(defaultRoot);
|
|
228
228
|
let rolesOf = null;
|
|
229
229
|
if (opts.withRoles === true) {
|
|
230
|
-
const { listTrajectoryConstraints } = await import("./profile-
|
|
230
|
+
const { listTrajectoryConstraints } = await import("./profile-Cz4oBXlI.js").then((n) => n.i);
|
|
231
231
|
rolesOf = (root) => {
|
|
232
232
|
try {
|
|
233
233
|
return listTrajectoryConstraints(root).map((p) => p.code);
|
package/lib/cro/core.d.ts
CHANGED
|
@@ -296,6 +296,16 @@ export interface CroHostVerdict {
|
|
|
296
296
|
* —— 程序还没跑,没有快照可读。⇒ 只能读文件。(这也是"机制属 ACC"的体现:
|
|
297
297
|
* ACC 在调用用户程序前先判定自己该不该调用。)
|
|
298
298
|
*
|
|
299
|
+
* ## 🆕 2026-10-19 owner 裁 Q2:**声明文件里的 `cro.host` 优先,独立文件回落**
|
|
300
|
+
*
|
|
301
|
+
* 收拢后机器名住在 `<轨迹目录>/trajectory.json` 的 `cro.host` 字段里。
|
|
302
|
+
* 判据(**两代并读,不硬切**):**声明面里有合法 `cro.host` ⇒ 用它;否则回落 `cro-host-binding` 文件**。
|
|
303
|
+
*
|
|
304
|
+
* 🔴 **为什么这里绝不能硬切**(比别处更硬的一条,逐字保留原裁定):
|
|
305
|
+
* 硬切之后,**第二台机器**读到的是「没绑」而不是「绑给了别人」——
|
|
306
|
+
* 两者都导致"不跑",**表面结果相同,但判据退化**(失去可诊断性)。
|
|
307
|
+
* ⇒ 只要还有一台机器可能装着旧版本,两条路都必须能读。
|
|
308
|
+
*
|
|
299
309
|
* @param root CCC 根
|
|
300
310
|
* @param dirName 轨迹目录名
|
|
301
311
|
* @param selfHost 本机机器名(**注入** ⇒ 可测;生产调用方传 `hostname()`)
|
package/lib/cro/log.d.ts
CHANGED
|
@@ -22,12 +22,36 @@
|
|
|
22
22
|
* | 文件 | 谁写 | 主语 | 回答 |
|
|
23
23
|
* |---|---|---|---|
|
|
24
24
|
* | `<轨迹目录>/cro-state.json`(CCC 侧程序自建,名字自定) | **CCC 的 CRO 程序** | 程序 | 「**我判了什么**」(含"没叫"的判定、心跳阈值、环境谓词) |
|
|
25
|
-
* | `<轨迹目录>/cro-wake-log.
|
|
25
|
+
* | `<轨迹目录>/cro-wake-log.log`(**本模块**) | **ACC** | ACC | 「**我把什么送出去了、送成没有**」 |
|
|
26
26
|
*
|
|
27
27
|
* **内容不重叠**:本模块**不复制**判定细节(不存 `lastDecision` / 阈值 / 谓词);
|
|
28
28
|
* 而程序**不可能**知道投递结果(CRO 投递是 fire-and-forget)。
|
|
29
29
|
* ⇒ 两者**互补**:完整审计 = 两者合看(本模块 = 投递面|程序状态 = 判定面)。
|
|
30
30
|
*
|
|
31
|
+
* ## 🔴 形态 = 纯文本行,不是 JSON(owner 2026-10-19 裁 Q1)
|
|
32
|
+
*
|
|
33
|
+
* owner 原话:「**日志不要写 json,不合适,日志直接写纯文本 `.log` 就行**」。
|
|
34
|
+
* ⇒ 一行一条,**tab 分隔**(终端里按制表位对齐,`grep` / `cut` / `awk` 直接可用):
|
|
35
|
+
*
|
|
36
|
+
* ```text
|
|
37
|
+
* # ACC CRO 唤起流水(纯文本 · tab 分隔 · 时间 / 结果 / tick / 方式 / 理由 / 提示词摘要)
|
|
38
|
+
* 2026-10-19T22:15:03+08:00 ok tick=82 已投递(live) reason=心跳:距上次 44m prompt=17:请先整理你的 SESSION.md
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* 🔴 **`#` 开头是注释 / 表头行,解析时跳过** —— 纯文本档案缺了表头,下一个人(或半年后的我)
|
|
42
|
+
* 打开只看到一堆制表符,那是把 R 推给读者。
|
|
43
|
+
* 🔴 **坏行跳过而非报错**(与 JSON 版的 `asEntry()` 同口径):手改 / 半行 / 截断都不得让整档失效。
|
|
44
|
+
*
|
|
45
|
+
* ## 🔴 两代并读(**不硬切**,本容器反复栽过的形态)
|
|
46
|
+
*
|
|
47
|
+
* 旧名 `cro-wake-log.json` **仍然读**(存量轨迹里可能正有那份);
|
|
48
|
+
* **只写新 `.log`**。读侧判据 = **「新档在就只读新档,否则回落旧档」**。
|
|
49
|
+
*
|
|
50
|
+
* 🔴 **首次写入 = 迁移,不是覆盖**:那一刻 `loadCroWakeLog` 读到的仍是旧档条目,
|
|
51
|
+
* 它们与新条目一起过裁剪、一起落进新档 ⇒ **窗内的旧记录不会凭空消失**;
|
|
52
|
+
* 而旧档此后不再被读(新档已在)⇒ **不会重复计入**,也不需要删除动作。
|
|
53
|
+
* ⚠️ 这条**只能靠读源码知道**(写出来的档看不出它继承过谁)⇒ 故在此明写。
|
|
54
|
+
*
|
|
31
55
|
* ## 🔴 轮转(所有者明示「程序化的」)
|
|
32
56
|
*
|
|
33
57
|
* **写入时按窗裁剪**:每次落盘只保留 `at >= now - CRO_LOG_RETENTION_MS` 的条目,
|
|
@@ -46,11 +70,21 @@
|
|
|
46
70
|
* 最坏(某程序每 5min 都叫)⇒ 288 条/天 ⇒ 两天 **≤ ~600 条、< 100 KB** —— 轮转**自带上限**。
|
|
47
71
|
*/
|
|
48
72
|
/** 固定文件名(所有者令:「文件名固定即可」)——与程序自建的 `cro-state.json` 并排、主语分明 */
|
|
49
|
-
export declare const CRO_LOG_FILENAME = "cro-wake-log.
|
|
73
|
+
export declare const CRO_LOG_FILENAME = "cro-wake-log.log";
|
|
74
|
+
/**
|
|
75
|
+
* 🔴 **读取族 = 新名在前、旧名在后**(认族,不认"当前叫什么")。
|
|
76
|
+
*
|
|
77
|
+
* 本容器已两次栽在"上游改名、下游写死旧名":`skiff.json` → `trajectory-constraint.json` 那次,
|
|
78
|
+
* 症状是「写不进去」,而真因是「文件名对不上」,两者在读数上完全不像。
|
|
79
|
+
* ⇒ 上游再改名只往族里加一项。
|
|
80
|
+
*/
|
|
81
|
+
export declare const CRO_LOG_LEGACY_FILENAMES: readonly ["cro-wake-log.json"];
|
|
50
82
|
/** 保留窗 = 2 日(所有者令「只保留仅两日」);**常量** ⇒ 「这个时间是程序化的」 */
|
|
51
83
|
export declare const CRO_LOG_RETENTION_MS: number;
|
|
52
84
|
/** 提示词摘要取前多少字(**只存摘要,不搬第二份全文**——全文属程序那侧的产物) */
|
|
53
85
|
export declare const CRO_PROMPT_HEAD_MAX = 80;
|
|
86
|
+
/** 纯文本档案的表头行(解析时跳过;人打开时先看到它) */
|
|
87
|
+
export declare const CRO_LOG_HEADER = "# ACC CRO \u5524\u8D77\u6D41\u6C34\uFF08\u7EAF\u6587\u672C \u00B7 tab \u5206\u9694 \u00B7 \u65F6\u95F4 / \u7ED3\u679C / tick / \u65B9\u5F0F / \u7406\u7531 / \u63D0\u793A\u8BCD\u6458\u8981\uFF09";
|
|
54
88
|
/** 一条唤起**尝试**(成功与失败**都记**,所有者令 2026-09-20) */
|
|
55
89
|
export interface CroWakeLogEntry {
|
|
56
90
|
/** 时刻(当地 RFC3339 带偏移,遵 D67) */
|
|
@@ -69,7 +103,7 @@ export interface CroWakeLogEntry {
|
|
|
69
103
|
head: string;
|
|
70
104
|
};
|
|
71
105
|
}
|
|
72
|
-
/**
|
|
106
|
+
/** 内存形态(**不再落盘**;读取器与裁剪器都吃它 ⇒ 换载体不改上层契约) */
|
|
73
107
|
export interface CroWakeLog {
|
|
74
108
|
version: number;
|
|
75
109
|
entries: CroWakeLogEntry[];
|
|
@@ -83,8 +117,20 @@ export interface CroWakeLogInput {
|
|
|
83
117
|
/** 唤起提示词原文(本模块只留摘要) */
|
|
84
118
|
prompt?: string;
|
|
85
119
|
}
|
|
86
|
-
/**
|
|
120
|
+
/** 日志绝对路径(**写入目标** = 新名) */
|
|
87
121
|
export declare function croWakeLogPath(root: string, dirName: string): string;
|
|
122
|
+
/** 旧档绝对路径(**只读**,用于两代并读) */
|
|
123
|
+
export declare function croWakeLogLegacyPath(root: string, dirName: string, filename: string): string;
|
|
124
|
+
/** 一条记录 → 纯文本行(tab 分隔、字段带前缀便于人读) */
|
|
125
|
+
export declare function formatCroLogLine(entry: CroWakeLogEntry): string;
|
|
126
|
+
/**
|
|
127
|
+
* 纯文本行 → 记录(**坏行返回 null 而不是抛**)。
|
|
128
|
+
*
|
|
129
|
+
* 判据:字段数不足 / 时间不可解析 / `ok` 标记不认识 ⇒ `null`(跳过该行,其余照读)。
|
|
130
|
+
* 🔴 `at` 必须**可被 `Date.parse` 解析**才收 —— 那是裁剪的前提,
|
|
131
|
+
* 收一条解析不了的时间等于让它在此档里永久驻留(轮转对它失效)。
|
|
132
|
+
*/
|
|
133
|
+
export declare function parseCroLogLine(line: string): CroWakeLogEntry | null;
|
|
88
134
|
/** 提示词摘要(长度 + 前 N 字;超长不截断标记——长度字段本身就是信号) */
|
|
89
135
|
export declare function summarizeCroPrompt(prompt: string | undefined): {
|
|
90
136
|
length: number;
|
|
@@ -92,6 +138,10 @@ export declare function summarizeCroPrompt(prompt: string | undefined): {
|
|
|
92
138
|
};
|
|
93
139
|
/**
|
|
94
140
|
* 读取日志(**永不抛**;读坏 ⇒ 当作空档 + 返回 error 文本)。
|
|
141
|
+
*
|
|
142
|
+
* 🔴 **两代并读的判据**:新档在 ⇒ **只读新档**;否则按族回落旧档。
|
|
143
|
+
* 这样首次写入之后旧档自然退场,**不需要删除动作、也不会重复计入**。
|
|
144
|
+
*
|
|
95
145
|
* @param root CCC 根
|
|
96
146
|
* @param dirName 轨迹目录名
|
|
97
147
|
*/
|