@shgroup/dsh-serenity-hooks 1.73.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 +18 -12
- package/dsh.plugin.json +2 -2
- package/lib/accounts-BHQbakUh.js +33 -0
- package/lib/{ccc-CZUOq3NY.js → ccc-CyYJL4F2.js} +9 -9
- package/lib/{ccc-roots-BhoA7G-0.js → ccc-roots-BVxn97dY.js} +4 -4
- package/lib/client.js +116 -1
- package/lib/cro/core.d.ts +11 -1
- package/lib/cro/log.d.ts +54 -4
- package/lib/guard/seam.d.ts +4 -4
- package/lib/host/effect.d.ts +1 -1
- package/lib/im/bridge.d.ts +3 -3
- package/lib/im/endpoint.d.ts +2 -2
- package/lib/im/guard.d.ts +1 -1
- package/lib/im/hook.d.ts +1 -1
- package/lib/im/inbound-event.d.ts +6 -6
- package/lib/im/route.d.ts +25 -3
- package/lib/index.d.ts +5 -5
- package/lib/index.js +680 -295
- package/lib/kernel/ccc-roots.d.ts +4 -4
- package/lib/kernel/ccc.d.ts +20 -19
- package/lib/kernel/ports.d.ts +1 -1
- package/lib/{message-source-ChyVfev9.js → message-source-JhN-qyfn.js} +2 -2
- package/lib/patches/opencode-provider.d.ts +1 -1
- package/lib/{profile-BIQ2widI.js → profile-Cz4oBXlI.js} +197 -65
- package/lib/{route-ItCgAsnz.js → route-COOFLTpU.js} +44 -6
- 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-UcwIPJhM.js → settings-CII0Y597.js} +40 -26
- package/lib/surface/faces.d.ts +1 -1
- package/lib/surface/http.d.ts +1 -1
- package/lib/surface/settings.d.ts +7 -7
- package/lib/surface/text.d.ts +3 -3
- package/lib/tools/config-docs.d.ts +71 -0
- package/lib/tools/container-admin.d.ts +24 -12
- package/lib/tools/msm/service.d.ts +18 -0
- package/lib/tools/trajectory-constraint-admin.d.ts +30 -0
- package/lib/trajectory/carrier.d.ts +1 -1
- package/lib/trajectory/core.d.ts +11 -1
- package/lib/trajectory/policy/files.d.ts +75 -0
- package/lib/trajectory/policy/profile.d.ts +41 -36
- package/lib/trajectory/policy/rules.d.ts +33 -20
- package/lib/trajectory/policy/window.d.ts +13 -13
- package/lib/trajectory/prompt.d.ts +12 -12
- package/lib/trajectory/rebuild.d.ts +2 -2
- package/lib/trajectory/session.d.ts +49 -49
- package/package.json +2 -2
- package/lib/tools/skiff-admin.d.ts +0 -30
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.js";
|
|
2
|
-
import { s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-
|
|
2
|
+
import { s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS } from "./ccc-CyYJL4F2.js";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
@@ -288,7 +288,7 @@ function runLocalStore(root, args) {
|
|
|
288
288
|
* 职责(零 DSH 依赖,可独立单测):
|
|
289
289
|
* - 读取 CCC 的 weixin 配置(.opencode/serenity.json weixin 段——结构/路由/开关)
|
|
290
290
|
* - 读取/写入 CCC localstore 的账号凭据(weixin.accounts.<accountId>.token/.baseUrl/.userId)
|
|
291
|
-
* - 微信用户 →
|
|
291
|
+
* - 微信用户 → 轨迹约束会话 id 映射(固定可重建:skiff-weixin-<sha256(userid)>.slice(1, 17);
|
|
292
292
|
* v1.27.3 错位一位避开损坏 log)
|
|
293
293
|
* - 路由匹配(exact user → 通配 * 兜底)
|
|
294
294
|
*
|
|
@@ -300,7 +300,9 @@ var route_exports = /* @__PURE__ */ __exportAll({
|
|
|
300
300
|
extractWeixinMedia: () => extractWeixinMedia,
|
|
301
301
|
extractWeixinText: () => extractWeixinText,
|
|
302
302
|
hasVoiceItem: () => hasVoiceItem,
|
|
303
|
+
imCredentialBound: () => imCredentialBound,
|
|
303
304
|
matchWeixinRoute: () => matchWeixinRoute,
|
|
305
|
+
nextFeishuAccountId: () => nextFeishuAccountId,
|
|
304
306
|
nextWeixinAccountId: () => nextWeixinAccountId,
|
|
305
307
|
readFeishuCredential: () => readFeishuCredential,
|
|
306
308
|
readImSettings: () => readImSettings,
|
|
@@ -313,6 +315,7 @@ var route_exports = /* @__PURE__ */ __exportAll({
|
|
|
313
315
|
upsertWeixinAccount: () => upsertWeixinAccount,
|
|
314
316
|
weixinInboundDir: () => weixinInboundDir,
|
|
315
317
|
weixinSessionIdForTrajectory: () => weixinSessionIdForTrajectory,
|
|
318
|
+
writeFeishuCredential: () => writeFeishuCredential,
|
|
316
319
|
writeWeixinCredential: () => writeWeixinCredential
|
|
317
320
|
});
|
|
318
321
|
/** localstore 凭据键前缀(**credential scope**——token 是凭据,走 UPPER_SNAKE 键;
|
|
@@ -323,10 +326,10 @@ function accountKeyPart(accountId) {
|
|
|
323
326
|
return accountId.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
|
|
324
327
|
}
|
|
325
328
|
/**
|
|
326
|
-
* 微信桥
|
|
329
|
+
* 微信桥 轨迹约束会话 id 前缀(守卫识别"外部面"用)。
|
|
327
330
|
*
|
|
328
|
-
* ⚠️ **2026-10-19 起它只是命名习惯,不再是判据** ——
|
|
329
|
-
* 判据 = 「绑定的轨迹有 `
|
|
331
|
+
* ⚠️ **2026-10-19 起它只是命名习惯,不再是判据** —— 轨迹约束的身份是**轨迹**,
|
|
332
|
+
* 判据 = 「绑定的轨迹有 `trajectory-constraint.json`」(`trajectory/policy/profile.ts` 的 `isTrajectoryConstrained`)。
|
|
330
333
|
* 保留前缀只为:① 日志/会话列表里一眼认出这是外部面;② 存量会话目录名不变。
|
|
331
334
|
*/
|
|
332
335
|
const WEIXIN_SESSION_PREFIX = "skiff-weixin-";
|
|
@@ -340,7 +343,7 @@ const WEIXIN_SESSION_PREFIX = "skiff-weixin-";
|
|
|
340
343
|
* 对不上旧会话的历史工具清单)。⇒ 那不是"轨迹是一等公民",那是"用户是一等公民"。
|
|
341
344
|
*
|
|
342
345
|
* 新派生 = **由轨迹编码决定**:同一条轨迹 ⇒ 恒同一条 dsh 会话(无论谁在跟它说话);
|
|
343
|
-
* 换轨迹 ⇒ 新会话。这正是"
|
|
346
|
+
* 换轨迹 ⇒ 新会话。这正是"轨迹约束是认知轨迹的一种"。
|
|
344
347
|
*
|
|
345
348
|
* ## 连带删掉的东西
|
|
346
349
|
*
|
|
@@ -507,6 +510,28 @@ function readFeishuCredential(root, accountId) {
|
|
|
507
510
|
appSecret
|
|
508
511
|
};
|
|
509
512
|
}
|
|
513
|
+
/** 写入飞书账号凭据(面板保存后;两者都必写——只写一半等于没绑) */
|
|
514
|
+
function writeFeishuCredential(root, accountId, cred) {
|
|
515
|
+
writeEntry(root, "credential", feishuLsKey(accountId, "APPID"), cred.appId);
|
|
516
|
+
writeEntry(root, "credential", feishuLsKey(accountId, "SECRET"), cred.appSecret);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* **按渠道判「该账号是否已绑定凭据」**(面板读数用;单一处)。
|
|
520
|
+
*
|
|
521
|
+
* 🔴 为什么需要它(2026-10-19 P2 面板实测缺陷):面板原先对所有账号都调
|
|
522
|
+
* `readWeixinCredential`(只看 `WEIXIN_<A>_TOKEN`)。一个**飞书**账号的凭据在
|
|
523
|
+
* `FEISHU_<A>_APPID|SECRET`,走那条读法**必然读到 null** ⇒ 面板把一个配好的飞书账号
|
|
524
|
+
* 显示成「未绑定凭据」,用户据此以为没配上。
|
|
525
|
+
*
|
|
526
|
+
* 判据与装配处**同源**(`im/bridge.ts` 的 `readImCredentialByChannel`):飞书要 appId **且**
|
|
527
|
+
* appSecret,微信只要有 token。两处若各写一份判据,就会重演"两个读数器给出不同答案"。
|
|
528
|
+
*
|
|
529
|
+
* ⚠️ 只回**布尔**,不回任何凭据值 —— 这是 wire 面。
|
|
530
|
+
*/
|
|
531
|
+
function imCredentialBound(root, accountId, channel) {
|
|
532
|
+
if ((channel ?? "").trim() === "feishu") return readFeishuCredential(root, accountId) !== null;
|
|
533
|
+
return readWeixinCredential(root, accountId) !== null;
|
|
534
|
+
}
|
|
510
535
|
/**
|
|
511
536
|
* 路由匹配:exact user 优先,通配 `*` 兜底。
|
|
512
537
|
* @returns 命中的**轨迹编码**;未命中 → null(无路由 → 消息不回复/忽略)
|
|
@@ -645,6 +670,19 @@ function nextWeixinAccountId(settings) {
|
|
|
645
670
|
while (used.has(`wechat-${n}`)) n++;
|
|
646
671
|
return `wechat-${n}`;
|
|
647
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* 生成下一个可用飞书账号 id(`feishu-N`,N 取**最小未占用**)。
|
|
675
|
+
*
|
|
676
|
+
* 与 {@link nextWeixinAccountId} 分开而不是加参数:两者的**前缀不同**,
|
|
677
|
+
* 而前缀是给人看的(面板上一眼分清哪些账号来自哪个渠道)。
|
|
678
|
+
* 判据相同(最小未占用,删中间不跳号)。
|
|
679
|
+
*/
|
|
680
|
+
function nextFeishuAccountId(settings) {
|
|
681
|
+
const used = new Set((settings.accounts ?? []).map((a) => a.accountId));
|
|
682
|
+
let n = 1;
|
|
683
|
+
while (used.has(`feishu-${n}`)) n++;
|
|
684
|
+
return `feishu-${n}`;
|
|
685
|
+
}
|
|
648
686
|
/** 切换总开关 */
|
|
649
687
|
function setWeixinEnabled(root, enabled) {
|
|
650
688
|
const next = {
|
package/lib/seams/guards.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import type { Context } from 'cordis';
|
|
10
10
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
11
11
|
import { type BlacklistRule } from '../kernel/ccc.js';
|
|
12
|
-
import { type
|
|
12
|
+
import { type TrajectoryConstraint } from '../trajectory/policy/profile.js';
|
|
13
13
|
export interface GuardInput {
|
|
14
14
|
root: string;
|
|
15
15
|
toolName: string;
|
|
@@ -20,13 +20,13 @@ export interface GuardInput {
|
|
|
20
20
|
/** container_fs 等复合工具的子命令 action(只读子命令不查黑名单) */
|
|
21
21
|
action?: string;
|
|
22
22
|
/**
|
|
23
|
-
* 该会话的
|
|
23
|
+
* 该会话的 轨迹约束面(`null`/`undefined` = 不是 轨迹约束会话 ⇒ 不判定)。
|
|
24
24
|
*
|
|
25
25
|
* 🔴 2026-10-19 起传**已解析好的约束面**,不传 sessionId:解判据("这条轨迹有没有
|
|
26
|
-
* `
|
|
26
|
+
* `trajectory-constraint.json`")留在唯一入口 `profile.ts`,守卫只消费结果 ⇒ 纯函数里不再做 IO,
|
|
27
27
|
* 也不可能出现"守卫的判据与 schema 收窄的判据不一致"。
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
trajectoryConstraint?: TrajectoryConstraint | null;
|
|
30
30
|
}
|
|
31
31
|
interface GuardDecisionResult {
|
|
32
32
|
deny?: string;
|
|
@@ -102,21 +102,21 @@ export declare function forgetHostScheduleToolHiding(sessionId: string): void;
|
|
|
102
102
|
export declare function getExclusiveToolsDiagnostics(): {
|
|
103
103
|
hidden: string[];
|
|
104
104
|
};
|
|
105
|
-
/**
|
|
106
|
-
export declare function
|
|
105
|
+
/** 轨迹约束工具面诊断(排查"某工具为什么不在 轨迹约束的清单里") */
|
|
106
|
+
export declare function getTrajectoryConstraintVisibilityDiagnostics(): {
|
|
107
107
|
keys: string[];
|
|
108
108
|
denyByKey: Record<string, string[]>;
|
|
109
109
|
};
|
|
110
110
|
/**
|
|
111
|
-
* 同步
|
|
111
|
+
* 同步 **轨迹约束会话的工具面**:把白名单之外的工具**从 schema 移除**(不是"看得到但被拒")。
|
|
112
112
|
*
|
|
113
113
|
* ## 为什么必须有这条(owner 2026-10-19:「工具清单也要热加载」)
|
|
114
114
|
*
|
|
115
|
-
*
|
|
115
|
+
* 在它之前,轨迹约束白名单**只由运行时守卫拦截**(`decideGuard` 的 轨迹约束 分支):
|
|
116
116
|
* 工具全部出现在模型 schema 里,调用时才被打回。⇒ 两个真实后果:
|
|
117
117
|
* ① **模型看得见它不该有的工具** —— 它会去试,试了才撞墙(一轮白烧,且错误文案泛化,
|
|
118
118
|
* 看不出"是不在清单里"还是"临时性拒绝");
|
|
119
|
-
* ② **配置变动在 schema 上永远不生效** —— 改 `
|
|
119
|
+
* ② **配置变动在 schema 上永远不生效** —— 改 `trajectory-constraint.json` 的 `tools` 只影响"调用是否放行"。
|
|
120
120
|
*
|
|
121
121
|
* ## 判据与降级
|
|
122
122
|
*
|
|
@@ -124,17 +124,17 @@ export declare function getSkiffRoleVisibilityDiagnostics(): {
|
|
|
124
124
|
* 不去动宿主的工具 —— 宿主的工具由各自的条件同步管)。
|
|
125
125
|
* - ⚠️ **未注册的名字会让整次 restrict 失败**(宿主契约逐字 "unknown names … fail"),
|
|
126
126
|
* 而 `diagram` 是按开关注册的 ⇒ 与 `hideAllFor` 同款**两档尝试**(先全覆盖,失败退常驻段)。
|
|
127
|
-
* - 读不到约束面(不是
|
|
128
|
-
* ⛔ 不能只是 `return` —— 那会把上一步的隐藏**永久留在**一个已不再是
|
|
129
|
-
* (这正是 owner 说的"删掉 `
|
|
127
|
+
* - 读不到约束面(不是 轨迹约束 / 配置删了)⇒ **撤销既有隐藏**(回到"无约束"):
|
|
128
|
+
* ⛔ 不能只是 `return` —— 那会把上一步的隐藏**永久留在**一个已不再是 轨迹约束的会话上
|
|
129
|
+
* (这正是 owner 说的"删掉 `trajectory-constraint.json` 就该立刻恢复")。
|
|
130
130
|
* - 幂等:算出来的 deny 签名不变就跳过(不每步重建 schema)。
|
|
131
131
|
*
|
|
132
132
|
* @param agent 目标会话
|
|
133
133
|
* @param root CCC 根
|
|
134
134
|
*/
|
|
135
|
-
export declare function
|
|
135
|
+
export declare function syncTrajectoryConstraintToolVisibility(agent: Agent, root: string): void;
|
|
136
136
|
/** 会话销毁清理(lifecycle 调用) */
|
|
137
|
-
export declare function
|
|
137
|
+
export declare function forgetTrajectoryConstraintToolVisibility(sessionId: string): void;
|
|
138
138
|
/**
|
|
139
139
|
* 同步专属工具可见性(v1.33)。
|
|
140
140
|
*
|
package/lib/seams/keeper.d.ts
CHANGED
|
@@ -85,7 +85,7 @@ export declare function __resetLogbookCompactionForTest(): void;
|
|
|
85
85
|
* 解析**活跃** SESSION.md 绝对路径(缓存 60s)。
|
|
86
86
|
*
|
|
87
87
|
* 候选链(刻意比 rebuild 的完整链短——这里每个工具调用都要跑,贵候选不划算):
|
|
88
|
-
* ① `getActiveSessionInfo(scope).mdPath`(`cognitive_trajectory use` /
|
|
88
|
+
* ① `getActiveSessionInfo(scope).mdPath`(`cognitive_trajectory use` / 轨迹约束 绑定 / 重启恢复都会写)
|
|
89
89
|
* ② `readLastBound(session).mdPath`(`.bindings.json` 权威绑定——重启后内存空时兜底)
|
|
90
90
|
* 两者都拿不到 → null(**不猜**:宁可不提醒,也不去猜别的轨迹——对齐 v1.30.13 D4 的教训)。
|
|
91
91
|
*/
|
package/lib/seams/lifecycle.d.ts
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* 两个此前缺失的收尾面:
|
|
5
5
|
*
|
|
6
6
|
* ① **会话/agent 销毁 → 清理 per-会话内存态**。dsp 有约 10 处 per-会话 Map
|
|
7
|
-
* (活跃 SESSION
|
|
7
|
+
* (活跃 SESSION 作用域、轨迹约束 注册表、keeper 计分、guard 白名单缓存、bootstrap
|
|
8
8
|
* 晋升状态、输出守卫状态…)。此前无人订阅 `agent/disposed` / `session/disposed`
|
|
9
9
|
* (宿主 0.1.2-rc.1 真实存在:`core/agent/src/runtime-types.ts:175`、
|
|
10
10
|
* `core/session/src/index.ts:62`),长跑进程里这些 Map 只增不减——且 `waitIdle`
|
|
11
11
|
* 在 agent 先被销毁时永不结算。
|
|
12
12
|
*
|
|
13
|
-
* ② **插件卸载/HMR/profile 重载 →
|
|
13
|
+
* ② **插件卸载/HMR/profile 重载 → 停掉自起的监听器与轮询器**。轨迹约束调试页、微信桥轮询
|
|
14
14
|
* 都是 dsp 自己起的资源(⚠️ 2026-10-15:原同批还有 ACP HTTP 端点,该面已退役);
|
|
15
15
|
* 此前没有 `ctx.effect` 拆卸,卸载后端口仍被占用(EADDRINUSE)、轮询器重复启动。
|
|
16
16
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { f as hostSettings } from "./ccc-roots-
|
|
2
|
-
import { _ as resolveInside, g as readUtf8 } from "./ccc-
|
|
1
|
+
import { f as hostSettings } from "./ccc-roots-BVxn97dY.js";
|
|
2
|
+
import { _ as resolveInside, g as readUtf8 } from "./ccc-CyYJL4F2.js";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -56,26 +56,26 @@ const ACC_VERSION = (() => {
|
|
|
56
56
|
*
|
|
57
57
|
* | 模块 | 管什么 |
|
|
58
58
|
* |---|---|
|
|
59
|
-
* | `./profile.ts` | **判据 + 读盘**("这是不是
|
|
59
|
+
* | `./profile.ts` | **判据 + 读盘**("这是不是 轨迹约束"、"约束面是什么") |
|
|
60
60
|
* | `./rules.ts`(本文件) | **从约束面派生出的纯函数**(白名单集合、提示词读取器、基础提示词文本) |
|
|
61
61
|
* | `../session-create.ts` | 会话创建/复用、提问、守门查询 |
|
|
62
62
|
*
|
|
63
|
-
* ⇒ 本文件**不再读 `serenity.json
|
|
64
|
-
* 它只接收一个已解析好的 `
|
|
63
|
+
* ⇒ 本文件**不再读 `serenity.json`**:`轨迹约束.roles` 整段已退役(owner 2026-10-19 重做)。
|
|
64
|
+
* 它只接收一个已解析好的 `TrajectoryConstraint`,因此**不涉及任何 IO**(除提示词文件,那是刻意懒读的)。
|
|
65
65
|
*
|
|
66
66
|
* ## S12(2026-10-19,轨迹中心重构)
|
|
67
67
|
*
|
|
68
|
-
* 原名 `role
|
|
68
|
+
* 原名 `role/轨迹约束/config.ts`。改名理由(框架 §6.3「角色不是一个概念,是一段历史」):
|
|
69
69
|
* 它派生的是**某条轨迹的约束面**,与"配置读取"无关(本文件零配置读取,见上一段)
|
|
70
70
|
* ⇒ `config` 这个名字描述的是**它曾经的样子**,`rules` 描述它**现在做的事**。
|
|
71
71
|
*/
|
|
72
72
|
/** 白名单推导 ────────────────────────────────────────────────────────────── */
|
|
73
73
|
/** 提示词来源提示串(`apply` 回执与面板共用;避免两处措辞漂) */
|
|
74
|
-
const
|
|
74
|
+
const TRAJECTORY_CONSTRAINT_HINT = "systemPromptFile hot-reloads by mtime; the rest of trajectory-constraint.json is re-read every turn";
|
|
75
75
|
/**
|
|
76
|
-
* 该
|
|
76
|
+
* 该 轨迹约束会话**可见**的工具面(tools ∪ `msm`)。
|
|
77
77
|
*
|
|
78
|
-
* 🔴 `msm` 为什么自动加入:`msms` 非空意味着这个
|
|
78
|
+
* 🔴 `msm` 为什么自动加入:`msms` 非空意味着这个 轨迹约束 **有 MSM 通道**,
|
|
79
79
|
* 而 MSM 的唯一合法调用入口是 `msm` 工具(单入口纪律)——不给它 `msm` 就等于
|
|
80
80
|
* 声明了一堆调不动的能力。⚠️ 这是**并集**,不是覆盖:`tools` 里显式写的照旧生效。
|
|
81
81
|
*/
|
|
@@ -85,12 +85,12 @@ function profileToolWhitelist(profile) {
|
|
|
85
85
|
if ((profile?.msms?.length ?? 0) > 0) out.add("msm");
|
|
86
86
|
return out;
|
|
87
87
|
}
|
|
88
|
-
/** 该
|
|
88
|
+
/** 该 轨迹约束会话可 exec 的 MSM 白名单(`msm` 工具内部再过滤;独立于工具白名单) */
|
|
89
89
|
function profileMsmWhitelist(profile) {
|
|
90
90
|
return new Set(profile?.msms ?? []);
|
|
91
91
|
}
|
|
92
|
-
/** 轨迹纪律参与项(`profile` 缺省已在 `
|
|
93
|
-
function
|
|
92
|
+
/** 轨迹纪律参与项(`profile` 缺省已在 `readTrajectoryConstraintAt` 归一为全 true) */
|
|
93
|
+
function constraintCognitiveTrajectory(profile) {
|
|
94
94
|
return {
|
|
95
95
|
session: profile?.cognitiveTrajectory.session === true,
|
|
96
96
|
keeper: profile?.cognitiveTrajectory.keeper === true,
|
|
@@ -105,18 +105,32 @@ function profileCognitiveTrajectory(profile) {
|
|
|
105
105
|
*
|
|
106
106
|
* ⚠️ 热路径**不用**它(那会用每次工具调用去读盘)——热路径用 `createProfilePromptReader`。
|
|
107
107
|
*/
|
|
108
|
-
function
|
|
108
|
+
function resolveConstraintSystemPrompt(root, profile) {
|
|
109
109
|
if (!profile) return "";
|
|
110
110
|
const file = profile.systemPromptFile?.trim();
|
|
111
111
|
if (file) {
|
|
112
112
|
const abs = resolveInside(root, file);
|
|
113
|
-
if (!existsSync(abs)) throw new Error(
|
|
113
|
+
if (!existsSync(abs)) throw new Error(`轨迹约束 "${profile.code}": systemPromptFile "${file}" not found (resolved: ${abs})`);
|
|
114
114
|
return readUtf8(abs).trim();
|
|
115
115
|
}
|
|
116
116
|
return profile.systemPrompt ?? "";
|
|
117
117
|
}
|
|
118
|
-
/**
|
|
119
|
-
|
|
118
|
+
/**
|
|
119
|
+
* 提示词来源(`list`/`validate` 展示用)。
|
|
120
|
+
*
|
|
121
|
+
* 🔴 **2026-10-19 修(T4 的漏网面)**:v1.72.0 起提示词有两代来源——**新形态**
|
|
122
|
+
* 是轨迹目录里的 `PROMPT.md`(`trajectory/prompt.ts`,**优先**),旧形态才是
|
|
123
|
+
* `systemPromptFile` / `systemPrompt`。本函数原先只认旧形态 ⇒ 两条只写了 `PROMPT.md`
|
|
124
|
+
* 的轨迹在 `container_admin config list` 里恒显示 `promptSource: 'none'`。
|
|
125
|
+
*
|
|
126
|
+
* 那是**读数器过时**,不是配置缺失:`validate` 侧早已按两条来源判(见
|
|
127
|
+
* `trajectory-constraint-admin.ts` 的 `hasTrajectoryPromptOrLegacy`),而 `list` 侧漏了。
|
|
128
|
+
* ⇒ 返 **四种**值,把"有章程但来源是新形态"这一格单独说出来。
|
|
129
|
+
*
|
|
130
|
+
* @param hasPromptFile 该轨迹目录下**是否真有** `PROMPT.md`(调用方查,本函数不做 IO)
|
|
131
|
+
*/
|
|
132
|
+
function constraintSystemPromptSource(profile, hasPromptFile = false) {
|
|
133
|
+
if (hasPromptFile) return "trajectory-file";
|
|
120
134
|
if (profile?.systemPromptFile?.trim()) return "file";
|
|
121
135
|
if (profile?.systemPrompt?.trim()) return "inline";
|
|
122
136
|
return "none";
|
|
@@ -144,7 +158,7 @@ function createProfilePromptReader(root, profile) {
|
|
|
144
158
|
try {
|
|
145
159
|
abs = resolveInside(root, file);
|
|
146
160
|
} catch (err) {
|
|
147
|
-
console.warn(`[serenity-hooks] ✗
|
|
161
|
+
console.warn(`[serenity-hooks] ✗ 轨迹约束提示词路径非法(${file}): ${String(err?.message ?? err)}`);
|
|
148
162
|
}
|
|
149
163
|
if (abs === null) return () => "";
|
|
150
164
|
const absPath = abs;
|
|
@@ -162,19 +176,19 @@ function createProfilePromptReader(root, profile) {
|
|
|
162
176
|
cachedSize = st.size;
|
|
163
177
|
cachedText = text;
|
|
164
178
|
warned = false;
|
|
165
|
-
if (isReload) console.info(`[serenity-hooks] ↻
|
|
179
|
+
if (isReload) console.info(`[serenity-hooks] ↻ 轨迹约束提示词已热重载(${file},${text.length} 字符)`);
|
|
166
180
|
return text;
|
|
167
181
|
} catch (err) {
|
|
168
182
|
if (!warned) {
|
|
169
183
|
warned = true;
|
|
170
|
-
console.warn(`[serenity-hooks] ✗
|
|
184
|
+
console.warn(`[serenity-hooks] ✗ 轨迹约束提示词读取失败(${file})——沿用上次成功内容: ${String(err?.message ?? err)}`);
|
|
171
185
|
}
|
|
172
186
|
return cachedText;
|
|
173
187
|
}
|
|
174
188
|
};
|
|
175
189
|
}
|
|
176
190
|
/**
|
|
177
|
-
*
|
|
191
|
+
* 轨迹约束 基础提示词(dsp 只给这部分;CCC 的 `systemPrompt` 段由调用方拼接)。
|
|
178
192
|
*
|
|
179
193
|
* ## 🔴 为什么**不再枚举**清单(owner 2026-10-19 令)
|
|
180
194
|
*
|
|
@@ -190,11 +204,11 @@ function createProfilePromptReader(root, profile) {
|
|
|
190
204
|
*
|
|
191
205
|
* ⇒ 现在只声明**边界与发现路径**,不抄内容:清单在哪,怎么取,越界会怎样。
|
|
192
206
|
*
|
|
193
|
-
* @param code
|
|
207
|
+
* @param code 轨迹编码(轨迹约束的身份 —— 不是"角色名",那个概念已退役)
|
|
194
208
|
*/
|
|
195
|
-
function
|
|
209
|
+
function buildTrajectoryBasePrompt(code) {
|
|
196
210
|
return [
|
|
197
|
-
"=== Serenity
|
|
211
|
+
"=== Serenity 轨迹约束 ===",
|
|
198
212
|
`Cognitive trajectory: ${code} (this is the trajectory you ARE, not a role you play)`,
|
|
199
213
|
"Your capability boundary is enforced mechanically by this CCC — anything outside it is rejected at the call site, not by your judgment.",
|
|
200
214
|
"Discover your surface, do not memorize it (both are generated from the live config on every turn):",
|
|
@@ -233,7 +247,7 @@ function defaultSimpleSettings() {
|
|
|
233
247
|
* `meta.volatile` **无条件**包 `createVolatile(value)`,且该分支排在"缺省值回退"那一段
|
|
234
248
|
* **之前** ⇒ **"用户没设过"的字段也是恒真对象**(`.get()` 返回 `undefined`),**不是 `undefined`**。
|
|
235
249
|
*
|
|
236
|
-
* ⇒ 若这里不解包,下面十行的 `??` 链会**短路在这层包装上** ⇒ 网关 /
|
|
250
|
+
* ⇒ 若这里不解包,下面十行的 `??` 链会**短路在这层包装上** ⇒ 网关 / 轨迹约束 会被
|
|
237
251
|
* **无意打开**(比"面板不显示"更坏:静默改变对外暴露面)。
|
|
238
252
|
*
|
|
239
253
|
* ## 为什么用结构判定
|
|
@@ -319,7 +333,7 @@ function simpleSettingsFromConfig(config) {
|
|
|
319
333
|
/** 运行时源(`registerSettingsSection` 装配:读本插件 fiber 的**当前** Config) */
|
|
320
334
|
let simpleSource = null;
|
|
321
335
|
/**
|
|
322
|
-
* 读取当前简单配置(各功能 gateway/rebuild
|
|
336
|
+
* 读取当前简单配置(各功能 gateway/rebuild/轨迹约束/… 的启动与运行时判断都经此)。
|
|
323
337
|
*
|
|
324
338
|
* 源 = 本插件 fiber 的 `config`(宿主在配置变更时走 `fiber.update()` ⇒ `config` 始终最新,
|
|
325
339
|
* **不必**依赖 apply 重跑,也不必缓存)。
|
|
@@ -351,4 +365,4 @@ function registerSettingsSection(ctx, config) {
|
|
|
351
365
|
} catch {}
|
|
352
366
|
}
|
|
353
367
|
//#endregion
|
|
354
|
-
export {
|
|
368
|
+
export { buildTrajectoryBasePrompt as a, createProfilePromptReader as c, resolveConstraintSystemPrompt as d, ACC_VERSION as f, TRAJECTORY_CONSTRAINT_HINT as i, profileMsmWhitelist as l, readSimpleSettings as n, constraintCognitiveTrajectory as o, findPackageRoot as p, registerSettingsSection as r, constraintSystemPromptSource as s, SERENITY_SETTINGS_NS as t, profileToolWhitelist as u };
|
package/lib/surface/faces.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* ## 现状 → 本模块要收掉什么(取证:`…/acc-c4c5-current-state.md` §①/§③ 3.1)
|
|
5
5
|
*
|
|
6
|
-
* 插件自己 spawn 了**三个** node:http 监听器(B 3081 网关 / C 3082 微信发送 / D 3099
|
|
6
|
+
* 插件自己 spawn 了**三个** node:http 监听器(B 3081 网关 / C 3082 微信发送 / D 3099 轨迹约束调试)。
|
|
7
7
|
* ⚠️ **2026-10-15 变更**:原为四个(含 **E 3100 ACP+问答**),E 已随 owner「砍掉外部问答」令**整面退役**
|
|
8
8
|
* ⇒ 仍保有面 B/C/D 三个;本段保留"当年是四个"的记述,因为下方"两套拆卸"的病史由它解释。
|
|
9
9
|
* 此前四处各写一份同款样板:`createServer` + `server.once('error')` +
|
package/lib/surface/http.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ interface StatusApiRegistration {
|
|
|
39
39
|
*
|
|
40
40
|
* 🔴🔴 **2026-10-18 修缺陷(owner 报「在别的 CCC 点开显示的还是 home-serenity 的信息」)**:
|
|
41
41
|
* 旧实现第 ③ 步是「**遍历 live sessions 找第一个 CCC 会话的 cwd**」—— 那是**跨工作区猜测**:
|
|
42
|
-
* 只要 sessionId 缺失或那条会话查不到(ACP
|
|
42
|
+
* 只要 sessionId 缺失或那条会话查不到(ACP/轨迹约束会话、尚未 materialize 的会话、远程访问),
|
|
43
43
|
* 它就会**静默返回另一个 CCC 的路径**,于是面板把**别人的轨迹/技能/安全模式**当成你的显示出来。
|
|
44
44
|
* 这比"显示未激活"危险得多 —— 用户会据此做判断(以为自己的 safe-mode 开着、以为那是自己的轨迹)。
|
|
45
45
|
*
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* ## 为什么旧扁平键**原样保留**(这是本文件最容易被后人改错的地方)
|
|
16
16
|
*
|
|
17
17
|
* 旧模型把简单配置存成 `~/.dsh/settings.yaml` 的 `serenity-hooks:` 段,字段名是**扁平**的
|
|
18
|
-
* (`gatewayEnabled` / `
|
|
18
|
+
* (`gatewayEnabled` / `轨迹约束Enabled` / …)。新模型的命名空间**逐字相同**
|
|
19
19
|
* (`serenity-hooks`),而宿主的 `SettingsForms.importLegacyDocument()` 会把该段
|
|
20
20
|
* **按同名条目导入**;schemastery 的 object 解析在非 strict 模式下 `merge(result, data)`
|
|
21
21
|
* ⇒ **未声明的键会被保留而非报错**。⇒ 只要这些扁平键**仍在本插件 Config 里声明**,
|
|
@@ -59,12 +59,12 @@ interface SimpleConfigFragment {
|
|
|
59
59
|
rebuild?: {
|
|
60
60
|
thresholdK?: number;
|
|
61
61
|
};
|
|
62
|
-
/** F4
|
|
63
|
-
|
|
62
|
+
/** F4 轨迹约束(实验性):调试服务启停(人工) */
|
|
63
|
+
轨迹约束?: {
|
|
64
64
|
enabled?: boolean;
|
|
65
65
|
debugPort?: number;
|
|
66
66
|
};
|
|
67
|
-
/** F4
|
|
67
|
+
/** F4 轨迹约束(实验性):调试服务启停(人工) */
|
|
68
68
|
/** diagram(实验性 demo;2026-09-29 owner 具名令 D104):标签源码 → 进程内出图(不借浏览器) */
|
|
69
69
|
diagram?: {
|
|
70
70
|
enabled?: boolean;
|
|
@@ -103,7 +103,7 @@ interface SerenitySimpleSettings {
|
|
|
103
103
|
* `parseDsl → renderDsl(SVG + 四项体检)→ resvg-wasm 光栅化(内置字体)→ PNG`,
|
|
104
104
|
* 产物落 CCC `_tmp/diagram/` 且**图片块进对话**(**不借浏览器、不截图**)。
|
|
105
105
|
* **缺省关**:owner 口中的"demo 功能" ⇒ 关时**不注册**(工具不进模型工具清单:
|
|
106
|
-
* 零 token、不会被误调),同
|
|
106
|
+
* 零 token、不会被误调),同 `轨迹约束` 的"未开启零资源占用"口径。
|
|
107
107
|
* 依赖面:随包分发 3.8 MB 内置字体(`assets/diagram/`,wasm 对系统字体不可见)。 */
|
|
108
108
|
diagramEnabled: boolean;
|
|
109
109
|
/** **human-channel(人机信道)机器级配置**(2026-09-26 owner 定案;P0-1 立 schema + 投影)。
|
|
@@ -128,7 +128,7 @@ interface VolatileRef<T> {
|
|
|
128
128
|
* `meta.volatile` **无条件**包 `createVolatile(value)`,且该分支排在"缺省值回退"那一段
|
|
129
129
|
* **之前** ⇒ **"用户没设过"的字段也是恒真对象**(`.get()` 返回 `undefined`),**不是 `undefined`**。
|
|
130
130
|
*
|
|
131
|
-
* ⇒ 若这里不解包,下面十行的 `??` 链会**短路在这层包装上** ⇒ 网关 /
|
|
131
|
+
* ⇒ 若这里不解包,下面十行的 `??` 链会**短路在这层包装上** ⇒ 网关 / 轨迹约束 会被
|
|
132
132
|
* **无意打开**(比"面板不显示"更坏:静默改变对外暴露面)。
|
|
133
133
|
*
|
|
134
134
|
* ## 为什么用结构判定
|
|
@@ -220,7 +220,7 @@ export declare function humanChannelSettingsFromConfig(fragment: HumanChannelCon
|
|
|
220
220
|
*/
|
|
221
221
|
export declare function simpleSettingsFromConfig(config: SimpleConfigFragment): SerenitySimpleSettings;
|
|
222
222
|
/**
|
|
223
|
-
* 读取当前简单配置(各功能 gateway/rebuild
|
|
223
|
+
* 读取当前简单配置(各功能 gateway/rebuild/轨迹约束/… 的启动与运行时判断都经此)。
|
|
224
224
|
*
|
|
225
225
|
* 源 = 本插件 fiber 的 `config`(宿主在配置变更时走 `fiber.update()` ⇒ `config` 始终最新,
|
|
226
226
|
* **不必**依赖 apply 重跑,也不必缓存)。
|
package/lib/surface/text.d.ts
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* ## 为什么它从调试面里拆出来(S11,2026-10-19,轨迹中心重构)
|
|
5
5
|
*
|
|
6
|
-
* 拆之前它是 `role
|
|
6
|
+
* 拆之前它是 `role/轨迹约束/debug.ts` 的**后半段**,而那份文件是**混装件**:
|
|
7
7
|
* · 前半段 = **面 D** 的 HTTP 调试页(自起 listener,端口见 `kernel/ports.ts`)
|
|
8
8
|
* · 后半段 = **通用文本清洗**(本文件,已随重构搬到 `surface/text.ts`)
|
|
9
9
|
*
|
|
10
|
-
* 判据(实测,不是猜):本文件的导出被**两个与
|
|
10
|
+
* 判据(实测,不是猜):本文件的导出被**两个与 轨迹约束 无关的模块**直接使用 ——
|
|
11
11
|
* `im/bridge.ts`(微信桥:回复前剥 think)与 `guard/seam.ts`(输出守卫:检测前剥 think)。
|
|
12
12
|
* ⇒ 它不属于"某一条轨迹的调试面",它是**任何输出面都会用的清洗**。
|
|
13
13
|
*
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* **hideThink=true(v1.26.4,public 口)→ 直接移除**(思考过程对普通用户不展示)
|
|
29
29
|
* @param hideThink 为 true 时 `<think>` 内容完全不渲染(public 问答页体验)
|
|
30
30
|
*/
|
|
31
|
-
export declare function
|
|
31
|
+
export declare function renderTrajectoryMarkdown(raw: string, hideThink?: boolean): string;
|
|
32
32
|
/**
|
|
33
33
|
* 剥离 `<think>…</think>` 块(v1.27.1,微信桥用户反馈:"过微信桥回复给用户的消息,
|
|
34
34
|
* 要去掉 think 标签,用户不应看到")。复用 extractThinkBlocks 状态机(v1.26.8,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tools/config-docs.ts — `container_admin config docs` 的**两层菜单**(P3,2026-10-19)
|
|
3
|
+
*
|
|
4
|
+
* ## owner 原话(本文件存在的全部理由,逐字)
|
|
5
|
+
*
|
|
6
|
+
* > 「im 的整体配置方法要在 ACC 级有方法能交代我们的**说明类内容**越来越多了,
|
|
7
|
+
* > 做个**两层菜单**来承载吧,admin 里面搞两个方法,一个是**使用说明目录**,
|
|
8
|
+
* > 一个是**使用说明详情(按章节获得)**」
|
|
9
|
+
*
|
|
10
|
+
* ⇒ 第一层 `docs`(无参)= **目录**:只列"有哪几章、每章一句话、去哪个子命令看详情"。
|
|
11
|
+
* 第二层 `docs <chapter>` = **详情**:该章全文。
|
|
12
|
+
*
|
|
13
|
+
* ## 为什么是"目录 + 按章详情"而不是一坨长文(R↓,这不是排版偏好)
|
|
14
|
+
*
|
|
15
|
+
* 说明类内容已经长到 `ccc-config` 单份约 20 KB。整份塞进一次工具返回有两个真实代价:
|
|
16
|
+
* ① **截断** —— 宿主对工具结果有预算(超了走 head/tail + 落盘)⇒ 用户拿到的**不是全文**,
|
|
17
|
+
* 而是它以为的全文(本轨 A59 记过这一格)。
|
|
18
|
+
* ② **不可发现** —— 一坨长文里"我该看哪一段"要靠通读才知道;目录让模型**先选后读**。
|
|
19
|
+
* ⇒ 判据:**目录只索引,不复制**。每章正文的唯一真相源仍在它自己的产出函数里
|
|
20
|
+
* (本章 = `ccc-config` 的对应段 / `role guide` 全文),本文件只做**切分与路由**。
|
|
21
|
+
*
|
|
22
|
+
* ## 归属(D23)
|
|
23
|
+
* 机制在 ACC(有哪几章、怎么切、怎么路由);**章目内容**部分来自 ACC 自己的 guide
|
|
24
|
+
* (那些是机制说明),部分来自 CCC 的配置现状(运行时读取)。
|
|
25
|
+
*
|
|
26
|
+
* ## 与 `msm catalog` 的分工(两个目录不是冗余)
|
|
27
|
+
* - `msm catalog` = **工具/能力**目录("去哪找功能说明")
|
|
28
|
+
* - `config docs` = **配置**目录("这个键怎么填、填错会怎样")
|
|
29
|
+
* 二者在 ④ 章互指,但**不复制**对方的内容。
|
|
30
|
+
*/
|
|
31
|
+
/** 一个章节 = 菜单项(第一层)+ 正文(第二层) */
|
|
32
|
+
export interface DocsChapter {
|
|
33
|
+
/** 章节 id(稳定标识:`config docs <id>`;**英文短名**,便于逐字敲出来) */
|
|
34
|
+
id: string;
|
|
35
|
+
/** 菜单里的一句话(用户据此决定要不要读下去) */
|
|
36
|
+
summary: string;
|
|
37
|
+
/** 该章正文(第二层才返回;**惰性**——目录不触发它) */
|
|
38
|
+
render: () => string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 渲染**目录**(第一层)。
|
|
42
|
+
*
|
|
43
|
+
* 🔴 只调 `summary`,**绝不调 `render`** —— 目录若触发正文,就退化成"整份长文"。
|
|
44
|
+
* 这条不是性能优化,是**判据**:它保证 `docs` 的输出大小与章数成正比,与正文长度无关。
|
|
45
|
+
*/
|
|
46
|
+
export declare function renderDocsIndex(chapters: readonly DocsChapter[]): string;
|
|
47
|
+
/**
|
|
48
|
+
* 解析一个章节参数(第二层)。
|
|
49
|
+
*
|
|
50
|
+
* 不存在 ⇒ 返回 `null`,由调用方给出**带候选清单**的拒绝 ——
|
|
51
|
+
* "不知道这个章节" 与 "这一章是空的" 必须可区分(否则用户以为功能没有)。
|
|
52
|
+
*/
|
|
53
|
+
export declare function findDocsChapter(chapters: readonly DocsChapter[], id: string): DocsChapter | null;
|
|
54
|
+
/**
|
|
55
|
+
* **指针文案**(v1.75.0,owner 裁 Q3「指针」)——被降级的旧入口共用这一份。
|
|
56
|
+
*
|
|
57
|
+
* ## 为什么要有"指针"这个形态(而不是直接删掉旧入口)
|
|
58
|
+
*
|
|
59
|
+
* 旧入口的名字(`msm catalog` / `msm ccc-config` / `config guide`)**已经写在 CCC 侧的
|
|
60
|
+
* 文档与提示词里**,硬删会让它们全部变成"未知动作",而且**没有任何机械信号**告诉我们
|
|
61
|
+
* 哪份文档已经说谎了(本仓 D151 同族)。
|
|
62
|
+
*
|
|
63
|
+
* ⇒ 保留名字、只换返回内容:调用方能**自己顺着指针找到正文**,而正文仍然只有一份。
|
|
64
|
+
*
|
|
65
|
+
* 🔴 **必须只有一处实现**:`container-admin.ts`(config 域)与 `msm/service.ts`(msm 域)
|
|
66
|
+
* 都要用它。两处各写一份文案 ⇒ 措辞漂移(本仓反复踩过的形态)。
|
|
67
|
+
*
|
|
68
|
+
* @param chapter 正文所在的章 id
|
|
69
|
+
* @param what 这个入口原来叫什么(进标题,让调用方一眼确认自己找对了)
|
|
70
|
+
*/
|
|
71
|
+
export declare function docsPointer(chapter: string, what: string): string;
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* container-admin.ts — container_admin(v1.30:机务舱——容器管理面统一入口)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* · skiff_admin(F4 Skiff 认知子集角色:guide/validate/apply/list)
|
|
6
|
-
* · acc_msm 管理面(register/deregister/check/guide/catalog/ccc-config)
|
|
7
|
-
* —— msm 工具只管执行+发现;一切「管理容器」的操作归本工具
|
|
4
|
+
* ## 域结构(2026-10-19 owner 两条令后:**两域**)
|
|
8
5
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* | 域 | 管什么 |
|
|
7
|
+
* |---|---|
|
|
8
|
+
* | `config` | **本 CCC 的全部配置面**:说明目录/按章详情 + 轨迹约束(原 `role` 域,已并入) |
|
|
9
|
+
* | `msm` | MSM 注册表管理 + 手册(register/deregister/check/guide/catalog/ccc-config) |
|
|
10
|
+
*
|
|
11
|
+
* 🔴 **`role` 域已并入 `config`**(owner 2026-10-19 裁「1 并入」)。为什么不是三个平行域:
|
|
12
|
+
* `role` 管的本来就是"某条轨迹的约束面"——**一组配置**,与 `config` 是同一抽象层的两半。
|
|
13
|
+
* 分着放的代价是:用户在 `config` 里看不到"轨迹怎么约束",得先知道 `role` 这个词存在。
|
|
14
|
+
* ⚠️ **旧 `role` 域仍被接受**(过渡别名,指向同一实现)——存量 CCC 的文档/脚本里到处是
|
|
15
|
+
* `container_admin role validate`(实测本仓 30 处),硬切会让它们全部变成"未知域"。
|
|
16
|
+
* 别名**只保留读取路径**:schema 的 `enum` 只列新名,文案只教新名。
|
|
12
17
|
*
|
|
13
|
-
*
|
|
18
|
+
* ## 三个动作名为什么是这三个(P3 的实现形态)
|
|
19
|
+
* - `config docs`(无参)→ **使用说明目录**(第一层;只索引不复制)
|
|
20
|
+
* - `config docs <chapter>` → **使用说明详情**(第二层;按章获得)
|
|
21
|
+
* - `config view` → 配置**现值**(原来是唯一动作;现在是"看当前填了什么")
|
|
14
22
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `ctx` 现**无消费者**,工厂形态保留只是为了让装配点签名不再变动(见 index.ts 注册处)。
|
|
23
|
+
* 归属(D23):**机制在 ACC**(有哪几章、怎么路由、怎么校验),**内容在 CCC**(填什么)。
|
|
24
|
+
* 语义(用户拍板"轨迹约束_admin 及系列 admin 合并成 container_admin"):
|
|
25
|
+
* container = CCC(具体认知容器);admin = 管理操作。
|
|
19
26
|
*/
|
|
20
27
|
import type { Context } from 'cordis';
|
|
28
|
+
/**
|
|
29
|
+
* 指针与章目的关系(v1.75.0):
|
|
30
|
+
* 被降级的旧入口(`msm catalog` / `msm ccc-config` / `config guide`)统一走
|
|
31
|
+
* `config-docs.ts` 的 `docsPointer()` —— **只有一处实现**,避免两域各写一份文案而漂移。
|
|
32
|
+
*/
|
|
21
33
|
export declare function createContainerAdminTool(ctx: Context): import("@deepseek-ai/dsh-tools").ToolDefinition;
|