@shgroup/dsh-serenity-hooks 1.26.15 → 1.26.17

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 (61) hide show
  1. package/dsh.plugin.json +1 -1
  2. package/experiments/autotrajectory/SKILL.md +14 -8
  3. package/experiments/autotrajectory/scripts/autotrajectory-exp.ts +23 -6
  4. package/lib/acp-core.d.ts +100 -0
  5. package/lib/acp-http.d.ts +29 -0
  6. package/lib/api.d.ts +47 -0
  7. package/lib/autotrajectory.d.ts +193 -0
  8. package/lib/ccc-CfDrlfA7.js +141 -0
  9. package/lib/ccc.d.ts +162 -0
  10. package/lib/client.js +5 -0
  11. package/lib/config-ops.d.ts +166 -0
  12. package/lib/constants.d.ts +8 -0
  13. package/lib/fs-ops.d.ts +36 -0
  14. package/lib/gateway-auth.d.ts +89 -0
  15. package/lib/gateway-proxy.d.ts +39 -0
  16. package/lib/gateway.d.ts +80 -0
  17. package/lib/git-ops.d.ts +28 -0
  18. package/lib/handyman-ops.d.ts +68 -0
  19. package/lib/handyman-preset-inherit.d.ts +34 -0
  20. package/lib/index.d.ts +68 -0
  21. package/lib/index.js +10 -8
  22. package/lib/invariant.d.ts +29 -0
  23. package/lib/json.d.ts +9 -0
  24. package/lib/kit-ops.d.ts +23 -0
  25. package/lib/localstore-ops.d.ts +85 -0
  26. package/lib/msm-ops.d.ts +78 -0
  27. package/lib/output-guard-seam.d.ts +21 -0
  28. package/lib/output-guard.d.ts +68 -0
  29. package/lib/rebuild.d.ts +118 -0
  30. package/lib/seams/bootstrap.d.ts +83 -0
  31. package/lib/seams/compact.d.ts +31 -0
  32. package/lib/seams/context.d.ts +48 -0
  33. package/lib/seams/env.d.ts +16 -0
  34. package/lib/seams/guards.d.ts +72 -0
  35. package/lib/seams/keeper.d.ts +61 -0
  36. package/lib/seams/opencode-skills.d.ts +14 -0
  37. package/lib/seams/system-prompt.d.ts +113 -0
  38. package/lib/session-ops.d.ts +127 -0
  39. package/lib/settings-section.d.ts +113 -0
  40. package/lib/skiff-core.d.ts +78 -0
  41. package/lib/skiff-debug.d.ts +86 -0
  42. package/lib/skiff-registry.d.ts +25 -0
  43. package/lib/skiff-role.d.ts +50 -0
  44. package/lib/skills/opencode-scan.d.ts +27 -0
  45. package/lib/skills-discovery.d.ts +25 -0
  46. package/lib/status.d.ts +38 -0
  47. package/lib/tools/autotrajectory-exp.d.ts +24 -0
  48. package/lib/tools/cc-fs.d.ts +7 -0
  49. package/lib/tools/cce.d.ts +9 -0
  50. package/lib/tools/eap.d.ts +7 -0
  51. package/lib/tools/git.d.ts +4 -0
  52. package/lib/tools/handyman.d.ts +43 -0
  53. package/lib/tools/kit.d.ts +4 -0
  54. package/lib/tools/localstore.d.ts +8 -0
  55. package/lib/tools/msm.d.ts +4 -0
  56. package/lib/tools/neat.d.ts +5 -0
  57. package/lib/tools/rebuild.d.ts +19 -0
  58. package/lib/tools/session.d.ts +78 -0
  59. package/lib/tools/skiff-admin.d.ts +25 -0
  60. package/lib/totp.d.ts +40 -0
  61. package/package.json +6 -4
