@shgroup/dsh-serenity-hooks 1.72.0 → 1.74.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 -11
- package/dsh.plugin.json +2 -2
- package/lib/accounts-BHQbakUh.js +33 -0
- package/lib/{ccc-Dkoa2oW3.js → ccc-CyYJL4F2.js} +9 -9
- package/lib/{ccc-roots-jZYR2GVE.js → ccc-roots-B2t_aM8L.js} +5 -5
- package/lib/client.js +165 -58
- package/lib/{wake/cro.d.ts → cro/core.d.ts} +3 -3
- package/lib/{wake/cro-guide.d.ts → cro/guide.d.ts} +3 -3
- package/lib/{wake/cro-log.d.ts → cro/log.d.ts} +2 -2
- package/lib/{wake/cro-turns.d.ts → cro/turns.d.ts} +2 -2
- package/lib/guard/seam.d.ts +4 -4
- package/lib/host/effect.d.ts +1 -1
- package/lib/{ilink-DEpmE3yi.js → ilink-BMk2w2KY.js} +1 -1
- package/lib/im/bridge.d.ts +36 -65
- package/lib/im/endpoint.d.ts +3 -3
- package/lib/im/feishu-account.d.ts +92 -0
- package/lib/im/guard.d.ts +1 -1
- package/lib/im/hook.d.ts +1 -1
- package/lib/im/inbound-event.d.ts +162 -0
- package/lib/im/route.d.ts +38 -3
- package/lib/index.d.ts +5 -27
- package/lib/index.js +1089 -1208
- package/lib/kernel/ccc-roots.d.ts +4 -4
- package/lib/kernel/ccc.d.ts +19 -19
- package/lib/kernel/ports.d.ts +3 -5
- package/lib/lib-TxscFKeo.js +119355 -0
- package/lib/{message-source-kVoNK0C5.js → message-source-DCpoRHP3.js} +2 -2
- package/lib/patches/opencode-provider.d.ts +1 -1
- package/lib/{profile-DyMJ_bfr.js → profile-BVt84mbi.js} +68 -65
- package/lib/rolldown-runtime-B4iAMlE-.js +35 -0
- package/lib/{route-f7JlinIt.js → route-COOFLTpU.js} +61 -8
- package/lib/seams/guards.d.ts +14 -14
- package/lib/seams/keeper.d.ts +1 -1
- package/lib/seams/lifecycle.d.ts +2 -2
- package/lib/{settings-lt1i3OZv.js → settings-D8hlqxua.js} +49 -84
- package/lib/skills/resource-index.d.ts +1 -1
- package/lib/surface/faces.d.ts +1 -1
- package/lib/surface/http.d.ts +1 -1
- package/lib/surface/settings.d.ts +7 -13
- package/lib/surface/text.d.ts +72 -0
- package/lib/surface/usage.d.ts +2 -2
- package/lib/tools/config-docs.d.ts +53 -0
- package/lib/tools/container-admin.d.ts +19 -12
- package/lib/tools/msm/service.d.ts +7 -0
- package/lib/tools/trajectory-constraint-admin.d.ts +30 -0
- package/lib/{role/worker/idle.d.ts → trajectory/carrier.d.ts} +12 -2
- package/lib/trajectory/core.d.ts +1 -1
- package/lib/{role/worker → trajectory/delegate}/core.d.ts +7 -1
- package/lib/{role/worker → trajectory/delegate}/preset.d.ts +9 -2
- package/lib/trajectory/policy/profile.d.ts +122 -0
- package/lib/trajectory/policy/rules.d.ts +98 -0
- package/lib/{role/skiff/registry.d.ts → trajectory/policy/window.d.ts} +19 -13
- package/lib/trajectory/prompt.d.ts +12 -12
- package/lib/trajectory/rebuild.d.ts +2 -2
- package/lib/{role/skiff/core.d.ts → trajectory/session.d.ts} +58 -49
- package/package.json +3 -2
- package/lib/role/skiff/config.d.ts +0 -79
- package/lib/role/skiff/debug.d.ts +0 -88
- package/lib/role/skiff/profile.d.ts +0 -115
- package/lib/rolldown-runtime-8H4AJuhK.js +0 -14
- package/lib/tools/skiff-admin.d.ts +0 -30
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* trajectory-constraint-admin.ts — 轨迹约束面逻辑层(公开入口 = `container_admin` 的 `role` 域)
|
|
3
|
+
*
|
|
4
|
+
* 三动作分工(用户拍板 2026-08-28,2026-10-19 重做后语义不变):guide 定义教程 /
|
|
5
|
+
* validate 校验 / list 摘要 / apply 显式应用确认。
|
|
6
|
+
*
|
|
7
|
+
* ## 🔴 2026-10-19 重做后,本文件的**数据源变了**
|
|
8
|
+
*
|
|
9
|
+
* 旧:读 `.opencode/serenity.json` 的 `轨迹约束.roles`(容器级配置表)。
|
|
10
|
+
* 新:读**轨迹目录里的 `trajectory-constraint.json`**(owner:「目录下拥有 `trajectory-constraint.json` 的认知轨迹自动是一个 轨迹约束」)。
|
|
11
|
+
* ⇒ `constraintCount` 的语义 = **本 CCC 有几条 轨迹约束轨迹**;"角色名"这个概念没有了,只有**轨迹编码**。
|
|
12
|
+
*
|
|
13
|
+
* 归属(D23)不变:ACC 提供机制(教程 + 校验 + 列表),**约束内容归 CCC**(写进 `trajectory-constraint.json`)。
|
|
14
|
+
*/
|
|
15
|
+
import type { JsonValue } from '../kernel/json.js';
|
|
16
|
+
/** 轨迹约束 定义教程:概念 / `trajectory-constraint.json` schema / 双白名单 / 轨迹纪律 / 微信路由 */
|
|
17
|
+
export declare const TRAJECTORY_CONSTRAINT_GUIDE = "\u2550\u2550\u2550 \u8F68\u8FF9\u7EA6\u675F Guide (2026-10-19 redesigned) \u2550\u2550\u2550\n\n**A \u8F68\u8FF9\u7EA6\u675F IS a cognitive trajectory \u2014 the one whose directory contains `trajectory-constraint.json`.**\nThat is the whole rule. No role table, no name registry: put the file there and the trajectory\nbecomes a \u8F68\u8FF9\u7EA6\u675F; delete it and it goes back to being an ordinary trajectory (takes effect at once).\n\n AGENT_SESSIONS/<YYYY-MM-DD--<code>--<desc>>/\n \u251C\u2500 SESSION.md \u2190 its persistent body (this IS the workspace \u2014 nothing is auto-created)\n \u251C\u2500 trajectory-constraint.json \u2190 its constraints (this file is what makes it a \u8F68\u8FF9\u7EA6\u675F)\n \u2514\u2500 TRAJECTORY-UID \u2190 legacy, read-only (superseded by the code)\n\n\u2500\u2500 trajectory-constraint.json schema \u2500\u2500\n {\n \"model\": \"provider/model\", // optional; falls back to cheap-worker.defaultModel\n \"tools\": [\"read\",\"grep\",\"msm\",...], // non-MSM toolbar whitelist \u2014 anything not listed is REMOVED from the schema\n \"msms\": [\"msm-a\",\"msm-b\"], // MSM whitelist \u2014 msm exec may only run these; register/deregister always refused\n \"cognitiveTrajectory\": { \"session\": true, \"keeper\": true, \"rebuild\": true }, // defaults TRUE (see below)\n \"systemPromptFile\": \".opencode/skiff/<role>.md\", // recommended: relative to CCC root, hot-reloads on save\n \"systemPrompt\": \"...\" // inline fallback; systemPromptFile wins when both are set\n }\n\n\u2500\u2500 Two whitelists, both default-deny \u2500\u2500\n - `tools: []` + non-empty `msms` = pure-MSM \u8F68\u8FF9\u7EA6\u675F (the usual knowledge-QA shape)\n - non-empty `msms` \u21D2 the `msm` tool is added automatically (the only entry point for MSMs)\n - anything outside both lists is invisible in the schema, not merely rejected at call time\n\n\u2500\u2500 cognitiveTrajectory: why the defaults are TRUE \u2500\u2500\n The workspace of a \u8F68\u8FF9\u7EA6\u675F is its own SESSION.md. Setting these to false would cut it off from\n its own body, so `session`/`keeper`/`rebuild` all default to true. Set false explicitly only\n when you deliberately want that participation off.\n\n\u2500\u2500 WeChat routing: user \u2192 trajectory code \u2500\u2500\n `weixin.routes`: `[{ \"user\": \"<wx id or *>\", \"trajectory\": \"<code>\" }]`\n A route pointing at a code with no such trajectory is a hard error (the message is NOT delivered).\n A trajectory WITHOUT `trajectory-constraint.json` is still a legal target \u2014 it is just an ordinary trajectory.\n\n\u2500\u2500 Operating it \u2500\u2500\n Everything is read live: saving `trajectory-constraint.json` takes effect on the next turn, no restart.\n (The prompt FILE hot-reloads by mtime; the JSON itself is re-read every turn.)\n After editing, run container_admin config apply for an explicit validation + confirmation pass.\n Skill loading is always available to \u8F68\u8FF9\u7EA6\u675F sessions (skills are not whitelisted \u2014 they are read-only knowledge).";
|
|
18
|
+
/** 校验当前 CCC 的 轨迹约束面:msms 均已注册 / model ∈ cheap-worker.models / 提示词非空 */
|
|
19
|
+
export declare function validateTrajectoryConstraint(root: string): JsonValue;
|
|
20
|
+
/** 列出当前 CCC 的轨迹约束(编码 / 模型 / msms / tools / 纪律摘要 / 提示词来源) */
|
|
21
|
+
export declare function listTrajectoryConstraintSummary(root: string): JsonValue;
|
|
22
|
+
/**
|
|
23
|
+
* 应用当前 轨迹约束 配置(S142 用户:改了 json 应该有个生效机制)。
|
|
24
|
+
*
|
|
25
|
+
* 语义:约束面是**每轮实时读取**的 ⇒ apply 不是"推送",而是**显式校验 + 应用确认**:
|
|
26
|
+
* ① 校验合法(复用 validate:msms 注册 / model 白名单 / 提示词非空)
|
|
27
|
+
* ② 非法 → 报告问题清单,不应用(提示修复后重跑 apply)
|
|
28
|
+
* ③ 合法 → 应用确认:绑定 CCC + 轨迹清单 + 说明(下一轮即生效)
|
|
29
|
+
*/
|
|
30
|
+
export declare function applyTrajectoryConstraint(root: string): JsonValue;
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* trajectory/carrier.ts — 等待 agent 空闲(含销毁竞速,S142 review F-08)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* ## 为什么在 `trajectory/` 而不是某个委派子域(S14,2026-10-19,轨迹中心重构)
|
|
5
|
+
*
|
|
6
|
+
* 它的两个消费者分属**不同的层**:`trajectory/session.ts`(轨迹的载体管理)与
|
|
7
|
+
* `cheap-worker`(轨迹 × 轨迹的委派)。⇒ 它**不是哪一家的私有件**,
|
|
8
|
+
* 而是"载体这一轮跑完没有"这个问题的**公共原语**——凡与载体打交道的地方都可能在用。
|
|
9
|
+
*
|
|
10
|
+
* 🔴 名字从 `idle` 改为 `carrier`:`idle` 描述的是**状态**(宿主 agent 空闲),
|
|
11
|
+
* 而本模块回答的是**关于载体的问题**(它空闲了/它被销毁了/会话先没了)。
|
|
12
|
+
* 三个结算条件(见下)里有两条与"空闲"无关 —— 名字取窄了会误导调用方以为只需等 idle。
|
|
13
|
+
*
|
|
14
|
+
* 为什么单独成模块:`askTrajectory`(问答)与 `cheap-worker`(杂工循环)都要"等这一轮做完",
|
|
5
15
|
* 此前各自复制了一份只监听 `agent/status → idle` 的实现。该实现有一个静默挂死:
|
|
6
16
|
* **agent 先被销毁(会话关闭/进程回收/显式 dispose)就永远不会再发 idle 事件**,
|
|
7
17
|
* 等待方 Promise 永不结算 → 问答/杂工永久卡住(宿主的 disposal 语义:
|
package/lib/trajectory/core.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*
|
|
33
33
|
* ⚠️ 由此产生一条**必须成立**的配套:`readAllSessions` **跳过 `_` 前缀目录**。
|
|
34
34
|
* 否则归档后的轨迹会继续出现在清单里,"归档"就不是归档了(历史 bug:`_weixin-logs` /
|
|
35
|
-
* `
|
|
35
|
+
* `_轨迹约束-logs` / `_corpus` 曾被当成轨迹列出来)。
|
|
36
36
|
*/
|
|
37
37
|
/**
|
|
38
38
|
* `cognitive_trajectory` 工具的动作集合(v1.33,S142 §32 用户裁决后的收敛结果)。
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* trajectory/delegate/core.ts — cheap-worker(杂工)纯逻辑层(零 DSH 依赖,可独立单测)
|
|
3
3
|
*
|
|
4
4
|
* 🆕 2026-10-14(owner 令「删除后台运行能力」):**进度文件 / stop token / 轮次循环**整族已退场 ——
|
|
5
5
|
* 它们**只**服务于 background 模式。本模块现存 = 前台委派真正需要的三件:
|
|
6
6
|
* 模型串解析 / 白名单校验 / provider 可用性判读(+ 使用指引文本)。
|
|
7
|
+
*
|
|
8
|
+
* ## S14(2026-10-19,轨迹中心重构):此前位于 `role/worker/` 下(该目录已消失)
|
|
9
|
+
*
|
|
10
|
+
* 落点 = `trajectory/delegate/`。判据(判读表 §3.1):它是**轨迹 × 轨迹**那种合法形态 ——
|
|
11
|
+
* 主语是「主轨迹把活交给子 agent」,既不是某一条轨迹的切面,也不是容器宪法。
|
|
12
|
+
* ⚠️ 它**不属于** `policy/`:policy 管"这条轨迹允许什么",本模块管"一条轨迹怎么把活派出去"。
|
|
7
13
|
*/
|
|
8
14
|
/** 解析 model 字符串(provider/model)→ {provider, model};无 / 视为 model-only */
|
|
9
15
|
export declare function splitModel(model: string): {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* trajectory/delegate/preset.ts — cheap-worker worker 的 preset 继承 + 工具面收窄(纯函数,可单测)
|
|
3
3
|
*
|
|
4
4
|
* v1.24.0:loop → cheap-worker 重命名。对齐 subagent 先例(applyChildComposition →
|
|
5
5
|
* agentPresets.composeFrom):cheap-worker worker 在创建窗口内 join 发起方 agent 的 standing
|
|
@@ -16,7 +16,14 @@
|
|
|
16
16
|
* (在 agent 未发布前执行 composeFrom + restrict,失败由创建事务回滚)。
|
|
17
17
|
*
|
|
18
18
|
* 仅依赖 cordis 的 Context 类型(type-only,运行时擦除)——保持可被 vitest
|
|
19
|
-
* 直接加载(与 kernel/ccc.ts /
|
|
19
|
+
* 直接加载(与 kernel/ccc.ts / trajectory/delegate/core.ts 同级的纯模块约定)。
|
|
20
|
+
*
|
|
21
|
+
* ## S14(2026-10-19,轨迹中心重构):此前位于 `role/worker/` 下(该目录已消失)
|
|
22
|
+
*
|
|
23
|
+
* 落点 = `trajectory/delegate/`,与 `./core.ts` 同域。这里的"preset 继承"是**委派关系**的
|
|
24
|
+
* 一部分(子 agent join 父的 standing preset),主语仍是"主轨迹怎么把活派出去"。
|
|
25
|
+
* 🔴 递归防护(`deny: ['cheap-worker']`)也住在这里 —— 它是委派**方向的守卫**,不是容器宪法:
|
|
26
|
+
* 换一条轨迹,它照样生效,但它约束的是"派出去之后再派"这件事。
|
|
20
27
|
*/
|
|
21
28
|
import type { Context } from 'cordis';
|
|
22
29
|
/** 从父 agent ctx 解析 preset 继承的创建期组合。 */
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* trajectory/policy/profile.ts — **轨迹约束的唯一判据**:目录下有 `trajectory-constraint.json` 的认知轨迹(零 DSH 依赖,可独立单测)
|
|
3
|
+
*
|
|
4
|
+
* ## 🔴 owner 2026-10-19 重做令(逐字,本文件存在的全部理由)
|
|
5
|
+
*
|
|
6
|
+
* > 「轨迹约束 复杂的约束和提示词体系都干掉,改为这样的实现:
|
|
7
|
+
* > **轨迹约束本身是认知轨迹的一个特殊情况,即目录下拥有 `trajectory-constraint.json` 的认知轨迹自动是一个 轨迹约束**
|
|
8
|
+
* > (json 里配置上个版本就有的各种约束),**会话跑在认知轨迹上且发现 `trajectory-constraint.json`,则运行时实现各类约束**」
|
|
9
|
+
*
|
|
10
|
+
* ## 旧模型 → 新模型(**一条判据取代四条**)
|
|
11
|
+
*
|
|
12
|
+
* | 项 | 旧 | 新 |
|
|
13
|
+
* |---|---|---|
|
|
14
|
+
* | 轨迹约束是什么 | `serenity.json` 的 `轨迹约束.roles.<name>` 一条配置 | **轨迹目录里有 `trajectory-constraint.json`** |
|
|
15
|
+
* | 怎么认出 轨迹约束会话 | dsh sessionId 前缀 `轨迹约束-` | **它绑定的轨迹有 `trajectory-constraint.json`** |
|
|
16
|
+
* | 工作台从哪来 | `ensureTrajectorySession` 另建一个 SESSION | **就是该轨迹自己的 SESSION.md** |
|
|
17
|
+
* | 身份 | 角色名 | **轨迹编码**(`trajectory/core.ts` 的 `parseTrajectoryCode`) |
|
|
18
|
+
*
|
|
19
|
+
* ⇒ 收益(owner:「理解难度大幅下降」的实际内容):四个各自会漂的机制收敛为**一条文件存在性判据**。
|
|
20
|
+
* 删掉 `trajectory-constraint.json` ⇒ 该轨迹**当场**退化为普通轨迹(工具面、提示词、keeper 全部恢复默认)。
|
|
21
|
+
*
|
|
22
|
+
* ## 归属(D23)
|
|
23
|
+
* **机制在 ACC**(文件叫什么、怎么读、怎么判、缺省值、如何施加约束);
|
|
24
|
+
* **内容在 CCC**(`trajectory-constraint.json` 里填什么:模型、白名单、提示词路径)。
|
|
25
|
+
* ⇒ ACC 代码里**不出现任何具体角色名**,也不读 `serenity.json` 的 轨迹约束段(该段已退役)。
|
|
26
|
+
*
|
|
27
|
+
* ## S12(2026-10-19,轨迹中心重构):此前位于 `role/轨迹约束/` 下(该目录已随本重构消失)
|
|
28
|
+
*
|
|
29
|
+
* 落点 = `trajectory/policy/`。判据(判读表 §3.1):本文件判的是**某条轨迹的约束面**,
|
|
30
|
+
* 主语是轨迹 ⇒ 它一直就是轨迹切面,只是旧目录把它挂在"角色"这个**平行概念**下。
|
|
31
|
+
* ⚠️ **文件名 `profile` 与 `trajectory-constraint.json` / `TrajectoryConstraint` 等符号名一律不动**:
|
|
32
|
+
* 那是有具体指称的东西(一个固定文件名 + 它的解析结果),不是组织单位。
|
|
33
|
+
*/
|
|
34
|
+
/** `trajectory-constraint.json` 的固定文件名(**判据就是它存在**——不是目录名前缀,也不是配置里的一行) */
|
|
35
|
+
export declare const TRAJECTORY_CONSTRAINT_FILENAME = "trajectory-constraint.json";
|
|
36
|
+
/**
|
|
37
|
+
* 一个 轨迹约束轨迹的**完整约束面**(= 旧 `轨迹约束.roles.<name>` 那套,整体搬进轨迹目录)。
|
|
38
|
+
*
|
|
39
|
+
* ⚠️ 与旧配置的**一处有意语义翻转**(R↓,别当成"顺手改默认值"):
|
|
40
|
+
* `cognitiveTrajectory.*` 在旧模型里**缺省全 false**("轨迹约束 完全独立"),理由是
|
|
41
|
+
* **它的工作台是外挂的**(`ensureTrajectorySession` 另建一个 SESSION,不由轨迹承载)。
|
|
42
|
+
* 新模型里**工作台就是它自己的 SESSION.md** ⇒ 全 false 会让它拿不到自己的身体
|
|
43
|
+
* ⇒ **缺省翻成 true**。这不是偏好问题,是两个模型的结构差。
|
|
44
|
+
*/
|
|
45
|
+
export interface TrajectoryConstraint {
|
|
46
|
+
/** 该约束面所属轨迹的目录名(`YYYY-MM-DD--<code>[--<desc>]`) */
|
|
47
|
+
dirName: string;
|
|
48
|
+
/** 轨迹编码(= 唯一标识;见 `parseTrajectoryCode`) */
|
|
49
|
+
code: string;
|
|
50
|
+
/** `trajectory-constraint.json` 的绝对路径 */
|
|
51
|
+
path: string;
|
|
52
|
+
/** 模型(`provider/model`);缺省回退 `cheap-worker.defaultModel` */
|
|
53
|
+
model?: string;
|
|
54
|
+
/** 非 MSM 工具白名单(白名单外**从 schema 移除**,不是"看得见调不动") */
|
|
55
|
+
tools: string[];
|
|
56
|
+
/** MSM 白名单(`msm()` 单入口内再过滤) */
|
|
57
|
+
msms: string[];
|
|
58
|
+
/** 轨迹纪律参与项(**缺省全 true**,见上方 R↓) */
|
|
59
|
+
cognitiveTrajectory: {
|
|
60
|
+
session: boolean;
|
|
61
|
+
keeper: boolean;
|
|
62
|
+
rebuild: boolean;
|
|
63
|
+
};
|
|
64
|
+
/** 内嵌提示词(`systemPromptFile` 为空时用) */
|
|
65
|
+
systemPrompt?: string;
|
|
66
|
+
/** 提示词文件(相对 CCC 根;**优先于** `systemPrompt`) */
|
|
67
|
+
systemPromptFile?: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 读一个目录下的 `trajectory-constraint.json`(**纯读,不施加约束**)。
|
|
71
|
+
*
|
|
72
|
+
* @param trajectoryDir 轨迹目录绝对路径
|
|
73
|
+
* @param root CCC 根(仅用于 `systemPromptFile` 的逃逸拒绝)
|
|
74
|
+
* @returns 归一后的约束面;**无该文件 → `null`(= 这不是 轨迹约束,常态,不是错误)**
|
|
75
|
+
*
|
|
76
|
+
* ⚠️ **形态容错**:数组元素非字符串 → 丢弃该项(不整份作废);`cognitiveTrajectory`
|
|
77
|
+
* 缺项 → 各自取 **true**(见 R↓);`model` 空白 → undefined(回退缺省)。
|
|
78
|
+
* 坏 JSON ⇒ 告警 + `null`(**按"不是 轨迹约束"处理**:宁可让它退回普通轨迹,也不要带着
|
|
79
|
+
* 半份读不懂的权限面运行)。
|
|
80
|
+
*/
|
|
81
|
+
export declare function readTrajectoryConstraintAt(trajectoryDir: string, root: string): TrajectoryConstraint | null;
|
|
82
|
+
/**
|
|
83
|
+
* 按**轨迹编码**解析 轨迹约束面(`list`/`admin`/调试页/路由解析用)。
|
|
84
|
+
*
|
|
85
|
+
* @returns 约束面;轨迹不存在 / 无 `trajectory-constraint.json` → `null`
|
|
86
|
+
*/
|
|
87
|
+
export declare function readTrajectoryConstraintByCode(root: string, code: string): TrajectoryConstraint | null;
|
|
88
|
+
/** 扫全部活跃轨迹,返回全部 轨迹约束。**顺序按目录名**(确定性,便于对读)。 */
|
|
89
|
+
export declare function listTrajectoryConstraints(root: string): TrajectoryConstraint[];
|
|
90
|
+
/**
|
|
91
|
+
* 编码 → 轨迹目录名(活跃轨迹内)。找不到 → `null`。
|
|
92
|
+
*
|
|
93
|
+
* ⚠️ 与 `findSession` 的分工:这里**只按编码精确**匹配(不做模糊),
|
|
94
|
+
* 因为它的调用方(路由 / 约束施加)要的是**确定性**,模糊匹配会把"手抖打错的名字"
|
|
95
|
+
* 静默投到一条相近的轨迹上——那正是最难查的一类串味。
|
|
96
|
+
*/
|
|
97
|
+
export declare function findDirNameByCode(root: string, code: string): string | null;
|
|
98
|
+
/**
|
|
99
|
+
* **会话级**判据(J2):这个 dsh 会话是不是 轨迹约束会话 —— 唯一入口。
|
|
100
|
+
*
|
|
101
|
+
* 判据 = **它绑定的轨迹有 `trajectory-constraint.json`**(不是 sessionId 前缀,也不是配置里有没有角色)。
|
|
102
|
+
*
|
|
103
|
+
* ## 为什么"绑定的轨迹"从两个来源取(R↓,一个失败模式)
|
|
104
|
+
* ① **持久绑定**(`readLastBound`,宿主存储域/`.bindings.json`)—— 权威,跨重启成立;
|
|
105
|
+
* ② **内存注册表**(`trajectory/policy/window`)—— 覆盖绑定的**窗口期**(轨迹刚定、bound 还没落盘)。
|
|
106
|
+
* ⇒ 只取 ① 会在建会话的第一轮判成"不是 轨迹约束"(工具面不收窄,模型看见不该有的工具);
|
|
107
|
+
* 只取 ② 会在进程重启后全判成"不是"(轨迹约束 失去约束,**权限面静默放开**)。
|
|
108
|
+
* ⇒ **两来源并取**,都不中才 `null`。
|
|
109
|
+
*
|
|
110
|
+
* @param root CCC 根
|
|
111
|
+
* @param sessionId dsh 会话 id
|
|
112
|
+
* @param boundDirName 调用方已解析的绑定目录名(可选;给了就省一次读绑定)
|
|
113
|
+
* @returns 约束面;不是 轨迹约束会话 → `null`
|
|
114
|
+
*/
|
|
115
|
+
export declare function trajectoryConstraintForSession(root: string, sessionId: string | undefined, boundDirName?: string | null): TrajectoryConstraint | null;
|
|
116
|
+
/**
|
|
117
|
+
* 该 dsh 会话**是不是** 轨迹约束会话(布尔形态的 `trajectoryConstraintForSession`)。
|
|
118
|
+
*
|
|
119
|
+
* 存在的理由:调用点很多只要一个"是/不是"(seams 的旁路判定),
|
|
120
|
+
* 让它们各自写 `!== null` 会把判据散开;**判据只能有一个入口**。
|
|
121
|
+
*/
|
|
122
|
+
export declare function isTrajectoryConstrained(root: string, sessionId: string | undefined): boolean;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* trajectory/policy/rules.ts — 轨迹约束面的**纯逻辑助手**(零 DSH 依赖,可独立单测)
|
|
3
|
+
*
|
|
4
|
+
* ## 2026-10-19 重做后的职责边界(R↓,别再混起来)
|
|
5
|
+
*
|
|
6
|
+
* | 模块 | 管什么 |
|
|
7
|
+
* |---|---|
|
|
8
|
+
* | `./profile.ts` | **判据 + 读盘**("这是不是 轨迹约束"、"约束面是什么") |
|
|
9
|
+
* | `./rules.ts`(本文件) | **从约束面派生出的纯函数**(白名单集合、提示词读取器、基础提示词文本) |
|
|
10
|
+
* | `../session-create.ts` | 会话创建/复用、提问、守门查询 |
|
|
11
|
+
*
|
|
12
|
+
* ⇒ 本文件**不再读 `serenity.json`**:`轨迹约束.roles` 整段已退役(owner 2026-10-19 重做)。
|
|
13
|
+
* 它只接收一个已解析好的 `TrajectoryConstraint`,因此**不涉及任何 IO**(除提示词文件,那是刻意懒读的)。
|
|
14
|
+
*
|
|
15
|
+
* ## S12(2026-10-19,轨迹中心重构)
|
|
16
|
+
*
|
|
17
|
+
* 原名 `role/轨迹约束/config.ts`。改名理由(框架 §6.3「角色不是一个概念,是一段历史」):
|
|
18
|
+
* 它派生的是**某条轨迹的约束面**,与"配置读取"无关(本文件零配置读取,见上一段)
|
|
19
|
+
* ⇒ `config` 这个名字描述的是**它曾经的样子**,`rules` 描述它**现在做的事**。
|
|
20
|
+
*/
|
|
21
|
+
import type { TrajectoryConstraint } from './profile.js';
|
|
22
|
+
/** 白名单推导 ────────────────────────────────────────────────────────────── */
|
|
23
|
+
/** 提示词来源提示串(`apply` 回执与面板共用;避免两处措辞漂) */
|
|
24
|
+
export declare const TRAJECTORY_CONSTRAINT_HINT = "systemPromptFile hot-reloads by mtime; the rest of trajectory-constraint.json is re-read every turn";
|
|
25
|
+
/**
|
|
26
|
+
* 该 轨迹约束会话**可见**的工具面(tools ∪ `msm`)。
|
|
27
|
+
*
|
|
28
|
+
* 🔴 `msm` 为什么自动加入:`msms` 非空意味着这个 轨迹约束 **有 MSM 通道**,
|
|
29
|
+
* 而 MSM 的唯一合法调用入口是 `msm` 工具(单入口纪律)——不给它 `msm` 就等于
|
|
30
|
+
* 声明了一堆调不动的能力。⚠️ 这是**并集**,不是覆盖:`tools` 里显式写的照旧生效。
|
|
31
|
+
*/
|
|
32
|
+
export declare function profileToolWhitelist(profile: TrajectoryConstraint | null | undefined): Set<string>;
|
|
33
|
+
/** 该 轨迹约束会话可 exec 的 MSM 白名单(`msm` 工具内部再过滤;独立于工具白名单) */
|
|
34
|
+
export declare function profileMsmWhitelist(profile: TrajectoryConstraint | null | undefined): Set<string>;
|
|
35
|
+
/** 轨迹纪律参与项(`profile` 缺省已在 `readTrajectoryConstraintAt` 归一为全 true) */
|
|
36
|
+
export declare function constraintCognitiveTrajectory(profile: TrajectoryConstraint | null | undefined): {
|
|
37
|
+
session: boolean;
|
|
38
|
+
keeper: boolean;
|
|
39
|
+
rebuild: boolean;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* 解析约束面声明的**系统提示词全文**(一次性读取;`create` / `validate` / `list` 用)。
|
|
43
|
+
*
|
|
44
|
+
* 顺序:`systemPromptFile`(**推荐**:超长提示词在 JSON 里内嵌不可读)→ 内嵌 `systemPrompt` → 空串。
|
|
45
|
+
* 文件缺失/逃逸 ⇒ **抛错**(调用方 catch 降级;`validate` 据此报 issue)。
|
|
46
|
+
*
|
|
47
|
+
* ⚠️ 热路径**不用**它(那会用每次工具调用去读盘)——热路径用 `createProfilePromptReader`。
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveConstraintSystemPrompt(root: string, profile: TrajectoryConstraint | null | undefined): string;
|
|
50
|
+
/**
|
|
51
|
+
* 提示词来源(`list`/`validate` 展示用)。
|
|
52
|
+
*
|
|
53
|
+
* 🔴 **2026-10-19 修(T4 的漏网面)**:v1.72.0 起提示词有两代来源——**新形态**
|
|
54
|
+
* 是轨迹目录里的 `PROMPT.md`(`trajectory/prompt.ts`,**优先**),旧形态才是
|
|
55
|
+
* `systemPromptFile` / `systemPrompt`。本函数原先只认旧形态 ⇒ 两条只写了 `PROMPT.md`
|
|
56
|
+
* 的轨迹在 `container_admin config list` 里恒显示 `promptSource: 'none'`。
|
|
57
|
+
*
|
|
58
|
+
* 那是**读数器过时**,不是配置缺失:`validate` 侧早已按两条来源判(见
|
|
59
|
+
* `trajectory-constraint-admin.ts` 的 `hasTrajectoryPromptOrLegacy`),而 `list` 侧漏了。
|
|
60
|
+
* ⇒ 返 **四种**值,把"有章程但来源是新形态"这一格单独说出来。
|
|
61
|
+
*
|
|
62
|
+
* @param hasPromptFile 该轨迹目录下**是否真有** `PROMPT.md`(调用方查,本函数不做 IO)
|
|
63
|
+
*/
|
|
64
|
+
export declare function constraintSystemPromptSource(profile: TrajectoryConstraint | null | undefined, hasPromptFile?: boolean): 'trajectory-file' | 'file' | 'inline' | 'none';
|
|
65
|
+
/**
|
|
66
|
+
* 提示词**读取器**(长期热更新;改文件即生效,无需重启)。
|
|
67
|
+
*
|
|
68
|
+
* 为什么返回函数而不是字符串(R↓,实证代价):旧实现在创建时把提示词**快照**进系统提示词段闭包
|
|
69
|
+
* ⇒ CCC 改了提示词文件必须重启 dsh web 才生效(实测:改完 18KB 提示词,live agent 仍用旧文本)。
|
|
70
|
+
* 现形态由系统提示词段的 `text()` **每轮调用**本读取器:
|
|
71
|
+
* - `systemPromptFile`:按 **mtime + size** 缓存重读(命中缓存零 IO;未变不解析)
|
|
72
|
+
* - 内嵌 `systemPrompt`:静态(改 JSON 仍需重载配置,这与文件热更的差别是**必然**的 —— 文件有 mtime,JSON 没有)
|
|
73
|
+
* - 读取失败:返回**上次成功内容**(⛔ 绝不返回空——空提示词会让角色失去人格与纪律),并按标签去重告警一次
|
|
74
|
+
*
|
|
75
|
+
* @param root CCC 根
|
|
76
|
+
* @param profile 约束面
|
|
77
|
+
*/
|
|
78
|
+
export declare function createProfilePromptReader(root: string, profile: TrajectoryConstraint | null | undefined): () => string;
|
|
79
|
+
/**
|
|
80
|
+
* 轨迹约束 基础提示词(dsp 只给这部分;CCC 的 `systemPrompt` 段由调用方拼接)。
|
|
81
|
+
*
|
|
82
|
+
* ## 🔴 为什么**不再枚举**清单(owner 2026-10-19 令)
|
|
83
|
+
*
|
|
84
|
+
* 旧版在这里抄了两份清单(`MSMs: a, b, c` / `Tools: read, grep, …`)。那是**第二真相源**,
|
|
85
|
+
* 而真相源本来就在模型自己手里:
|
|
86
|
+
* · **工具清单** = 这一轮实际注册给它的 tool schema —— 模型已经看得见,抄一遍只会漂
|
|
87
|
+
* · **MSM 清单** = `msm()` 无参调用返回的目录 —— 已按白名单过滤,且**每次实时读配置**
|
|
88
|
+
*
|
|
89
|
+
* ⚠️ **漂移不是理论风险,是已发生的缺陷**(2026-10-19):角色配置早就长到 8 个工具,
|
|
90
|
+
* 而这个函数是从**创建时冻结的快照**求值的 ⇒ 提示词里一直写着旧的 4 个
|
|
91
|
+
* ⇒ 模型照着提示词办事,**它自己以为没有的能力就不去调** ⇒ 症状是"工具用不了",
|
|
92
|
+
* 而守卫那边(每调用实时读配置)其实是放行的。两个真相源打架,输的总是提示词。
|
|
93
|
+
*
|
|
94
|
+
* ⇒ 现在只声明**边界与发现路径**,不抄内容:清单在哪,怎么取,越界会怎样。
|
|
95
|
+
*
|
|
96
|
+
* @param code 轨迹编码(轨迹约束的身份 —— 不是"角色名",那个概念已退役)
|
|
97
|
+
*/
|
|
98
|
+
export declare function buildTrajectoryBasePrompt(code: string): string;
|
|
@@ -1,41 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* trajectory/policy/window.ts — 会话 → 轨迹 的内存映射(零 DSH 依赖)
|
|
3
3
|
*
|
|
4
4
|
* ## 它现在只做一件事:**把「会话」映到「轨迹」**
|
|
5
5
|
*
|
|
6
6
|
* 旧形态存的是 `{role, ccc}`(角色名)。owner 2026-10-19 重做后 **角色名不再存在**——
|
|
7
|
-
*
|
|
7
|
+
* 轨迹约束的身份是**轨迹编码**,约束面住在该轨迹的 `trajectory-constraint.json` 里(见 `./profile.ts`)。
|
|
8
8
|
* ⇒ 本表退化为一张**会话 → 轨迹目录名**的内存映射,供**同步**热路径(guards / system-prompt)查询;
|
|
9
9
|
* 权威来源仍是持久绑定(`trajectory/bound.ts` 的 `readLastBound`)。
|
|
10
10
|
*
|
|
11
|
+
* ## S12(2026-10-19,轨迹中心重构):原名 `role/轨迹约束/registry.ts`
|
|
12
|
+
*
|
|
13
|
+
* 改名理由:它**不是**一张"注册表"(注册表的语义是权威名单),它是**权威来源之外的一个窗口**——
|
|
14
|
+
* 覆盖「轨迹已定、绑定还没落盘」那一段(见下方「为什么还需要这张内存表」)。
|
|
15
|
+
* `registry` 这个名字会让下一个人以为它是权威,而权威在 `bound.ts` ⇒ 改叫 `window`。
|
|
16
|
+
*
|
|
11
17
|
* ## 为什么还需要这张内存表(R↓,一个窗口期)
|
|
12
18
|
*
|
|
13
|
-
* 持久绑定是**异步落盘**的(宿主存储域写入)。会话刚建立、`
|
|
14
|
-
* 还没落盘的那一段,`readLastBound` 返回 null ⇒ 若只认持久绑定,**第一轮会被判成"不是
|
|
19
|
+
* 持久绑定是**异步落盘**的(宿主存储域写入)。会话刚建立、`trajectory-constraint.json` 已生效、绑定的记录
|
|
20
|
+
* 还没落盘的那一段,`readLastBound` 返回 null ⇒ 若只认持久绑定,**第一轮会被判成"不是 轨迹约束"**
|
|
15
21
|
* ⇒ 工具面不收窄(模型看见并会去试它不该有的工具)。
|
|
16
|
-
* ⇒ 两个来源并取(见 `profile.ts` 的 `
|
|
22
|
+
* ⇒ 两个来源并取(见 `profile.ts` 的 `trajectoryConstraintForSession`),**都不中才判"不是"**。
|
|
17
23
|
*
|
|
18
24
|
* ## 生命周期
|
|
19
25
|
* 进程内存态:连接/会话关闭时解绑(`lifecycle.ts`),进程重启自然清空
|
|
20
26
|
* (此时持久绑定已落盘 ⇒ 由它接管,**不会因为内存空而失去约束**)。
|
|
21
27
|
*/
|
|
22
28
|
/** 注册表值:该 dsh 会话承载哪条轨迹(`trajectoryDirName` 为空串 = 已登记但还没定轨迹) */
|
|
23
|
-
interface
|
|
24
|
-
/** 轨迹目录名(`YYYY-MM-DD--<code>[--<desc>]
|
|
29
|
+
interface 轨迹约束SessionBinding {
|
|
30
|
+
/** 轨迹目录名(`YYYY-MM-DD--<code>[--<desc>]`)——**轨迹约束 身份的唯一载体** */
|
|
25
31
|
trajectoryDirName: string;
|
|
26
32
|
/** CCC 根(多 CCC 时防止串味:同 sessionId 复用必须同 (轨迹, CCC)) */
|
|
27
33
|
ccc: string;
|
|
28
34
|
}
|
|
29
35
|
/** 登记/更新一个会话 → 轨迹的映射 */
|
|
30
|
-
export declare function
|
|
36
|
+
export declare function registerTrajectorySession(sessionId: string, trajectoryDirName: string, ccc: string): void;
|
|
31
37
|
/** 解绑(会话销毁 / 轨迹失效 ⇒ 换身份) */
|
|
32
|
-
export declare function
|
|
38
|
+
export declare function unregisterTrajectorySession(sessionId: string): void;
|
|
33
39
|
/** 查会话承载的轨迹目录名(无 → null);`guards`/`system-prompt` 的同步热路径用 */
|
|
34
|
-
export declare function
|
|
40
|
+
export declare function trajectoryDirNameForSession(sessionId: string): string | null;
|
|
35
41
|
/** 查会话的完整绑定(轨迹 + CCC;无 → null)——追问延续时校验 (轨迹, CCC) 未串味 */
|
|
36
|
-
export declare function
|
|
42
|
+
export declare function trajectorySessionInfo(sessionId: string): 轨迹约束SessionBinding | null;
|
|
37
43
|
/** 测试/诊断:注册表快照 */
|
|
38
|
-
export declare function
|
|
44
|
+
export declare function trajectorySessionSnapshot(): ReadonlyMap<string, 轨迹约束SessionBinding>;
|
|
39
45
|
/** 测试:清空(进程级状态,用例间必须复位) */
|
|
40
|
-
export declare function
|
|
46
|
+
export declare function resetTrajectorySessions(): void;
|
|
41
47
|
export {};
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* **轨迹提示词** = 一条认知轨迹的**可编辑章程声明**,由 ACC 按固定顺序装配进系统提示词。
|
|
9
9
|
* 三个关键词各是一条判据:
|
|
10
10
|
* - **可编辑**:住在 CCC(盘上),改它**不发版**(D23 归属判据的直接推论)
|
|
11
|
-
* - **声明**:它声明**身份/章程/方法论**,**不声明能力**(能力面归 `
|
|
11
|
+
* - **声明**:它声明**身份/章程/方法论**,**不声明能力**(能力面归 `trajectory-constraint.json` 白名单与工具 schema)
|
|
12
12
|
* - **固定顺序**:装配顺序由 ACC 定死(见 `seams/system-prompt.ts` 的 ⑧ 位)
|
|
13
13
|
*
|
|
14
14
|
* ## 为什么取代「人格」
|
|
@@ -23,24 +23,24 @@
|
|
|
23
23
|
*
|
|
24
24
|
* - **跟着轨迹走**:`archive` 时整个目录搬走,章程不会掉队(旧形态 `.opencode/skiff/<name>.md`
|
|
25
25
|
* 与轨迹**分居两处** —— 多条轨迹共用一份文件正是那个后果)。
|
|
26
|
-
* - **每条轨迹都能有**:不只是
|
|
27
|
-
* - 与 `SESSION.md`(身体:延续/日志)、`
|
|
26
|
+
* - **每条轨迹都能有**:不只是 轨迹约束。普通轨迹同样需要"我是谁、按什么章程"。
|
|
27
|
+
* - 与 `SESSION.md`(身体:延续/日志)、`trajectory-constraint.json`(约束面:能力)三件并列,
|
|
28
28
|
* 各管一件事,不合并(合并会让"改能力"与"改身份"互相牵连)。
|
|
29
29
|
*
|
|
30
30
|
* ## 兼容(不静默坏)
|
|
31
31
|
*
|
|
32
|
-
* `PROMPT.md`
|
|
32
|
+
* `PROMPT.md` 不存在时**不报错**(普通轨迹常态)。轨迹约束的旧字段 `systemPromptFile`
|
|
33
33
|
* 在兼容期仍被读取——优先级见 {@link resolveTrajectoryPrompt}。
|
|
34
34
|
*/
|
|
35
|
-
import type {
|
|
35
|
+
import type { TrajectoryConstraint } from './policy/profile.js';
|
|
36
36
|
/** 轨迹提示词的固定文件名(**判据就是它存在**——不是目录名前缀,也不是配置里的一行) */
|
|
37
37
|
export declare const TRAJECTORY_PROMPT_FILENAME = "PROMPT.md";
|
|
38
38
|
/** 一次解析的结果(`source` 说明正文**从哪来**,便于诊断与「为什么我改的不生效」) */
|
|
39
39
|
export interface TrajectoryPromptResolution {
|
|
40
40
|
/** 提示词正文(已 trim);无来源 ⇒ 空串 */
|
|
41
41
|
text: string;
|
|
42
|
-
/** 来源:轨迹目录的 PROMPT.md /
|
|
43
|
-
source: 'trajectory-file' | '
|
|
42
|
+
/** 来源:轨迹目录的 PROMPT.md / 轨迹约束 旧字段 / 无 */
|
|
43
|
+
source: 'trajectory-file' | '轨迹约束-legacy' | 'none';
|
|
44
44
|
/** 实际读取的绝对路径(`none` ⇒ null) */
|
|
45
45
|
path: string | null;
|
|
46
46
|
}
|
|
@@ -49,9 +49,9 @@ export declare function trajectoryPromptPath(root: string, dirName: string): str
|
|
|
49
49
|
/**
|
|
50
50
|
* 该轨迹**有没有**轨迹提示词(单一判据)。
|
|
51
51
|
*
|
|
52
|
-
* 用途:兼容期的"让位"判定 —— 若已有 `PROMPT.md
|
|
53
|
-
* 必须**让位**,否则同一份章程会在两处各注入一遍(第 ⑧ 段 + `serenity
|
|
54
|
-
* 🔴 判据只有这一处:别在
|
|
52
|
+
* 用途:兼容期的"让位"判定 —— 若已有 `PROMPT.md`,轨迹约束 旧字段 `systemPromptFile`
|
|
53
|
+
* 必须**让位**,否则同一份章程会在两处各注入一遍(第 ⑧ 段 + `serenity-轨迹约束` 段)。
|
|
54
|
+
* 🔴 判据只有这一处:别在 轨迹约束那边自己拼路径再判(两处会漂)。
|
|
55
55
|
*/
|
|
56
56
|
export declare function hasTrajectoryPrompt(root: string, dirName: string): boolean;
|
|
57
57
|
/**
|
|
@@ -61,13 +61,13 @@ export declare function hasTrajectoryPrompt(root: string, dirName: string): bool
|
|
|
61
61
|
*
|
|
62
62
|
* 优先级(**确定性,只有这一条**):
|
|
63
63
|
* ① `<轨迹目录>/PROMPT.md` —— 新形态,**所有轨迹**都能有
|
|
64
|
-
* ②
|
|
64
|
+
* ② 轨迹约束的 `systemPromptFile` —— **兼容期**旧形态(存量 CCC 不必同批迁移)
|
|
65
65
|
* ③ 无 ⇒ 空串(**不是错误**:没有章程的轨迹是常态)
|
|
66
66
|
*
|
|
67
67
|
* ⚠️ 读失败(权限/坏文件)⇒ 空串而不是抛错:提示词读不到不该阻断会话创建;
|
|
68
68
|
* 但**会告警**(见 reader 版本),不静默。
|
|
69
69
|
*/
|
|
70
|
-
export declare function resolveTrajectoryPrompt(root: string, dirName: string, legacyProfile?:
|
|
70
|
+
export declare function resolveTrajectoryPrompt(root: string, dirName: string, legacyProfile?: TrajectoryConstraint | null): TrajectoryPromptResolution;
|
|
71
71
|
/**
|
|
72
72
|
* 轨迹提示词的**读取器**(长期热更新;改文件即生效,无需重启)。
|
|
73
73
|
*
|
|
@@ -75,9 +75,9 @@ interface RebuildResult {
|
|
|
75
75
|
* → ②b **权威绑定**(`AGENT_SESSIONS/.bindings.json`,本会话持久绑定)→ ③ surface 首条锚点
|
|
76
76
|
* (events 异常时兜底)。
|
|
77
77
|
*
|
|
78
|
-
* v1.30.13(S142 用户"微信桥 +
|
|
78
|
+
* v1.30.13(S142 用户"微信桥 + 轨迹约束会话锚定要准确",诊断 D4):**移除**原 ④「全局最新未完成
|
|
79
79
|
* 会话」(`findLatestActiveSessionMd`)。理由(R↓):④ 是**跨轨迹**猜测——候选①②③全空时,
|
|
80
|
-
* 它会把 rebuild 静默接到 AGENT_SESSIONS 里最新的另一个会话(临时
|
|
80
|
+
* 它会把 rebuild 静默接到 AGENT_SESSIONS 里最新的另一个会话(临时 轨迹约束会话 persistent=false、
|
|
81
81
|
* 重启后首条消息前、新会话首条消息都命中该形态),而"接错轨迹"比重建失败危险得多
|
|
82
82
|
* (错误轨迹被继续写入 + 正确轨迹静默丢失)。现在全部候选失败 → 返回 null → 调用方
|
|
83
83
|
* 报错引导用户显式 `cognitive_trajectory use`(响亮失败优于静默接错)。
|