@shgroup/dsh-serenity-hooks 1.102.0 → 1.104.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.
Files changed (34) hide show
  1. package/README.md +1 -2
  2. package/dsh.plugin.json +2 -3
  3. package/lib/{ccc-CyYJL4F2.js → ccc-B-h_A7uc.js} +17 -36
  4. package/lib/{ccc-roots-WfktvbN8.js → ccc-roots-BIdg0EyM.js} +8 -12
  5. package/lib/{channels-CuCsUfcY.js → channels-BItMJUO8.js} +2 -2
  6. package/lib/client.js +1 -6
  7. package/lib/cro/guide.d.ts +1 -1
  8. package/lib/guard/seam.d.ts +2 -1
  9. package/lib/host/access.d.ts +10 -42
  10. package/lib/host/contract.d.ts +3 -2
  11. package/lib/index.js +64 -375
  12. package/lib/invariant.js +0 -1
  13. package/lib/kernel/ccc-roots.d.ts +4 -3
  14. package/lib/kernel/ccc.d.ts +12 -30
  15. package/lib/kernel/invariant.d.ts +1 -1
  16. package/lib/{message-source-BAMwXu6i.js → message-source-CKJPJCzc.js} +14 -3
  17. package/lib/{profile-zxakCNXy.js → profile-Dpg3wYO5.js} +1 -1
  18. package/lib/{route-DxIKWeN9.js → route-CmEoKp9w.js} +2 -2
  19. package/lib/seams/context.d.ts +5 -2
  20. package/lib/{service-DDmHSglV.js → service-Cndtf7q4.js} +6 -6
  21. package/lib/{session-Dao7X5lR.js → session-CaNqSHVB.js} +25 -139
  22. package/lib/surface/status.d.ts +1 -2
  23. package/lib/tools/localstore/service.d.ts +1 -1
  24. package/lib/tools/msm/service.d.ts +2 -2
  25. package/lib/tools/trajectory-constraint-admin.d.ts +1 -1
  26. package/lib/trajectory/bound.d.ts +1 -1
  27. package/lib/trajectory/carrier.d.ts +5 -4
  28. package/lib/trajectory/model-runtime.d.ts +5 -3
  29. package/lib/trajectory/model-string.d.ts +26 -0
  30. package/lib/trajectory/policy/profile.d.ts +1 -1
  31. package/package.json +2 -2
  32. package/lib/tools/cheap-worker.d.ts +0 -21
  33. package/lib/trajectory/delegate/core.d.ts +0 -55
  34. package/lib/trajectory/delegate/preset.d.ts +0 -42