@@ -0,0 +1,80 @@
1
+ /**
2
+ * gateway.ts — F1 双端口网关(v1.21)+ 安全加固(v1.22.4)——**装配层**
3
+ *
4
+ * 需求(S142 用户拍板):dsh web 维持 127.0.0.1 主端口现状不变,**额外监听一个端口**;
5
+ * 额外端口需网页登录(账号+密码),登录后即原生 Web UI 使用;适应任何部署情况。
6
+ *
7
+ * 实现(零改 DSH):
8
+ * - 插件自起第二 node:http server(host/port 走 localstore 配置,默认 0.0.0.0:3081)
9
+ * - 未登录 → 返回内嵌极简登录页(user + pass + submit)
10
+ * - POST /serenity/login → 验证账号(localstore accounts,scrypt hash)→ Set-Cookie(HttpOnly)
11
+ * - 已登录 → 反向代理到 http://127.0.0.1:${ctx.webServer.port}
12
+ * (Host 头改写成 127.0.0.1:<主端口> → 过信任栅栏;WS upgrade 转发握手 + pipe socket)
13
+ * - token 内存表 + HttpOnly cookie(重启即失效——用户决策"重启重新登录")
14
+ *
15
+ * v1.22.4 安全加固(S142 公网审计,用户原则:不体验影响直接修/体验影响改方案/不限制 IP):
16
+ * - S5:token 带过期时间(滑动 24h)+ POST /serenity/logout 主动吊销
17
+ * - S3:登录 POST 与配置写操作校验 Origin(同源/loopback 主端口)+ 双提交 CSRF cookie
18
+ * - S2:账号维度失败锁定(5 次失败 → 15 分钟,指数退避)——不按 IP(用户要求随时随地访问)
19
+ * - S1:可选 TOTP 第二因素(账号绑定后登录需 6 位码;Authenticator 兼容,RFC 6238)
20
+ * - S7:cookieSecure 配置项(反代 TLS 时开启;默认关保持明文 HTTP 可用)
21
+ * - S9:登录失败审计日志(时间/IP/账号/原因,console.warn)
22
+ *
23
+ * v1.22.8 熵点治理(S142):认证域纯逻辑拆到 gateway-auth.ts(会话/锁定/CSRF/Origin/
24
+ * cookie/登录页),代理辅助纯逻辑拆到 gateway-proxy.ts(polyfill/headers/workspace 过滤);
25
+ * 本文件只保留 HTTP 装配(startGateway/registerGateway/readBody)——re-export 两模块
26
+ * 保持既有 import 面兼容(tests/gateway.test.ts 直接 import 两模块导出)。
27
+ */
28
+ import type { Context } from 'cordis';
29
+ import { type Server } from 'node:http';
30
+ export { RANDOM_UUID_POLYFILL, injectPolyfillHtml, filterWorkspaceList, workspaceAllowed, workspaceDenyResponse, buildProxyHeaders, } from './gateway-proxy.js';
31
+ export { loginPageHtml, verifyGatewayLogin, SESSION_TTL_MS, issueToken, revokeToken, validateToken, FAIL_LOCK_THRESHOLD, FAIL_LOCK_BASE_MS, FAIL_LOCK_MAX_MS, getFailState, resetFailState, isAccountLocked, recordLoginFailure, accountLockRemaining, newCsrfToken, isCsrfValid, csrfFromRequest, safeEqual, originAllowed, cookieValue, } from './gateway-auth.js';
32
+ declare module 'cordis' {
33
+ interface Events {
34
+ /** /serenity/config PUT(账号/监听/白名单变化)→ 强制重建 gateway(lastSig=null) */
35
+ 'serenity/config-updated'(): void;
36
+ /** DSH settings 简单配置变化(开关/阈值)→ 重新 sync(sig 判断,无实质变化不重建) */
37
+ 'serenity/settings-changed'(): void;
38
+ }
39
+ }
40
+ export interface GatewayConfig {
41
+ host: string;
42
+ port: number;
43
+ /** 登录态 cookie 名 */
44
+ cookieName: string;
45
+ /** 主端口(ctx.webServer.port) */
46
+ mainPort: number;
47
+ /** 登录失败后的重定向延迟(秒) */
48
+ loginDelayMs: number;
49
+ /** 外部可访问的工作区路径前缀白名单(v1.22;空 = 全部允许) */
50
+ allowWorkspaces?: string[];
51
+ /** Cookie Secure 属性(v1.22.4;反代 TLS 时开启;明文 HTTP 下必须关,否则 cookie 不落) */
52
+ cookieSecure?: boolean;
53
+ /** 允许外部新建工作区(v1.22.4;false = workspace.create 一律 403 RPC error) */
54
+ allowWorkspaceCreate?: boolean;
55
+ /** 启用 Authenticator 第二因素(v1.22.4;false = TOTP 完全禁用) */
56
+ totpEnabled?: boolean;
57
+ }
58
+ /**
59
+ * 启动第二监听器。返回 { server, dispose }——dispose 关 server(**不清 token**:
60
+ * token 模块级,进程重启自然清空;热重建清 token → 已登录用户 WS 断 + 重连 cookie 无效)。
61
+ * @param config - 监听/代理配置。
62
+ * @param getAccounts - 运行时读取账号列表(plugin 全局文件;gateway.enabled 开关在调用方判)。
63
+ */
64
+ export declare function startGateway(config: GatewayConfig, getAccounts: () => readonly {
65
+ id: string;
66
+ user: string;
67
+ passHash: string;
68
+ totpSecret?: string;
69
+ }[]): {
70
+ server: Server;
71
+ dispose: () => void;
72
+ };
73
+ /** 注册 gateway(index.ts apply 调用)。
74
+ * 归属原则(v1.22):gateway 是 plugin 全局能力——enabled 开关读 DSH settings
75
+ * (readSimpleSettings().gatewayEnabled),host/port/accounts 读 plugin 全局文件
76
+ * (readAdvancedSettings(),~/.dsh/serenity-hooks.json)。**不依赖任何具体 CCC**。
77
+ * 幂等 sync:仅当 配置/端口/开关 变化时重建监听器。
78
+ * 事件驱动:config-updated(/serenity/config PUT 后 emit)+ DSH settings 变化(onChange emit)触发重新 sync。
79
+ */
80
+ export declare function registerGateway(ctx: Context): void;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * git-ops.ts — cc_git 纯操作层(零 DSH 依赖)
3
+ *
4
+ * 行为对齐 osp(opencode-serenity-plugin/src/git/cc-git-tool.ts)——osp 是 ACC 工具 spec:
5
+ * - status:JSON {clean, files:[{status,file}], summary}
6
+ * - commit:git add -A + commit -m;clean 返回 '(nothing to commit — working tree clean)'
7
+ * - push:无 remote 报错;非快进 → [REJECTED] + 操作建议(绝不自动 force)
8
+ * - pull:git fetch + merge --ff-only;up-to-date / [REJECTED] 建议
9
+ * - log:--oneline [-n <count>]
10
+ * - diff:git diff [--cached] [<ref>] [-- <path>]
11
+ * 保留 dsp 增强:localstore git 合规联动(S134:deny 且 .gitignore 未覆盖 → status 提示 / commit 拒绝)。
12
+ */
13
+ import type { JsonValue } from './json.js';
14
+ export type GitAction = 'status' | 'commit' | 'push' | 'log' | 'pull' | 'diff';
15
+ export declare const GIT_ACTIONS: readonly GitAction[];
16
+ export interface GitArgs {
17
+ action: GitAction;
18
+ message?: string;
19
+ /** log 条数(对齐 osp 参数 n,默认 10,max 100) */
20
+ count?: number;
21
+ /** diff: 显示暂存区变更(--cached) */
22
+ staged?: boolean;
23
+ /** diff: 对比 ref(如 HEAD~1 / main / origin/main) */
24
+ ref?: string;
25
+ /** diff: 限定路径 */
26
+ path?: string;
27
+ }
28
+ export declare function runGit(root: string, args: GitArgs): JsonValue;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * handyman-ops.ts — handyman(杂工)纯逻辑层(零 DSH 依赖,可独立单测)
3
+ *
4
+ * v1.24.0:loop(牛马)→ handyman(杂工)重命名。语义对齐 osp loop:
5
+ * 进度文件(handyman-<label>.md/.json)、续跑、轮次 prompt 结构、stop token。
6
+ * 不兼容旧 loop- 进度文件(用户拍板:仅新 handyman- 前缀)。
7
+ */
8
+ export interface HandymanProgress {
9
+ round: number;
10
+ done: boolean;
11
+ label: string;
12
+ model: string;
13
+ updated: string;
14
+ lastResponse: string;
15
+ /** 对齐 osp writeFailedStatus:failed 时 done=true + status=failed + errorCode */
16
+ status?: 'running' | 'done' | 'failed';
17
+ errorCode?: string;
18
+ errorMessage?: string;
19
+ }
20
+ /** label 脱敏(Windows 审计问题 17):非法字符 → '-',去尾点/空格,限长(按码点截断,修复代理对切散 U+FFFD) */
21
+ export declare function sanitizeLabel(label: string): string;
22
+ export declare function handymanProgressPaths(root: string, label: string): {
23
+ md: string;
24
+ json: string;
25
+ };
26
+ /** 读取进度(续跑);无文件返回 round 0 */
27
+ export declare function readProgress(root: string, label: string): HandymanProgress | null;
28
+ export declare function writeProgress(root: string, label: string, p: HandymanProgress): void;
29
+ /** 失败状态落盘(对齐 osp writeFailedStatus:done=true / status=failed / errorCode) */
30
+ export declare function writeFailedStatus(root: string, label: string, info: {
31
+ errorCode: string;
32
+ errorMessage?: string;
33
+ }): void;
34
+ export declare function newStopToken(): string;
35
+ /** 解析 model 字符串(provider/model)→ {provider, model};无 / 视为 model-only */
36
+ export declare function splitModel(model: string): {
37
+ provider: string | undefined;
38
+ model: string;
39
+ };
40
+ /** 校验模型在白名单内;不在 → 抛错(用户拍板:只能使用 CCC 配置的模型) */
41
+ export declare function requireWhitelistedModel(model: string, models: string[]): void;
42
+ /** 轮次 prompt(对齐老 loop 结构:回顾进度 → 自由工作 → 汇报;S134 EAP 化:固定详尽) */
43
+ export declare function buildRoundPrompt(opts: {
44
+ root: string;
45
+ session?: string;
46
+ label: string;
47
+ round: number;
48
+ stopToken: string;
49
+ progress?: HandymanProgress | null;
50
+ task?: string;
51
+ }): string;
52
+ /**
53
+ * handyman 规模化使用指引(guide 子命令输出;S134 继承 + v1.24.0 更新):
54
+ * 使用 handyman 前必须先加载 eap 设计方案;并行策略(jobs 编排);提示词规范(详尽固定 EAP);
55
+ * 阅读/文字编写类 handyman 内部也加载 eap。
56
+ */
57
+ export declare const HANDYMAN_GUIDE = "# handyman \u2014 Scale-Up Usage Guide (guide)\n\n## \u26A0\uFE0F Before using: load eap and design the plan\nBefore calling handyman, load eap (acc-eap skill) and design the \"scale-up handyman plan\" based on the EAP framework.\n\n### 1. Task decomposition (E\u2191 Explicit)\n- Split large tasks into explicit subtasks: each subtask defines goal / input / boundaries (what to do, what not to do) / acceptance criteria\n- Make dependencies explicit: dependent tasks run serially, independent ones can run in parallel\n\n### 2. Prompt design (handyman's task parameter)\n- task must be detailed, fixed, and EAP-compliant: clear goal, drawn boundaries, decidable acceptance criteria\n- Anti-example \"handle this file\" \u2014 ambiguous; good example \"read <path>, extract all rows of the\u300C\u5173\u952E\u51B3\u7B56\u300Dtable,\n output a JSON array (fields id/conclusion/evidence), do not modify the original file\"\n- Reading/curating or text-writing work (extracting from files, summarizing, writing docs, generating text, etc.):\n the handyman-internal agent is also required to load eap and organize output per the EAP standard\n\n### 3. Model whitelist (CCC-configured, mandatory)\n- handyman only uses models listed in .opencode/serenity.json \"handyman.models\" \u2014 never arbitrary models\n- Recursive subagents inside a handyman inherit the handyman's model automatically (DSH native)\n- Keep the subagent tool instance free of a fixed agentOptions, or model inheritance breaks\n\n### 4. Parallel strategy (jobs orchestration, workflow capability)\n- Independent subtasks can run in parallel via handyman(jobs=[...]): each job gets its own label + task + stop token + progress file\n- Concurrency safety guaranteed: unique sessionId (handyman-<label>-<uuid>), progress files isolated per label\n (AGENT_SESSIONS/handyman-<label>.json) \u2014 same label resumes, different labels never interfere\n- Parallel cap: handyman.maxParallel (default 10 \u2014 cheap models are cheap)\n- Aggregation: after each parallel job produces progress, the main agent merges (or spawns one aggregation handyman)\n- For programmable pipeline/phase orchestration at scale, use the platform's workflow tool instead\n\n## Completion criteria (osp loop standard)\n- The only completion condition = the handyman-internal agent echoes this round's random verification code (stop token); dialogue round cap (default 100, osp fail-safe, forced stop beyond the cap, resumable)\n- Automatic restart on abnormal agent stop (\u2264100 restarts, anti-infinite-loop)\n\n## Waiting UI\n- The WebUI session-header Serenity detail card shows running handymen's progress (label / round / last response), one line per parallel job, ~3s refresh\n";
58
+ /** handyman 运行状态(进度文件摘要;WebUI 等待界面数据源) */
59
+ export interface HandymanRunInfo {
60
+ label: string;
61
+ round: number;
62
+ done: boolean;
63
+ model: string;
64
+ updated: string;
65
+ lastResponse: string;
66
+ }
67
+ /** 列出 AGENT_SESSIONS/handyman-*.json 的全部进度(按 updated 倒序;坏文件跳过) */
68
+ export declare function listActiveHandymen(root: string): HandymanRunInfo[];
@@ -0,0 +1,34 @@
1
+ /**
2
+ * handyman-preset-inherit.ts — handyman worker 的 preset 继承 + 工具面收窄(纯函数,可单测)
3
+ *
4
+ * v1.24.0:loop → handyman 重命名。对齐 subagent 先例(applyChildComposition →
5
+ * agentPresets.composeFrom):handyman worker 在创建窗口内 join 发起方 agent 的 standing
6
+ * preset 组合,从而获得 preset 层工具(read/write/edit 等)。
7
+ *
8
+ * **工具面收窄(用户拍板)**:worker 内部**不含 handyman 工具本身**——递归编排归主
9
+ * agent,worker 内部只走 subagent(模型继承 worker,同样低能)。实现:setup 钩子
10
+ * composeFrom 后对子 scope `tools.restrict({ deny: ['handyman'] })`(同 scope 注册的
11
+ * 规则,最近 scope 胜出——worker 看不到 handyman,主 agent 不受影响)。
12
+ *
13
+ * agentPresets 是可选服务(ctx.get 读取):
14
+ * - 无该服务 / 父未 join preset → 返回空(worker 落全局工具层 + deny handyman);
15
+ * - 有且父已 join → 返回 preset id(写入 session meta 供重建)+ setup 钩子
16
+ * (在 agent 未发布前执行 composeFrom + restrict,失败由创建事务回滚)。
17
+ *
18
+ * 仅依赖 cordis 的 Context 类型(type-only,运行时擦除)——保持可被 vitest
19
+ * 直接加载(与 ccc.ts / handyman-ops.ts 同级的纯模块约定)。
20
+ */
21
+ import type { Context } from 'cordis';
22
+ /** 从父 agent ctx 解析 preset 继承的创建期组合。 */
23
+ export interface HandymanPresetInheritance {
24
+ /** 父 agent 的 preset id(写入子 session meta.agentPreset,供持久化重建);无则不写。 */
25
+ readonly agentPreset?: string;
26
+ /** 创建 setup 钩子:子 scope join 父的 standing preset + deny handyman 工具;无 preset 继承时仅 deny。 */
27
+ readonly setup?: (childCtx: Context) => void;
28
+ }
29
+ /**
30
+ * 解析 handyman worker 从父 agent 继承的 preset,并组装创建 setup 钩子。
31
+ * @param parentCtx - 发起 handyman 的 agent 的 scope ctx;无(headless/非 agent 上下文)时为 undefined。
32
+ * @returns 继承结果:meta 用的 agentPreset 与创建 setup 钩子。
33
+ */
34
+ export declare function handymanPresetInheritance(parentCtx: Context | undefined): HandymanPresetInheritance;
package/lib/index.d.ts ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * dsh-serenity-hooks — 宁静号 ACC harness(Native Cordis 插件,DSH 运行时)
3
+ *
4
+ * 形态(DSH 官方 native hook 约定):name / inject / Config / apply,无 default export。
5
+ *
6
+ * 能力:
7
+ * 1. 真实 DSH 工具注册:cc_fs(文件系统 15 子命令,含 reveal)、session(会话全周期 7 子命令)
8
+ * 2. 拦截缝机械约束:tools/pre-execute + ctx.tools.guard(安全模式/黑名单/路径守卫)
9
+ *
10
+ * 加载:~/.dsh/config.yaml 加 insert 行(免改 DSH 源码),插件包装入 DSH node_modules。
11
+ *
12
+ * 配置:进程级 Config(cordis.yml 提供)+ 运行时读取 CCC 的 .opencode/serenity.json(规范位置,.dsh 回退)。
13
+ */
14
+ import type { Context } from 'cordis';
15
+ import z from '@deepseek-ai/schemastery';
16
+ export declare const name = "dsh-serenity-hooks";
17
+ /** 主动调用的服务;其余(agent 事件)随 harness 装配必然存在 */
18
+ export declare const inject: string[];
19
+ /** 插件配置(cordis.yml 提供;进程级) */
20
+ export interface Config {
21
+ /** CCC 配置相对路径(运行时从根读取);缺省 .opencode/serenity.json(规范)+ .dsh/serenity.json(回退) */
22
+ serenityConfigPaths?: string[];
23
+ /** 注册真实工具 */
24
+ tools?: boolean;
25
+ /** 注册拦截缝守卫 */
26
+ guards?: boolean;
27
+ /** 注册 session-keeper DCP 提醒 */
28
+ keeper?: boolean;
29
+ /** keeper 缺省阈值 */
30
+ keeperThreshold?: number;
31
+ /** 注册 ACC 上下文注入(session-start + prompt-submit) */
32
+ context?: boolean;
33
+ /** 注册压缩保留(compaction/end 后重注入 ACC 身份) */
34
+ compactRetention?: boolean;
35
+ /** 注册 HTTP 状态接口(WebUI 停靠栏) */
36
+ api?: boolean;
37
+ /** 身份注入时并入 CCC 入口 skill 内容(0 = 不注入) */
38
+ entrySkillMaxChars?: number;
39
+ /** 注册 shell.env(DSH_SERENITY_* 环境事实) */
40
+ env?: boolean;
41
+ /** 兼容 opencode skill 标准(provider:.opencode/skills 扫描注册) */
42
+ opencodeSkills?: boolean;
43
+ /** F1 双端口网关(简单配置;entry 默认值,运行时经 DSH settings) */
44
+ gateway?: {
45
+ enabled?: boolean;
46
+ };
47
+ /** F2 超限重建(entry 默认值,运行时经 DSH settings) */
48
+ rebuild?: {
49
+ enabled?: boolean;
50
+ thresholdRatio?: number;
51
+ };
52
+ /** F3 会话命名(entry 默认值,运行时经 DSH settings) */
53
+ naming?: {
54
+ enabled?: boolean;
55
+ };
56
+ /** F4 Skiff(实验性):调试服务启停(entry 默认值,运行时经 DSH settings) */
57
+ skiff?: {
58
+ enabled?: boolean;
59
+ debugPort?: number;
60
+ };
61
+ /** F4c ACP(实验性):HTTP JSON-RPC 端点启停(entry 默认值,运行时经 DSH settings) */
62
+ acp?: {
63
+ enabled?: boolean;
64
+ httpPort?: number;
65
+ };
66
+ }
67
+ export declare const Config: z<Config>;
68
+ export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js CHANGED
@@ -7100,14 +7100,14 @@ async function fetchBiasContent(root, providerRel) {
7100
7100
  error: "偏见内容提供者脚本无法运行(bun 与 node 均不可用)"
7101
7101
  };
