@shgroup/dsh-serenity-hooks 1.113.1 → 1.113.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/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-serenity-hooks",
3
- "version": "1.113.1",
3
+ "version": "1.113.2",
4
4
  "main": "lib/index.js",
5
5
  "description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——12 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/localstore/container_admin;另两个 im-bridge/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": {
package/lib/index.js CHANGED
@@ -8865,6 +8865,45 @@ function rememberMessageId(id) {
8865
8865
  }
8866
8866
  }
8867
8867
  /**
8868
+ * 🔴🔴 **该会话是不是 subagent 子会话**(v1.113.2,owner 2026-11-03 裁:
8869
+ * 「subagent 任务书记录到用户语录是不对的,这个需要修掉」)。
8870
+ *
8871
+ * ## 为什么必须排除(判据缺陷,不是规格取舍)
8872
+ *
8873
+ * subagent 的父 agent 用 `createUserMessage(...)` 下发任务书,而宿主 `agent.followup/steer`
8874
+ * **只接受 user 消息** ⇒ 任务书的 `source.kind` **确实是 `'user'`**。
8875
+ * ⇒ 「`kind === 'user'`」这个判据**分不开「真人说的话」与「另一个 agent 说的话」**。
8876
+ *
8877
+ * 实测污染(v1.113.0/1 上线当天,42 条真实记录里 **2 条**):
8878
+ * 正文是"你在宁静号 CCC 做一次只读的历史调研…"、`trajectory: null`。
8879
+ *
8880
+ * ## 判据为什么是两条(⛔ 只判一条会漏)
8881
+ *
8882
+ * | 字段 | 出处 | 谁在用同款判据 |
8883
+ * |---|---|---|
8884
+ * | `header.origin === 'subagent'` | DSH 路由语义(`agent-lookup.ts`) | `seams/context.ts` 的 `shouldAutoRestore` |
8885
+ * | `header.delegationDepth > 0` | 宿主委派深度 | `seams/bootstrap.ts` 的目录窄化 |
8886
+ *
8887
+ * ⇒ **两条都判**:实测两者通常同时在场,但**任一条单独在场时也必须排除**;
8888
+ * 被 resume 的旧持久化 subagent 会话不一定带全两个字段 —— 这正是要双判的理由。
8889
+ *
8890
+ * 🔴 **本函数是判据的单一真相源**:`seams/context.ts` 调它,测试也测它。
8891
+ * ⛔ 不要在两处各写一份 `origin === 'subagent' || depth > 0` —— 那是两份会漂的判据(D230)。
8892
+ *
8893
+ * ⚠️ **边界**:这是"结构性排除整个子会话"。若将来要让 subagent 也进台账,
8894
+ * 那要**换判据**(例如按 `parentSession` 溯源到真主),⛔ 不是在这里放宽 —— 那是另一个裁决。
8895
+ *
8896
+ * @param session 宿主 session(只需 `header`)
8897
+ * @returns 是 subagent ⇒ `true`(调用方应当**不采集**)
8898
+ */
8899
+ function isSubagentSession(session) {
8900
+ const header = session?.header;
8901
+ if (header === null || typeof header !== "object") return false;
8902
+ if (header.origin === "subagent") return true;
8903
+ const depth = header.delegationDepth;
8904
+ return typeof depth === "number" && depth > 0;
8905
+ }
8906
+ /**
8868
8907
  * 一条消息的正文文本(只取 `text` 块,按出现顺序以 `\n` 相连)。
8869
8908
  *
8870
8909
  * 判据与 `session.ts:496` / `guard/seam.ts:70` 同款 —— 不另造一套取文法(否则同一条消息
@@ -9256,7 +9295,7 @@ function registerContext(ctx, opts = {}) {
9256
9295
  * 但我们**不修改** `payload.messages`(那是下游的输入,动它就是行为变更)。
9257
9296
  */
9258
9297
  if (root) try {
9259
- if (readUserQuotesEnabled(root, configPaths)) {
9298
+ if (!isSubagentSession(agent.session) && readUserQuotesEnabled(root, configPaths)) {
9260
9299
  const sessionId = agent.session?.id;
9261
9300
  if (typeof sessionId === "string" && sessionId !== "") recordUserQuotes(root, sessionId, messages);
9262
9301
  }
@@ -153,6 +153,39 @@ export interface UserQuoteWriteResult {
153
153
  }
154
154
  /** 仅测试用:清空去重记忆(⛔ 生产代码不许调) */
155
155
  export declare function __resetUserQuoteDedupeForTest(): void;
156
+ /**
157
+ * 🔴🔴 **该会话是不是 subagent 子会话**(v1.113.2,owner 2026-11-03 裁:
158
+ * 「subagent 任务书记录到用户语录是不对的,这个需要修掉」)。
159
+ *
160
+ * ## 为什么必须排除(判据缺陷,不是规格取舍)
161
+ *
162
+ * subagent 的父 agent 用 `createUserMessage(...)` 下发任务书,而宿主 `agent.followup/steer`
163
+ * **只接受 user 消息** ⇒ 任务书的 `source.kind` **确实是 `'user'`**。
164
+ * ⇒ 「`kind === 'user'`」这个判据**分不开「真人说的话」与「另一个 agent 说的话」**。
165
+ *
166
+ * 实测污染(v1.113.0/1 上线当天,42 条真实记录里 **2 条**):
167
+ * 正文是"你在宁静号 CCC 做一次只读的历史调研…"、`trajectory: null`。
168
+ *
169
+ * ## 判据为什么是两条(⛔ 只判一条会漏)
170
+ *
171
+ * | 字段 | 出处 | 谁在用同款判据 |
172
+ * |---|---|---|
173
+ * | `header.origin === 'subagent'` | DSH 路由语义(`agent-lookup.ts`) | `seams/context.ts` 的 `shouldAutoRestore` |
174
+ * | `header.delegationDepth > 0` | 宿主委派深度 | `seams/bootstrap.ts` 的目录窄化 |
175
+ *
176
+ * ⇒ **两条都判**:实测两者通常同时在场,但**任一条单独在场时也必须排除**;
177
+ * 被 resume 的旧持久化 subagent 会话不一定带全两个字段 —— 这正是要双判的理由。
178
+ *
179
+ * 🔴 **本函数是判据的单一真相源**:`seams/context.ts` 调它,测试也测它。
180
+ * ⛔ 不要在两处各写一份 `origin === 'subagent' || depth > 0` —— 那是两份会漂的判据(D230)。
181
+ *
182
+ * ⚠️ **边界**:这是"结构性排除整个子会话"。若将来要让 subagent 也进台账,
183
+ * 那要**换判据**(例如按 `parentSession` 溯源到真主),⛔ 不是在这里放宽 —— 那是另一个裁决。
184
+ *
185
+ * @param session 宿主 session(只需 `header`)
186
+ * @returns 是 subagent ⇒ `true`(调用方应当**不采集**)
187
+ */
188
+ export declare function isSubagentSession(session: unknown): boolean;
156
189
  /**
157
190
  * 一条消息的正文文本(只取 `text` 块,按出现顺序以 `\n` 相连)。
158
191
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.113.1",
3
+ "version": "1.113.2",
4
4
  "description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:12 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/localstore/container_admin;另两个 im-bridge/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(三档)。",
5
5
  "license": "MIT",
6
6
  "repository": {