package/lib/invariant.js CHANGED
@@ -144,7 +144,6 @@ const REGISTERED_TOOLS = [
144
144
  "praxis",
145
145
  "ontology",
146
146
  "serenity-skill-creator",
147
- "cheap-worker",
148
147
  "localstore",
149
148
  "container_admin",
150
149
  "im-bridge",
@@ -52,9 +52,10 @@ export interface ExecOrAgent {
52
52
  * `exec.agent?.session?.header?.cwd ?? process.cwd()`。
53
53
  *
54
54
  * ⚠️ 无 `exec.agent` 时回落进程 cwd —— "用服务启动目录冒充会话目录"是**既有语义**,
55
- * 不是本模块的选择(改它会动到 9 个工具的根解析行为)。已知副作用与规避见
56
- * `tools/cheap-worker.ts` 的「调用形态检查前移」补偿(`?? process.cwd()` 会把真因
57
- * "exec.agent 不存在"盖成 `No CCC found`)。
55
+ * 不是本模块的选择(改它会动到所有工具的根解析行为)。已知副作用:`?? process.cwd()`
56
+ * 会把真因"exec.agent 不存在"盖成 `No CCC found` —— 工具侧须把**调用形态检查前移**再判根
57
+ * (原实现范例 `tools/cheap-worker.ts`,该文件已于 2026-10-28 随工具下线删除;
58
+ * 现行的正例见 `tools/fs/service.ts` 的入参校验顺序)。
58
59
  */
59
60
  export declare function agentCwdFor(execOrAgent: ExecOrAgent): string;
60
61
  /**
@@ -32,24 +32,6 @@ export declare function resolveInside(root: string, p: string): string;
32
32
  */
33
33
  export declare function readCccName(root: string): string | null;
34
34
  interface SerenityConfig {
35
- /** cheap-worker(杂工)配置:模型白名单(v1.24.0 取代 loop;2026-10-14 取代 handyman) */
36
- 'cheap-worker'?: {
37
- /** 可用模型白名单(provider/model 列表)——cheap-worker 只能使用其中模型(用户拍板:CCC 配置控制) */
38
- models?: string[];
39
- /** 缺省模型(必须 ∈ models) */
40
- defaultModel?: string;
41
- };
42
- /**
43
- * 🔴 **旧键(历史名)**:2026-10-14 起本插件读 `cheap-worker`,**读不到时回落到这里**
44
- * (owner 令「配置兼容旧配置 key」)。仍可含 `maxRounds`/`maxParallel` —— 那两个键已随
45
- * background 模式退场,**不再被读取**,但**留在文件里不会报错**(宽松解析,见 loadSerenityConfig)。
46
- */
47
- handyman?: {
48
- models?: string[];
49
- defaultModel?: string;
50
- maxRounds?: number;
51
- maxParallel?: number;
52
- };
53
35
  sessionKeeper?: {
54
36
  /** 计分提醒阈值(缺省 150) */
55
37
  threshold?: number;
@@ -295,21 +277,21 @@ export interface WeixinRouteConfig {
295
277
  * 而新模型里 轨迹约束恒等于一条轨迹 ⇒ 恒有 SESSION.md ⇒ 该区分没有指称对象(静默忽略)。
296
278
  */
297
279
  /**
298
- * 解析 cheap-worker 配置。
299
- *
300
- * 🔴 **键的优先级(2026-10-14,owner 令「配置兼容旧配置 key」)**:
301
- * ① 新键 `cheap-worker`;② **读不到(键缺失或 models 非有效数组)⇒ 回落旧键 `handyman`**。
302
- * 「读不到」的判据是**同一套**(models 必须是至少含一个非空字符串的数组)—— 这样"新键存在但写错了"
303
- * 与"没写新键"行为一致,都不会静默走一个空白名单。
280
+ * 🔴 **`readCheapWorkerConfig` / `pickModelSection` 已于 2026-10-28 删除**
281
+ * (owner 令「下线 cheap-worker,完全删掉」)。
304
282
  *
305
- * ⚠️ `maxRounds`/`maxParallel` 已随 background 模式退场,**不再被本函数读取**(旧配置里留着无害)。
283
+ * 它们原本有三个消费者,三个都已同步处置:
284
+ * | 消费者 | 处置 |
285
+ * |---|---|
286
+ * | `tools/cheap-worker.ts`(模型白名单校验) | 文件整体删除 |
287
+ * | `surface/status.ts` 的 `cheapWorkerModel`(面板回显) | 字段删除(面板同步) |
288
+ * | `tools/trajectory-constraint-admin.ts` 的 `model ∈ cheap-worker.models` 校验 | **校验整条移除** |
306
289
  *
307
- * @returns 白名单 + 缺省模型;两处都取不到 models 时返回 null(工具应报错要求配置)
290
+ * ⚠️ 最后一条要说清(R↓):那条校验原本是「轨迹约束声明的 model 必须在 CCC 白名单里」。
291
+ * 白名单随 cheap-worker 一起消失 ⇒ **它失去了判据来源**。而模型合法性本来就有
292
+ * **更权威的判据**(`trajectory/model-runtime.ts`:宿主报非法模型 ⇒ 不切+响亮告警)
293
+ * ⇒ 删掉它**不是丢了一个保护,而是去掉一份与权威判据并行的第二真相源**(D131 同族)。
308
294
  */
309
- export declare function readCheapWorkerConfig(root: string, paths?: string[]): {
310
- models: string[];
311
- defaultModel: string;
312
- } | null;
313
295
  /**
314
296
  * ACC 依赖的 CCC 配置路径(S134 修正:兼容历史——历史在 .opencode,规范位置 = .opencode;
315
297
  * .dsh 仅作 dsh 运行时回退,不优先)。
@@ -58,6 +58,6 @@ export declare function assertManifestProse(manifestPath: string, readmePaths: r
58
58
  * `review`(C 档,调引擎 `compliance`)/`index`(调 P1 的生成器)/`status` ⇒ **14**。
59
59
  * 同规格:**条件可见与否不影响这里列它**(本常量 = "插件**具备**的工具面")。
60
60
  */
61
- export declare const REGISTERED_TOOLS: readonly ["container_fs", "cognitive_trajectory", "dashboard", "container_git", "msm", "praxis", "ontology", "serenity-skill-creator", "cheap-worker", "localstore", "container_admin", "im-bridge", "acc-diag", "diagram"];
61
+ export declare const REGISTERED_TOOLS: readonly ["container_fs", "cognitive_trajectory", "dashboard", "container_git", "msm", "praxis", "ontology", "serenity-skill-creator", "localstore", "container_admin", "im-bridge", "acc-diag", "diagram"];
62
62
  /** 条件出现的工具数(`REGISTERED_TOOLS` 的**末段**;`assertManifestProse` 用) */
63
63
  export declare const CONDITIONAL_TOOL_COUNT = 3;
@@ -1,6 +1,6 @@
1
- import { r as cccRootForCwd } from "./ccc-roots-WfktvbN8.js";
2
- import { _ as resolveInside, g as readUtf8 } from "./ccc-CyYJL4F2.js";
3
- import { D as getLastActiveSessionInfo, E as getActiveSessionInfo, I as sessionEvents, L as sessionsRoot, M as parseTrajectoryCode, _ as readBindDeclaration, g as listBindDeclarations, h as isBindUsable, m as claimBinding } from "./profile-zxakCNXy.js";
1
+ import { r as cccRootForCwd } from "./ccc-roots-BIdg0EyM.js";
2
+ import { g as resolveInside, h as readUtf8 } from "./ccc-B-h_A7uc.js";
3
+ import { D as getLastActiveSessionInfo, E as getActiveSessionInfo, I as sessionEvents, L as sessionsRoot, M as parseTrajectoryCode, _ as readBindDeclaration, g as listBindDeclarations, h as isBindUsable, m as claimBinding } from "./profile-Dpg3wYO5.js";
4
4
  import { dirname, join } from "node:path";
5
5
  import { existsSync, readFileSync, statSync } from "node:fs";
6
6
  import { fileURLToPath } from "node:url";
@@ -446,6 +446,17 @@ function appendBound(session, action, rec) {
446
446
  detail
447
447
  };
448
448
  }
449
+ const header = sessionHeader(session);
450
+ if (header?.origin === "subagent") {
451
+ const detail = `会话 ${id} 是 **subagent 子会话**(header.origin="subagent"${header.parentSession ? `,parentSession=${header.parentSession}` : ""}),不能作为轨迹「${rec.dirName}」的载体 ⇒ current.dsh_session_bind **未被改写**。\n 原因:子会话的消息投递权归宿主 subagent routing,ACC 唤醒/投递会被宿主以 \`session/agent-busy\`(is owned by subagent routing)拒绝 ⇒ 该轨迹**每一条**到点唤醒都送不出去。
452
+ 正确做法:在**根会话**(不是子会话)里执行 cognitive_trajectory use。`;
453
+ console.warn(`[serenity-hooks] ✗ 绑定未写入(SESSION_IS_SUBAGENT):${detail}`);
454
+ return {
455
+ ok: false,
456
+ code: "SESSION_IS_SUBAGENT",
457
+ detail
458
+ };
459
+ }
449
460
  const result = claimBinding(sessionsRoot(root), rec.dirName, {
450
461
  sessionId: id,
451
462
  at: Date.now(),
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.js";
2
- import { _ as resolveInside, g as readUtf8 } from "./ccc-CyYJL4F2.js";
2
+ import { g as resolveInside, h as readUtf8 } from "./ccc-B-h_A7uc.js";
3
3
  import { basename, dirname, join } from "node:path";
4
4
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
5
5
  //#region src/kernel/time.ts
@@ -1,6 +1,6 @@
1
1
  import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.js";
2
- import { s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-CyYJL4F2.js";
3
- import { c as unsetEntry, l as writeEntry, r as getEntry } from "./service-DDmHSglV.js";
2
+ import { s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-B-h_A7uc.js";
3
+ import { c as unsetEntry, l as writeEntry, r as getEntry } from "./service-Cndtf7q4.js";
4
4
  import { join, resolve } from "node:path";
5
5
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
6
  import { createHash } from "node:crypto";
@@ -15,7 +15,8 @@ import type { UserMessage } from '@deepseek-ai/dsh-session';
15
15
  export declare function accIdentityText(root: string, configPaths?: string[], entrySkillMaxChars?: number): string;
16
16
  /**
17
17
  * ACC 注入消息(S134 去重):**只含简短身份锚点**([ACC] 已激活 + CCC 根 + 约束 + Phase 2)。
18
- * ⚠️ 原文案含「+ cheap-worker 模型」,该注入已于 2026-09-16 删除(§0e-G)⇒ 此处同步订正(散文级残留)。
18
+ * ⚠️ 原文案含「+ cheap-worker 模型」;该注入已于 2026-09-16 删除(§0e-G),
19
+ * 且 cheap-worker 本身已于 2026-10-28 整条下线 ⇒ 此处订正(散文级残留已无对应实现)。
19
20
  * 完整身份(ACC 5 块 + CCE + Constraints + EAP + SKILL 全文 + Session 块)由**系统提示词层**
20
21
  * (systemPrompt.section,每轮 prompt 装配自动注入,含 subagent)承担——对话消息流/压缩重注入
21
22
  * 不再重复注入同一内容(token 双倍浪费,见 S134 注入方案梳理)。
@@ -39,7 +40,9 @@ export declare function hasAccBanner(session: unknown): boolean;
39
40
  * 只有"conversation 根会话"才自动恢复最近激活的宁静号会话——
40
41
  * - subagent:session header `origin === 'subagent'`(DSH 路由语义,agent-lookup.ts)
41
42
  * - 派生会话:`parentSession` 存在(任何子会话)
42
- * - cheap-worker 杂工:sessionId 固定 `cheap-worker-` 前缀(tools/cheap-worker.ts 生成)
43
+ * - 历史 `cheap-worker-` 前缀会话(**兼容保留**:生成者 `tools/cheap-worker.ts` 已于
44
+ * 2026-10-28 整条下线 ⇒ **不会再产生新会话**,但**旧持久化会话仍可能被 resume**,
45
+ * 那时它依旧不该把主会话激活注入子上下文)
43
46
  * 三者都不恢复(避免把主会话激活注入子上下文,违背 v1.16.2 scope 隔离)。
44
47
  */
45
48
  export declare function shouldAutoRestore(agent: Agent, root?: string | null): boolean;
@@ -1,4 +1,4 @@
1
- import { s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-CyYJL4F2.js";
1
+ import { s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-B-h_A7uc.js";
2
2
  import { join } from "node:path";
3
3
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
4
  //#region src/tools/localstore/service.ts
@@ -18,7 +18,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
18
18
  * 存储结构(JSON 顶层分节):
19
19
  * { "credentials": { "HOME_GITLAB_TOKEN": "xxx" }, "<config节>": { "<key>": "v" } }
20
20
  * credentials 为保留节(credential 命名空间,key 大写蛇形);其余节归 config 命名空间
21
- * (path = section.key,如 cheap-worker.models)。
21
+ * (path = section.key,如 my-feature.someKey)。
22
22
  */
23
23
  const LOCALSTORE_SCOPES = ["credential", "config"];
24
24
  /** 存储文件名(CCC 根根目录) */
@@ -111,7 +111,7 @@ function assertCredentialKey(key) {
111
111
  /** 校验 config 路径(节.key);不合法抛错 */
112
112
  function assertConfigPath(path) {
113
113
  const idx = path.indexOf(".");
114
- if (idx <= 0 || idx === path.length - 1) throw new Error(`config path "${path}" must be section.key (e.g. cheap-worker.models)`);
114
+ if (idx <= 0 || idx === path.length - 1) throw new Error(`config path "${path}" must be section.key (e.g. my-feature.someKey)`);
115
115
  const section = path.slice(0, idx);
116
116
  const key = path.slice(idx + 1);
117
117
  if (!CONFIG_SECTION_RE.test(section)) throw new Error(`config section "${section}" must match ^[a-z][a-z0-9-]*$`);
@@ -195,8 +195,8 @@ function docText(root) {
195
195
  " \"credentials\": {",
196
196
  " \"HOME_GITLAB_TOKEN\": \"xxx\"",
197
197
  " },",
198
- " \"cheap-worker\": {",
199
- " \"models\": [\"minimax-cn-coding-plan/MiniMax-M3\"]",
198
+ " \"my-feature\": {",
199
+ " \"someKey\": \"some-value\"",
200
200
  " }",
201
201
  "}",
202
202
  "```",
@@ -204,7 +204,7 @@ function docText(root) {
204
204
  "",
205
205
  "## Key conventions",
206
206
  "- credential key: ^[A-Z][A-Z0-9_]*$ (e.g. HOME_GITLAB_TOKEN)",
207
- "- config path: section.key (section ^[a-z][a-z0-9-]*$, key lowerCamel ^[a-z][a-zA-Z0-9_]*$, e.g. cheap-worker.models)",
207
+ "- config path: section.key (section ^[a-z][a-z0-9-]*$, key lowerCamel ^[a-z][a-zA-Z0-9_]*$, e.g. my-feature.someKey)",
208
208
  "",
209
209
  "## Reading (agents may use fs tools directly)",
210
210
  `- Read ${path} with the read tool → JSON.parse`,
@@ -1,8 +1,8 @@
1
- import { n as agentCwdFor, r as cccRootForCwd, s as hostAgents } from "./ccc-roots-WfktvbN8.js";
2
- import { g as readUtf8, o as isSafeModeOn, p as readCognitiveTrajectorySkills, u as readBlacklist } from "./ccc-CyYJL4F2.js";
3
- import { K as isoLocal, L as sessionsRoot, N as readActiveSessionMd, d as registerTrajectorySession$1, f as trajectoryDirNameForSession, o as readTrajectoryConstraintAt, p as unregisterTrajectorySession$1, u as trajectoryConstraintForSession, y as DEFAULT_SESSION_SCOPE } from "./profile-zxakCNXy.js";
4
- import { a as readGitTrack, i as localstorePath } from "./service-DDmHSglV.js";
5
- import { d as constraintCognitiveTrajectory, m as profileMsmWhitelist, n as PLUGIN_SOURCE, o as readLastBound, p as createProfilePromptReader, u as buildTrajectoryBasePrompt, v as ACC_VERSION } from "./message-source-BAMwXu6i.js";
1
+ import { n as agentCwdFor, r as cccRootForCwd, s as hostAgents } from "./ccc-roots-BIdg0EyM.js";
2
+ import { f as readCognitiveTrajectorySkills, h as readUtf8, o as isSafeModeOn, u as readBlacklist } from "./ccc-B-h_A7uc.js";
3
+ import { K as isoLocal, L as sessionsRoot, N as readActiveSessionMd, d as registerTrajectorySession$1, f as trajectoryDirNameForSession, o as readTrajectoryConstraintAt, p as unregisterTrajectorySession$1, u as trajectoryConstraintForSession, y as DEFAULT_SESSION_SCOPE } from "./profile-Dpg3wYO5.js";
4
+ import { a as readGitTrack, i as localstorePath } from "./service-Cndtf7q4.js";
5
+ import { d as constraintCognitiveTrajectory, m as profileMsmWhitelist, n as PLUGIN_SOURCE, o as readLastBound, p as createProfilePromptReader, u as buildTrajectoryBasePrompt, v as ACC_VERSION } from "./message-source-CKJPJCzc.js";
6
6
  import { basename, dirname, join, resolve } from "node:path";
7
7
  import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
8
8
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
@@ -1507,7 +1507,6 @@ function toolsBlock() {
1507
1507
  " msm — execute a registered CCC MSM: msm(name, args); partial name returns candidates; inspect=true shows usage",
1508
1508
  " praxis — actionable theory injection: praxis (index) / praxis eap / praxis neat / praxis cce / praxis ontology",
1509
1509
  " ontology — ontology engineering ENGINE (executable): init (write template) / check (M1-M10 structural; level=strict adds L1-L5 hints) / explain (summary) / verify (V1-V4 runtime compliance) / review (semantic-review prompt) / compliance (axiom-vs-skill checklist). Sibling of `praxis ontology` — that one is the METHOD TEXT, this one RUNS it. path must stay inside the container; the receipt carries the engine exit code (0/1/2/4) and the engine text verbatim, so read it rather than assuming success",
1510
- " cheap-worker — delegate work to a worker agent on the CCC-configured model; one serial child per task, returns its final text. `jobs=[...]` fans out in parallel (cap 10, results keep your order). No loop, no completion code, no progress file. The model is NOT selectable per call (read from the CCC config); a worker's tool set excludes cheap-worker itself",
1511
1510
  " serenity-skill-creator — creator for serenity-skills (this container's enhanced skill standard): guide (authoring/optimization method — read first) / create <name> (scaffold SKILL.md + skill.ttl + references/, base-chain import path computed) / check <name> (A1 structural + A2 base-chain; three states: modeled-ok / plain-skill / modeled-but-check-could-not-run) / review <name> (C tier: axiom-vs-text compliance question list, half-mechanical) / index <name> (preview the second-layer resource list the model will see) / status (which skills are modeled). A skill is \"modeled\" iff it has a file named exactly skill.ttl next to SKILL.md; a plain skill is NOT an anomaly. Only `create` writes, and it refuses an existing directory",
1512
1511
  " localstore — ACC local credential/config storage (CCC-root localstore.json; git policy localstore.gitTrack default deny)",
1513
1512
  " container_admin — container administration (the maintenance bay): role (轨迹约束 roles: guide/validate/apply/list) / msm (register/deregister/check/guide/catalog/ccc-config) / config (view)",
@@ -2090,21 +2089,29 @@ function registerCognitiveTrajectorySkillSection(agent, root) {
2090
2089
  }
2091
2090
  }
2092
2091
  //#endregion
2093
- //#region src/trajectory/delegate/core.ts
2092
+ //#region src/trajectory/model-string.ts
2094
2093
  /**
2095
- * trajectory/delegate/core.ts — cheap-worker(杂工)纯逻辑层(零 DSH 依赖,可独立单测)
2094
+ * trajectory/model-string.ts — `provider/model` 串解析(**共用件**,不属于任何工具)
2096
2095
  *
2097
- * 🆕 2026-10-14(owner 令「删除后台运行能力」):**进度文件 / stop token / 轮次循环**整族已退场 ——
2098
- * 它们**只**服务于 background 模式。本模块现存 = 前台委派真正需要的三件:
2099
- * 模型串解析 / 白名单校验 / provider 可用性判读(+ 使用指引文本)。
2096
+ * ## 为什么单独成模块(2026-10-28,cheap-worker 下线时抽出)
2100
2097
  *
2101
- * ## S14(2026-10-19,轨迹中心重构):此前位于 `role/worker/` 下(该目录已消失)
2098
+ * 它原本住在 `trajectory/delegate/core.ts`(cheap-worker 的纯逻辑层)。但 grep 调用点后发现
2099
+ * **它有两个与 cheap-worker 无关的消费者**:
2100
+ * - `trajectory/session.ts`(`agentOptions` 装配,IM 入站 / send-now 冷启都用)
2101
+ * - `trajectory/model-runtime.ts`(`trajectory.json` 的 `model` 运行时热切换)
2102
2102
  *
2103
- * 落点 = `trajectory/delegate/`。判据(判读表 §3.1):它是**轨迹 × 轨迹**那种合法形态 ——
2104
- * 主语是「主轨迹把活交给子 agent」,既不是某一条轨迹的切面,也不是容器宪法。
2105
- * ⚠️ 它**不属于** `policy/`:policy 管"这条轨迹允许什么",本模块管"一条轨迹怎么把活派出去"。
2103
+ * ⇒ 若跟着 `delegate/` 一起删掉,**轨迹的模型热切换与载体装配会一起断**。
2104
+ * ⇒ 判据(可外推):**删一个模块前,先核它的导出有没有"跨域消费者"** ——
2105
+ * 目录归属(谁住在谁的目录里)不等于依赖归属(谁在用)。同族先例:`listWakes` 有完整诊断出口
2106
+ * 却被误判成零调用点(续 337 ②b)。
2107
+ */
2108
+ /**
2109
+ * 解析 model 字符串(`provider/model`)→ `{ provider, model }`。
2110
+ *
2111
+ * 无 `/` ⇒ 视为 **model-only**(`provider === undefined`),由调用方决定是否接受这种形态。
2112
+ * ⚠️ 只按**第一个** `/` 切分:provider id 不含 `/`,但 model id 可能含(如 `p/ns/model-x`)
2113
+ * ⇒ 取 `indexOf` 而非 `split('/')` 才是对的。
2106
2114
  */
2107
- /** 解析 model 字符串(provider/model)→ {provider, model};无 / 视为 model-only */
2108
2115
  function splitModel(model) {
2109
2116
  const idx = model.indexOf("/");
2110
2117
  if (idx < 0) return {
@@ -2116,130 +2123,9 @@ function splitModel(model) {
2116
2123
  model: model.slice(idx + 1)
2117
2124
  };
2118
2125
  }
2119
- /** 校验模型在白名单内;不在 → 抛错(用户拍板:只能使用 CCC 配置的模型) */
2120
- function requireWhitelistedModel(model, models) {
2121
- if (!models.includes(model)) throw new Error(`cheap-worker: model "${model}" is not in the CCC whitelist. Configure .opencode/serenity.json "cheap-worker.models" with one of: ${models.join(", ")}`);
2122
- }
2123
- /**
2124
- * providerAvailabilityError — 判定「**本机有没有该 provider 的 adapter**」,并产出**可执行**的错误文本。
2125
- * 返回 `null` = 全部可用(调用方照常继续)。
2126
- *
2127
- * 🔴 为什么需要它(S142 2026-09-25,owner 在 **Mac** 上实测):`cheap-worker` 的模型白名单写在
2128
- * **CCC**(`.opencode/serenity.json`,**随 git 走**),而 provider adapter 由**每台机器的宿主**
2129
- * 注册(profile 配置 / settings 命名空间)⇒ 同一份白名单在一台机器可用、在另一台必失败。
2130
- * 实测症状:宿主抛 `no adapter registered for provider "<p>"`(`dsh-llm`,code `NO_ADAPTER`),
2131
- * 而**前台路径的 `diagnostic` 是空的** ⇒ 调用方(LLM)拿到 `stopReason:"error"` 却**不知道为什么**,
2132
- * 也就无法修正自己的配置 —— 本条把「沉默的失败」变成「可执行的错误」。
2133
- *
2134
- * 数据来源(宿主 `LlmRuntime`):`listProviders()` = **有 adapter 的路由**;
2135
- * `listConfigurableProviders()` = **已声明但未必激活**的路由(含激活用的 settings 命名空间)。
2136
- *
2137
- * 判据边界:`model` 串里**没有 `/`** 时取不到 provider(沿用 agent 默认路由)⇒ **不判定**(跳过)。
2138
- */
2139
- function providerAvailabilityError(models, facts) {
2140
- const registered = new Set(facts.registered.map((r) => r.id));
2141
- const requested = models.map((m) => ({
2142
- raw: m,
2143
- provider: splitModel(m).provider
2144
- })).filter((e) => typeof e.provider === "string" && e.provider !== "");
2145
- const missing = [...new Set(requested.filter((e) => !registered.has(e.provider)).map((e) => e.provider))];
2146
- if (missing.length === 0) return null;
2147
- const list = (items, cap = 12) => items.length === 0 ? " (none)" : items.slice(0, cap).map((s) => ` - ${s}`).join("\n") + (items.length > cap ? `\n … and ${items.length - cap} more` : "");
2148
- const available = facts.registered.map((r) => r.name ? `${r.id} (${r.name})` : r.id).sort();
2149
- const declared = (facts.declared ?? []).filter((d) => missing.includes(d.provider));
2150
- const configPath = facts.configPath ?? "<ccc>/.opencode/serenity.json";
2151
- const missingList = missing.map((p) => `"${p}"`).join(", ");
2152
- return [
2153
- `cheap-worker: provider ${missingList} has no adapter registered on this machine.`,
2154
- "",
2155
- " Requested model(s) :",
2156
- ...requested.map((e) => ` ${e.raw}`),
2157
- ` Configured in : ${configPath} → "cheap-worker.models" / "cheap-worker.defaultModel"`,
2158
- "",
2159
- " Why this happens : the whitelist lives in the CCC (it travels with the repository), while",
2160
- " provider adapters are registered per machine by the host. An entry that",
2161
- " works on one machine can fail on another.",
2162
- "",
2163
- " Available on this machine (registered adapters):",
2164
- list(available),
2165
- "",
2166
- " Declared but NOT active here (activate via settings, then retry):",
2167
- list(declared.map((d) => `${d.provider}${d.displayName ? ` (${d.displayName})` : ""}${d.settingsNs ? ` — settings namespace "${d.settingsNs}"` : ""}`)),
2168
- "",
2169
- " Fix (pick one, then retry):",
2170
- ` 1. Point the whitelist at a provider that IS registered here — edit ${configPath}`,
2171
- " (\"cheap-worker.models\", and \"cheap-worker.defaultModel\" if that is what you relied on).",
2172
- ` 2. Register/activate provider ${missingList} on this machine (host profile config,`,
2173
- " or the settings namespace listed above).",
2174
- "",
2175
- " Do not retry unchanged — the same call fails identically."
2176
- ].join("\n");
2177
- }
2178
- /**
2179
- * cheap-worker 规模化使用指引(guide 子命令输出)。
2180
- *
2181
- * 🆕 2026-10-14:**双模式段已整段退场**(owner 令「删除后台运行能力」)。本指引只描述现行机制:
2182
- * 前台委派(单任务)/前台并行扇出(jobs)/白名单与 provider 预检。
2183
- */
2184
- const CHEAP_WORKER_GUIDE = `# cheap-worker — Scale-Up Usage Guide (guide)
2185
-
2186
- ## What it is
2187
- One delegation primitive: **foreground spawn**. The host starts child agent(s) through its delegation
2188
- service, awaits them, and returns their final text. There is no loop, no completion code, no progress
2189
- file, and no unattended/background run.
2190
-
2191
- | | single | parallel (jobs) |
2192
- |---|---|---|
2193
- | Call | cheap-worker(task, [label]) | cheap-worker(jobs=[{task, label?}, ...]) |
2194
- | Behaviour | one child runs the task once | all children start at once, results keep your order |
2195
- | Cap | — | **10 (fixed, hardcoded)** |
2196
- | Model | CCC config (single source) | same |
2197
-
2198
- ## ⚠️ Before using: load eap and design the plan
2199
- Before calling cheap-worker, load eap (acc-eap skill) and design the "scale-up cheap-worker plan" based on the EAP framework.
2200
-
2201
- ### 1. Task decomposition (E↑ Explicit)
2202
- - Split large tasks into explicit subtasks: each subtask defines goal / input / boundaries (what to do, what not to do) / acceptance criteria
2203
- - Make dependencies explicit: dependent tasks run serially, independent ones can run in parallel via \`jobs\`
2204
-
2205
- ### 2. Prompt design (cheap-worker's task parameter)
2206
- - task must be detailed, fixed, and EAP-compliant: clear goal, drawn boundaries, decidable acceptance criteria
2207
- - the child does NOT share your conversation — restate everything it needs in task
2208
- - Anti-example "handle this file" — ambiguous; good example "read <path>, extract all rows of the「关键决策」table,
2209
- output a JSON array (fields id/conclusion/evidence), do not modify the original file"
2210
- - Reading/curating or text-writing work (extracting from files, summarizing, writing docs, generating text, etc.):
2211
- the cheap-worker-internal agent is also required to load eap and organize output per the EAP standard
2212
-
2213
- ### 3. Model (CCC-configured, not selectable per call)
2214
- - The model is read from .opencode/serenity.json "cheap-worker.models" — **the caller cannot pass one**
2215
- (there is no "model" parameter). "cheap-worker.defaultModel" names which entry is used; it falls back to models[0].
2216
- - The CCC is expected to point this whitelist at LOW-COST models: cheap-worker is the bulk-execution channel
2217
- - A child's own recursive subagents inherit the child's model automatically (DSH native)
2218
-
2219
- ### 3b. 🔴 Provider availability (per-machine — the whitelist is NOT enough)
2220
- - The whitelist lives in the **CCC** ("serenity.json", it **travels with the repository**), but provider
2221
- **adapters are registered per machine by the host** (profile config / settings namespace). An entry that
2222
- works on one machine can fail on another with: "no adapter registered for provider <p>".
2223
- - Before spawning, cheap-worker verifies the provider of the resolved model against the adapters registered
2224
- **on this machine**; if it is missing it reports the requested model, where it is configured, **the
2225
- providers that ARE available here**, any declared-but-dormant route (with its settings namespace), and the
2226
- exact fix — delivered in the result's "diagnostic" field (never an opaque failure, never a created child).
2227
- - ⇒ If you see "has no adapter registered on this machine": edit ".opencode/serenity.json" "cheap-worker.models"
2228
- (and "cheap-worker.defaultModel") to a provider listed as available, or activate/register the provider on this
2229
- machine. **Do not retry the same call unchanged** — it fails identically.
2230
-
2231
- ### 4. Parallel strategy
2232
- - Independent subtasks: cheap-worker(jobs=[{task,label?},...]) ⇒ fan-out, **cap 10**, results come back
2233
- **in the order you passed them** (label is only a display name).
2234
- - For programmable pipeline/phase orchestration at scale, use the platform's workflow tool instead.
2235
-
2236
- ## Completion criteria
2237
- - The child's run settles; done=true only when stopReason="completed" — otherwise read "diagnostic"
2238
- (and "output" for whatever partial text was produced).
2239
- `;
2240
2126
  //#endregion
2241
2127
  //#region src/trajectory/session.ts
2242
- /** `provider/model` → agentOptions(由 delegate/core 提供,保持单一实现) */
2128
+ /** `provider/model` → agentOptions(由 `model-string.ts` 提供,保持单一实现) */
2243
2129
  const trajectoryAgents = /* @__PURE__ */ new Map();
2244
2130
  /** 查 sessionId 的活体 agent(进程内会话延续用;未注册/已清理 → undefined) */
2245
2131
  function getTrajectoryAgent(sessionId) {
@@ -2567,4 +2453,4 @@ function trajectoryConstraintMsmGate(root, sessionId, action, name) {
2567
2453
  return {};
2568
2454
  }
2569
2455
  //#endregion
2570
- export { buildResourceIndex as A, verifyPassword as C, recordToolUsage as D, verifyTotpCode as E, hasTrajectoryPrompt as F, isSafeSkillName as M, truncateContent as N, REFERENCE_DIR as O, TRAJECTORY_PROMPT_FILENAME as P, toWire as S, MECHANISM_PORTS as T, registerEntrySkillSectionGlobal as _, trajectoryConstraintFor as a, projectKnownWorkspaces as b, trajectoryWorkspaceMdPath as c, CHEAP_WORKER_GUIDE as d, providerAvailabilityError as f, registerEntrySkillSection as g, registerCognitiveTrajectorySkillSection as h, getTrajectoryAgent as i, buildResourceNameSuffix as j, SKILL_ONTOLOGY_FILE as k, unregisterTrajectorySession as l, splitModel as m, deliverToTrajectory as n, trajectoryConstraintMsmGate as o, requireWhitelistedModel as p, ensureWorkspacePromptSection as r, trajectoryConstraintParticipates as s, createTrajectoryAgent as t, workspaceCognitiveTrajectoryLine as u, applyWirePatch as v, FACE_PORTS as w, readAdvancedSettings as x, migrateLegacyLocalstore as y };
2456
+ export { truncateContent as A, verifyTotpCode as C, buildResourceIndex as D, SKILL_ONTOLOGY_FILE as E, hasTrajectoryPrompt as M, buildResourceNameSuffix as O, MECHANISM_PORTS as S, REFERENCE_DIR as T, projectKnownWorkspaces as _, trajectoryConstraintFor as a, verifyPassword as b, trajectoryWorkspaceMdPath as c, splitModel as d, registerCognitiveTrajectorySkillSection as f, migrateLegacyLocalstore as g, applyWirePatch as h, getTrajectoryAgent as i, TRAJECTORY_PROMPT_FILENAME as j, isSafeSkillName as k, unregisterTrajectorySession as l, registerEntrySkillSectionGlobal as m, deliverToTrajectory as n, trajectoryConstraintMsmGate as o, registerEntrySkillSection as p, ensureWorkspacePromptSection as r, trajectoryConstraintParticipates as s, createTrajectoryAgent as t, workspaceCognitiveTrajectoryLine as u, readAdvancedSettings as v, recordToolUsage as w, FACE_PORTS as x, toWire as y };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * surface/status.ts — 状态与安全模式操作(纯逻辑,零 DSH 依赖,可独立单测)
3
3
  *
4
- * WebUI 停靠栏的数据源:ACC 版本 / CCC 根 / safe-mode 状态 / 黑名单 / keeper 阈值 / cheap-worker 模型。
4
+ * WebUI 停靠栏的数据源:ACC 版本 / CCC 根 / safe-mode 状态 / 黑名单 / keeper 阈值。
5
5
  * setSafeMode 直接读写 .serenity-safe-on 标记(守卫实时读取,写即生效)。
6
6
  */
7
7
  import { type TrajectorySummary } from '../trajectory/core.js';
@@ -56,7 +56,6 @@ interface SerenityStatus {
56
56
  message?: string;
57
57
  }[];
58
58
  threshold: number | null;
59
- cheapWorkerModel: string | null;
60
59
  /**
61
60
  * 活跃轨迹清单(owner 2026-10-18:CCC 状态面板要展示"所有没有归档的轨迹")。
62
61
  * 🔴 判据源 = `listActiveTrajectories`(它内含 `_` 前缀跳过 ⇒ 归档区自动不在域内);
@@ -14,7 +14,7 @@
14
14
  * 存储结构(JSON 顶层分节):
15
15
  * { "credentials": { "HOME_GITLAB_TOKEN": "xxx" }, "<config节>": { "<key>": "v" } }
16
16
  * credentials 为保留节(credential 命名空间,key 大写蛇形);其余节归 config 命名空间
17
- * (path = section.key,如 cheap-worker.models)。
17
+ * (path = section.key,如 my-feature.someKey)。
18
18
  */
19
19
  import type { JsonValue } from '../../kernel/json.js';
20
20
  /** 命名空间:credential(凭据)| config(配置) */