7102
7102
  }
7103
- /** 唤起消息(三段式:身份锚定 / 先验偏见[自生动机+偏见内容] / 任务)——注入前台会话,用户可见 */
7103
+ /** 唤起消息(四段式:轨迹焦点[CCC 定义,稳定] / 身份锚定 / 先验偏见[自生动机+偏见内容] / 任务)——注入前台会话,用户可见 */
7104
7104
  function buildWakeMessage(opts) {
7105
- const lines = [
7106
- `[自主轨迹唤起] — 距上次轨迹活动已满 ${opts.intervalHours} 小时,自动继续。`,
7107
- "",
7108
- `身份锚定:继续 ${opts.sessionName} 的 trajectory(SESSION.md: ${opts.mdPath})。`,
7109
- "先验偏见:"
7110
- ];
7105
+ const lines = [];
7106
+ if (opts.topPrompt) {
7107
+ lines.push(`[轨迹焦点] ${opts.topPrompt}`);
7108
+ lines.push("");
7109
+ }
7110
+ lines.push(`[自主轨迹唤起] — 距上次轨迹活动已满 ${opts.intervalHours} 小时,自动继续。`, "", `身份锚定:继续 ${opts.sessionName} 的 trajectory(SESSION.md: ${opts.mdPath})。`, "先验偏见:");
7111
7111
  if (opts.motivation) lines.push(` · 自生动机:${opts.motivation}`);
7112
7112
  if (opts.biasContent) lines.push(` · 偏见内容:${opts.biasContent}`);
7113
7113
  if (!opts.motivation && !opts.biasContent) lines.push(" · (无——本轮纯自主探索)");
@@ -7164,6 +7164,7 @@ async function performAutoTrajectoryWake(ctx, root, settings, opts = {}) {
7164
7164
  sessionName: basename(dirname(mdPath)),
7165
7165
  mdPath,
7166
7166
  intervalHours: Math.max(1, settings.intervalHours ?? 12),
7167
+ topPrompt: settings.topPrompt?.trim() || null,
7167
7168
  motivation,
7168
7169
  biasContent: biasRes.text
7169
7170
  });
@@ -7321,6 +7322,7 @@ function getAutoTrajectoryStatus(root) {
7321
7322
  enabled: cfg?.enabled ?? false,
7322
7323
  intervalHours: Math.max(1, cfg?.intervalHours ?? 12),
7323
7324
  biasProvider: cfg?.biasProvider?.trim() || "autotrajectory-bias.ts",
7325
+ topPrompt: cfg?.topPrompt?.trim() || null,
7324
7326
  session: cfg?.session ?? null,
7325
7327
  avoidWakeHours: {
7326
7328
  start: cfg?.avoidWakeHours?.start ?? DEFAULT_AVOID_HOURS.start,
@@ -7497,7 +7499,7 @@ function renderDiagLive(r) {
7497
7499
  function createAutoTrajectoryExpTool(ctx) {
7498
7500
  return defineTool({
7499
7501
  name: "autotrajectory-exp",
7500
- description: "自主轨迹实验(Self-Sustaining Trajectory)一站式管理——实验提案 v1.26.14,默认关。无参/action=all:全报告(背景摘要 + 就绪检查 + 状态 + 下一步)——CCC agent 看一次即完整理解实验并知道怎么开始;init:初始化辅助(写配置 + 生成偏见提供者脚本模板);random:运行偏见提供者脚本输出当前偏见内容;diag:唤起条件链诊断(--ccc <path> 指定 CCC,无参递归扫描 /home/yh 两层——覆盖任意实验 CCC 位置;逐条件输出 + 阻断点 + 修复建议);diag-live:**进程内诊断**(v1.26.14——live 会话清单/标题/agent 定位/面板解析目标;排查\"面板检测不到实验 CCC\");doc:实验定义全文;check/status/guide:单项。实验是 CCC 的自选动作——dsp 只提供工具与知识,不自动安装任何东西。",
7502
+ description: "自主轨迹实验(Self-Sustaining Trajectory)一站式管理——实验提案 v1.26.14,默认关。无参/action=all:全报告(背景摘要 + 就绪检查 + 状态 + 下一步)——CCC agent 看一次即完整理解实验并知道怎么开始;init:初始化辅助(写配置 + 生成偏见提供者脚本模板);random:运行偏见提供者脚本输出当前偏见内容;diag:唤起条件链诊断(--ccc <path> 指定 CCC,无参递归扫描 /home/yh 两层——覆盖任意实验 CCC 位置;逐条件输出 + 阻断点 + 修复建议);diag-live:**进程内诊断**(v1.26.14——live 会话清单/标题/agent 定位/面板解析目标;排查\"面板检测不到实验 CCC\");doc:实验定义全文;check/status/guide:单项。**topPrompt(v1.26.17,轨迹焦点)**:CCC 定义 autotrajectory 时自己填写本轨迹核心焦点(顶层提示词),每次唤起最先注入——稳定焦点锚定防漂移(实验观察:无焦点多轮唤起轨迹腐化),与偏见内容(每轮随机探索)互补。实验是 CCC 的自选动作——dsp 只提供工具与知识,不自动安装任何东西。",
7501
7503
  parameters: { action: {
7502
7504
  type: "string",
7503
7505
  enum: [...AUTO_TRAJECTORY_EXP_ACTIONS],
@@ -0,0 +1,29 @@
1
+ /**
2
+ * invariant.ts — 包级不变量伴生(dsh-my-rsi creating-a-plugin 规范)
3
+ *
4
+ * 检查:dsh.plugin.json 的 contributes.tools 与代码实际注册的工具一致。
5
+ * 挂载时 plugin-local 会校验清单;本不变量让仓库内 `verify-package-invariants`
6
+ * 类门禁也可直接调用。
7
+ */
8
+ export interface PluginManifest {
9
+ id: string;
10
+ version?: string;
11
+ main?: string;
12
+ description?: string;
13
+ engines?: {
14
+ dsh?: string;
15
+ };
16
+ contributes?: {
17
+ tools?: string[];
18
+ skills?: string[];
19
+ };
20
+ }
21
+ /** 读取插件清单;缺失/非法返回 null */
22
+ export declare function readPluginManifest(manifestPath: string): PluginManifest | null;
23
+ /**
24
+ * 校验清单声明的工具与代码注册的工具一致。
25
+ * 返回不一致项列表(空 = 通过)。
26
+ */
27
+ export declare function verifyToolConsistency(manifestPath: string, registeredTools: readonly string[]): string[];
28
+ /** 包级不变量:本插件注册的工具集合(与 dsh.plugin.json contributes.tools 一致) */
29
+ export declare const REGISTERED_TOOLS: readonly ["cc_fs", "session", "acc_kit", "cc_git", "acc_msm", "eap", "neat", "cce", "handyman", "session_rebuild", "localstore", "skiff_admin"];
package/lib/json.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * json.ts — 本地 JsonValue 类型(与 DSH 的 JsonValue 同构)
3
+ *
4
+ * 纯层(fs-ops/session-ops)保持零 DSH 运行时依赖:仅用本地类型标注,
5
+ * 工具层(defineTool)要求 execute 返回 DSH JsonValue,二者结构等价。
6
+ */
7
+ export type JsonValue = string | number | boolean | null | JsonValue[] | {
8
+ [key: string]: JsonValue;
9
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * kit-ops.ts — acc_kit 纯操作层(零 DSH 依赖)
3
+ *
4
+ * 行为对齐 osp(opencode-serenity-plugin/src/acc-kit.ts)——osp 是 ACC 工具 spec:
5
+ * - health:{ccc, root, version, status: healthy|degraded, principles: {P1_rooted, P2_git_managed, P3_binary_permissions}}
6
+ * - time:{now_iso, now_local, epoch_ms}
7
+ * - wait:缺省 1s(正整数秒),返回 'waited Ns' 文本
8
+ * 平台适配:P3 在 osp 检查 opencode.json,DSH 无 opencode.json → 检查 DSH/opencode 配置路径
9
+ * (.opencode/serenity.json / .dsh/serenity.json 等,见 DEFAULT_SERENITY_CONFIG_PATHS)。
10
+ * CCC 缺失时返回 degraded 报告而非抛错(对齐 osp 未激活语义)。
11
+ * 保留 dsp 增强:accVersion/dshVersion 版本自省字段。
12
+ * wait 用纯 Node setTimeout——不依赖外部 sleep 可执行文件(Windows 无 GNU coreutils sleep)。
13
+ */
14
+ import { loadSerenityConfig } from './ccc.js';
15
+ import type { JsonValue } from './json.js';
16
+ export type KitAction = 'health' | 'time' | 'wait';
17
+ export declare const KIT_ACTIONS: readonly KitAction[];
18
+ export interface KitArgs {
19
+ action: KitAction;
20
+ seconds?: number;
21
+ }
22
+ export declare function runKit(root: string | null, args: KitArgs): Promise<JsonValue>;
23
+ export { loadSerenityConfig };
@@ -0,0 +1,85 @@
1
+ /**
2
+ * localstore-ops.ts — localstore 纯逻辑层(零 DSH 依赖,可独立单测)
3
+ *
4
+ * S134 重设计(v1.16.7):存储从 ~/.serenity/ 迁到 **CCC 根根目录 localstore.json**
5
+ * (JSON 格式——方便 MSM 直接 read + JSON.parse 读取,零解析依赖)。
6
+ *
7
+ * git 提交策略(可靠机制 × 用户自由):
8
+ * - 配置:.opencode/serenity.json `localstore.gitTrack`: "allow"(可提交)| "deny"(禁提交)
9
+ * - **缺省 deny(没配就是不提交)**;且 deny 的保证**不依赖 dsh 运行**——
10
+ * 写入时自动确保 .gitignore 含 localstore.json(物理保证:即使 dsh 不在、
11
+ * 用户手动 git commit 也不会误提交),cc_git 检查为第二道防线(拒绝 + 提示)
12
+ * - allow:放行(文件可提交,用户自行管理 .gitignore)
13
+ *
14
+ * 存储结构(JSON 顶层分节):
15
+ * { "credentials": { "HOME_GITLAB_TOKEN": "xxx" }, "<config节>": { "<key>": "v" } }
16
+ * credentials 为保留节(credential 命名空间,key 大写蛇形);其余节归 config 命名空间
17
+ * (path = section.key,如 handyman.models)。
18
+ */
19
+ import type { JsonValue } from './json.js';
20
+ /** 命名空间:credential(凭据)| config(配置) */
21
+ export type LocalStoreScope = 'credential' | 'config';
22
+ export declare const LOCALSTORE_SCOPES: readonly LocalStoreScope[];
23
+ /** 存储文件名(CCC 根根目录) */
24
+ export declare const LOCALSTORE_FILENAME = "localstore.json";
25
+ /** 凭据保留节名(JSON 顶层) */
26
+ export declare const CREDENTIALS_SECTION = "credentials";
27
+ /** 凭据 key 规范:大写蛇形,如 HOME_GITLAB_TOKEN */
28
+ export declare const CREDENTIAL_KEY_RE: RegExp;
29
+ /** 配置节名规范:小写字母数字连字符 */
30
+ export declare const CONFIG_SECTION_RE: RegExp;
31
+ /** 配置 key 规范(节内):小驼峰,如 defaultModel */
32
+ export declare const CONFIG_KEY_RE: RegExp;
33
+ /** git 提交策略 */
34
+ export type GitTrack = 'allow' | 'deny';
35
+ /** 存储文件绝对路径(CCC 根根目录) */
36
+ export declare function localstorePath(root: string): string;
37
+ /** git 策略:serenity.json localstore.gitTrack,缺省 deny(不提交) */
38
+ export declare function readGitTrack(root: string, paths?: string[]): GitTrack;
39
+ /** .gitignore 是否已覆盖 localstore 文件(非空非注释行含文件名即算) */
40
+ export declare function isLocalstoreGitignored(root: string): boolean;
41
+ /**
42
+ * 确保 .gitignore 含 localstore 文件(deny 时的物理保证,不依赖 dsh 运行):
43
+ * 写入 localstore 时调用——deny(含缺省)且 .gitignore 未覆盖 → 自动追加一行。
44
+ * allow → 不写入(放行,文件可提交)。
45
+ */
46
+ export declare function ensureLocalstoreGitignored(root: string): {
47
+ status: 'allow' | 'ignored' | 'appended';
48
+ };
49
+ /**
50
+ * cc_git 联动检查(第二道防线):文件存在 && deny && .gitignore 未覆盖 → 不通过。
51
+ * 调用方(cc_git commit)据此拒绝提交;status 可输出 warning。
52
+ */
53
+ export declare function checkLocalstoreGitCompliance(root: string): {
54
+ ok: boolean;
55
+ reason?: string;
56
+ };
57
+ /** 读取命名空间全部条目:credential → 扁平;config → 分节(剔除 credentials 保留节) */
58
+ export declare function readStore(root: string, scope: LocalStoreScope): Record<string, string> | Record<string, Record<string, string>>;
59
+ /** 校验凭据 key 合法(大写蛇形);不合法抛错 */
60
+ export declare function assertCredentialKey(key: string): void;
61
+ /** 校验 config 路径(节.key);不合法抛错 */
62
+ export declare function assertConfigPath(path: string): {
63
+ section: string;
64
+ key: string;
65
+ };
66
+ /** 写入单个条目(自动建文件;deny 默认时同步确保 .gitignore 物理保证) */
67
+ export declare function writeEntry(root: string, scope: LocalStoreScope, name: string, value: string): void;
68
+ /** 删除单个条目(不存在返回 false);空节自动移除 */
69
+ export declare function unsetEntry(root: string, scope: LocalStoreScope, name: string): boolean;
70
+ /** 读取单个条目值;不存在返回 null */
71
+ export declare function getEntry(root: string, scope: LocalStoreScope, name: string): string | null;
72
+ /** 列出 key(凭据只返回 key 名,不返回值) */
73
+ export declare function listKeys(root: string, scope: LocalStoreScope): string[];
74
+ /**
75
+ * doc 说明文本:输出存储位置/格式/key 规范/git 策略/读写方法。
76
+ * agent 据此可直接用 fs 工具(read/write)自己读写凭据/配置。
77
+ */
78
+ export declare function docText(root: string): string;
79
+ /** 运行 localstore 操作(纯逻辑;返回 JSON 值供工具 render) */
80
+ export declare function runLocalStore(root: string, args: {
81
+ action: string;
82
+ name?: string;
83
+ value?: string;
84
+ scope?: string;
85
+ }): JsonValue;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * msm-ops.ts — acc_msm 纯操作层(零 DSH 依赖)
3
+ *
4
+ * MSM(Mech & Semi-Mech)框架:list / exec / admin(register|deregister|check)。
5
+ * 复用 CCC 的 mech-registry.json(v1 或数组格式)。cwd 钉在 CCC 根。
6
+ */
7
+ import type { JsonValue } from './json.js';
8
+ export declare const MSM_TIMEOUT_MS = 600000;
9
+ /** CCC 名:从 .serenity 首行解析(对齐 osp readSerenityCccName) */
10
+ export declare function readCccName(root: string): string | null;
11
+ export type MsmAction = 'list' | 'exec' | 'register' | 'deregister' | 'check' | 'guide' | 'ccc-config';
12
+ export declare const MSM_ACTIONS: readonly MsmAction[];
13
+ export declare const MSM_GUIDE = "MSM Development Manual (Mech & Semi-Mech framework)\n\n## What it is\nMSM = the executable-unit layer. Mech is pure TS with zero LLM reasoning; Semi-Mech is a TS framework + LLM decision points.\nMSM is ACC's deterministic executable-unit layer \u2014 all shell/exec operations go through MSM and cannot be bypassed.\n\n## Registering a new MSM (acc_msm register)\n1. Write the script under <skill>/scripts/ (runnable via tsx; must include a main() CLI guard with an import.meta.url check)\n2. acc_msm register <name> --skill <s> --path <script path relative to root> --category <mech|semi-mech> --description <desc>\n3. Auto-writes mech-registry.json (preserving the original format) + git commit (commits only the registry file)\n4. Validation: path must be inside root, script must exist, name must be globally unique\n\n## flag schema (v1)\nflags is a new-style object array for parameter validation and path-escape guarding:\n [{\"name\":\"output\",\"type\":\"string\",\"description\":\"output path\"},\n {\"name\":\"target\",\"type\":\"path\",\"description\":\"operation target (type:path enables in-root validation + symlink defense)\"},\n {\"name\":\"force\",\"type\":\"boolean\",\"description\":\"force mode\",\"default\":false}]\n- {name, type} format \u2014 new style, type:\"path\" enables the path-escape guard\n- {flag, description} format \u2014 old style, CLI flag description string\n- On registration, flags are passed via acc_msm register --flags '<json>' (the tool currently parses the name style)\n\n## Script conventions\n- Top-of-file documentation: purpose / usage / exit codes\n- Exit codes: 0 success / 1 user / 2 system / 3 operator (per ACC protocol classification)\n- main() CLI guard (DC-M2): the script must start with\n if (import.meta.url === `file://${process.argv[1]}`) { main() }\n or an equivalent isMain / require.main === check \u2014 so vitest imports never trigger top-level code\n- A paired .test.ts or .spec.ts (DC-M1, vitest)\n- Business subprocess environment: SERENITY_ROOT / SERENITY_CCC / SERENITY_VERSION injected\n\n## Interaction & confirmation conventions (no blocking confirmation)\n- MSMs run in **user-less subprocesses** (spawn/execFile, 600s timeout) \u2014 **never** use\n readline / prompt / process.stdin etc. to block waiting for user input (it would hang until killed by the timeout)\n- When a second confirmation is needed: **directly return the confirmation request** (list the operation to perform and its impact + how to retry with the confirmation flag),\n returning a non-zero exit code (or an explicit hint)\n- After the agent confirms, **re-invoke the MSM with the confirmation flag** (e.g. --confirm / --yes / --force) to retry\n- Standard mode (two-phase):\n 1. First call: destructive/confirmation-requiring operation detected and no confirmation flag present \u2192 output the confirmation request (list operation/impact/rollback),\n exit non-zero (e.g. 1 user), **perform no changes**\n 2. After the agent evaluates, re-invoke: with the confirmation flag \u2192 execute and output the result\n- Applies to: delete/overwrite/push/batch operations and other irreversible or wide-impact operations\n- Anti-example (forbidden): readline waiting for user input, process.stdin.on('data') blocking waits\n (MSMs have no stdin interaction channel \u2014 they hang until the 600s timeout)\n\n## Quality checks (acc_msm check, DC-M1~M4)\nDC-M1 has .test.ts/.spec.ts; DC-M2 has a main() guard (function main( / isMain / require.main === / import.meta.url);\nDC-M3 bidirectional: scripts unregistered + registry references missing scripts; DC-M4 path-type flags marked type:\"path\"\n\n## Self-description (protocol flags, first argument only)\nacc_msm exec <name> --list \u2014 list all MSMs\nacc_msm exec <name> --schema <n> \u2014 view a specific MSM's parameter schema\nacc_msm exec <name> --format=json \u2014 JSON output mode (remaining args passed through losslessly)\n";
14
+ /** CCC 配置参考(对齐 osp ccc-config action) */
15
+ export declare const CCC_CONFIG_REFERENCE = "\u2550\u2550\u2550 CCC Configuration Reference \u2550\u2550\u2550\n\nCCC-level features are configured in .opencode/serenity.json.\nBelow are all available configuration sections.\n\n\u2500\u2500 1. handyman.models \u2500\u2500\nhandyman\uFF08\u6742\u5DE5\uFF09\u5DE5\u5177\u53EF\u7528\u6A21\u578B\u767D\u540D\u5355\uFF08provider/model \u5217\u8868\uFF09\uFF1B\u672A\u914D\u7F6E\u65F6 handyman \u62A5\u9519\u8981\u6C42\u914D\u7F6E\u3002\n\u7F3A\u7701\u6A21\u578B = models[0]\uFF08\u53EF\u7528 handyman.defaultModel \u6307\u5B9A\uFF0C\u5FC5\u987B \u2208 models\uFF09\u3002\n\n Config:\n { \"handyman\": { \"models\": [\"provider/model-name\"] } }\n\n Example:\n { \"handyman\": { \"models\": [\"minimax-cn-coding-plan/MiniMax-M3\"], \"defaultModel\": \"minimax-cn-coding-plan/MiniMax-M3\", \"maxRounds\": 100, \"maxParallel\": 10 } }\n\n\u2500\u2500 2. sessionKeeper.threshold \u2500\u2500\nSESSION-KEEPER \u63D0\u9192\u673A\u5236\u7684\u79EF\u5206\u9608\u503C\uFF08\u975E headless \u4E3B agent\uFF09\u3002\n\u6309\u5DE5\u5177\u8C03\u7528\u52A0\u6743 + \u8017\u65F6\u8BA1\u5206\uFF1B\u8FBE\u5230\u9608\u503C\u6CE8\u5165\u63D0\u9192\uFF0C\u8981\u6C42\u6A21\u578B\u56DE\u590D ACK \u7801\u3002\n\n Config:\n { \"sessionKeeper\": { \"threshold\": 150 } }\n\n \u8BA1\u5206\uFF1Awrite/edit = 3\uFF0Ctask = 10\uFF0Cread/grep/glob/msm \u7B49 = 1\uFF0C\u65F6\u95F4 = 1/\u5206\u949F\n \u9ED8\u8BA4\uFF1A150\n\n\u2500\u2500 3. localstore.gitTrack \u2500\u2500\nlocalstore.json \u7684 git \u7B56\u7565\uFF1Aallow \u53EF\u63D0\u4EA4 / deny \u7981\u63D0\u4EA4\uFF08\u9ED8\u8BA4 deny\uFF09\u3002\ndeny \u65F6\u5199\u5165\u81EA\u52A8\u786E\u4FDD .gitignore \u542B\u8BE5\u6587\u4EF6\uFF08\u7269\u7406\u4FDD\u8BC1\uFF09\uFF0Ccc_git commit \u4F1A\u68C0\u67E5\u62D2\u7EDD\u3002\n\n Config:\n { \"localstore\": { \"gitTrack\": \"allow\" } }\n\n\u2500\u2500 4. hooks.autoRestoreSession \u2500\u2500\n\u4F1A\u8BDD\u81EA\u52A8\u6062\u590D\uFF08\u9ED8\u8BA4 true\uFF1B\u53D7 events \u95E8\u63A7\u2014\u2014\u4EC5\u6839\u4F1A\u8BDD + \u5DF2\u6709\u5BF9\u8BDD\u5386\u53F2\u624D\u6062\u590D\uFF09\u3002\n\n Config:\n { \"hooks\": { \"autoRestoreSession\": false } }\n\n\u2500\u2500 5. safeMode / blacklist \u2500\u2500\nsafe-mode \u7531 WebUI \u5F00\u5173\u63A7\u5236\uFF08\u5199 .serenity-safe-on \u6807\u8BB0\uFF09\uFF1B\u9ED1\u540D\u5355\u8DEF\u5F84\u53D7 guards seam \u62E6\u622A\u3002\n\n Config:\n { \"safeMode\": { \"blacklist\": [\".secrets/\"] } }\n";
16
+ export interface MsmFlag {
17
+ name: string;
18
+ type?: string;
19
+ description?: string;
20
+ required?: boolean;
21
+ default?: unknown;
22
+ }
23
+ export interface MsmEntry {
24
+ name: string;
25
+ path: string;
26
+ skill?: string;
27
+ category?: string;
28
+ description?: string;
29
+ usage?: string;
30
+ flags?: MsmFlag[];
31
+ }
32
+ export interface MsmArgs {
33
+ action: MsmAction;
34
+ name?: string;
35
+ args?: string[];
36
+ skill?: string;
37
+ path?: string;
38
+ category?: string;
39
+ description?: string;
40
+ /** register: flags JSON 字符串(对齐 osp --flags 入参;如 '[{"name":"hook","type":"string",...}]') */
41
+ flags?: string;
42
+ /** register: 自定义 usage(缺省 'acc_msm exec <name> [args...]') */
43
+ usage?: string;
44
+ }
45
+ export declare function parseRegistry(raw: string): MsmEntry[];
46
+ export declare function findRegistries(root: string): string[];
47
+ export declare function loadMsmEntries(root: string): MsmEntry[];
48
+ export declare function findEntry(root: string, name: string): MsmEntry | null;
49
+ /** 扫描各 skill scripts/ 下的非测试脚本(DC-M3 正向基准,对齐 osp) */
50
+ export declare function scanSkillScripts(root: string): string[];
51
+ export declare function runMsm(root: string, args: MsmArgs): JsonValue;
52
+ /** 解析并校验 exec 参数:返回可执行条目 + 业务参数(list/schema 协议 flag 已分流) */
53
+ export interface PreparedExec {
54
+ entry: MsmEntry;
55
+ businessArgs: string[];
56
+ fmtJson: boolean;
57
+ /** 业务参数是否含 --help/-h(exit≠0 时不追加 TIP,对齐 osp) */
58
+ hasHelp: boolean;
59
+ /** 协议结果(--list / --schema);非协议执行时为 undefined */
60
+ protocol?: {
61
+ list: {
62
+ name: string;
63
+ category: string | null;
64
+ }[];
65
+ } | {
66
+ schema: {
67
+ name: string;
68
+ path: string;
69
+ flags: {
70
+ name: string;
71
+ type: string | null;
72
+ description: string | null;
73
+ }[];
74
+ };
75
+ };
76
+ }
77
+ export declare function prepareExec(root: string, args: MsmArgs): PreparedExec;
78
+ export declare function runMsmAsync(root: string, args: MsmArgs): Promise<JsonValue>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * output-guard-seam.ts — 输出守卫拦截缝(v1.26.3,S142 用户需求)
3
+ *
4
+ * `agent/turn-stopping`(serial)时:取该 turn 最后 assistant 文本 → 敏感词表检测 →
5
+ * 命中 → `agent.steer(buildRebuke(hits))` 打回重生成(turn 不关闭,模型同轮重答)。
6
+ * 连续命中达 REBUKE_MAX_ROUNDS → 放弃打回(防死循环),输出保留 + 审计日志。
7
+ *
8
+ * 作用范围(v1.26.3 用户拍板):**仅外部面**——skiff/ACP/问答页等对外输出会话
9
+ * (session id `skiff-`/`acp-`/`rebuild-` 前缀;v1.22.4 rebuild 新建会话同面)。
10
+ * **本地维护会话(普通 dsh 会话)不检测**——维护会话必然提及机制词
11
+ * (dsh-serenity-hooks/session_rebuild/mech-registry),打回会瘫痪自身工作。
12
+ */
13
+ import type { Context } from 'cordis';
14
+ /** 外部面会话判定(v1.26.3 用户拍板:仅外部面检测,本地维护会话豁免):
15
+ * skiff-(F4 问答)/ acp-(F4c 程序化)/ rebuild-(v1.22.4 重建会话)前缀 */
16
+ export declare function isExternalFaceSession(sessionId: string | undefined): boolean;
17
+ /**
18
+ * 注册输出守卫(index.ts apply 调用):
19
+ * turn-stopping 时检测最终输出,命中敏感词 → steer 打回重生成(官方机制,零改 DSH)。
20
+ */
21
+ export declare function registerOutputGuardHook(ctx: Context): void;