@shgroup/dsh-serenity-hooks 1.32.0 → 1.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -11
- package/dsh.plugin.json +5 -5
- package/lib/acp-core.d.ts +2 -22
- package/lib/acp-http.d.ts +8 -0
- package/lib/api.d.ts +12 -4
- package/lib/autopilot-chain.d.ts +76 -0
- package/lib/autopilot-core-DCRkiWEe.js +229 -0
- package/lib/autopilot-core.d.ts +132 -0
- package/lib/autopilot-ops.d.ts +48 -0
- package/lib/autopilot-trajectory-D9Znxo75.js +782 -0
- package/lib/autopilot-trajectory.d.ts +79 -83
- package/lib/{ccc-DAsSHsub.js → ccc-NlLr_sxy.js} +18 -2
- package/lib/ccc-roots-Bd_SjEs7.js +152 -0
- package/lib/ccc-roots.d.ts +105 -0
- package/lib/ccc.d.ts +23 -6
- package/lib/client.js +30 -10
- package/lib/clock-runtime.d.ts +197 -0
- package/lib/config-ops.d.ts +9 -14
- package/lib/constants.d.ts +0 -2
- package/lib/container-status.d.ts +183 -0
- package/lib/diag-ops.d.ts +76 -0
- package/lib/face-host.d.ts +110 -0
- package/lib/fs-ops.d.ts +3 -2
- package/lib/gateway-auth.d.ts +2 -5
- package/lib/gateway.d.ts +0 -34
- package/lib/git-ops.d.ts +3 -2
- package/lib/handyman-ops.d.ts +3 -2
- package/lib/handyman-preset-inherit.d.ts +2 -1
- package/lib/host/access.d.ts +8 -7
- package/lib/host/contract.d.ts +17 -6
- package/lib/host/type-contract.d.ts +1 -2
- package/lib/im-bridge.d.ts +6 -5
- package/lib/index.d.ts +1 -1
- package/lib/index.js +11053 -8305
- package/lib/invariant.d.ts +5 -16
- package/lib/invariant.js +8 -4
- package/lib/json.d.ts +1 -1
- package/lib/kit-ops.d.ts +11 -31
- package/lib/localstore-ops.d.ts +3 -17
- package/lib/msm-ops.d.ts +34 -52
- package/lib/opencode-provider.d.ts +4 -5
- package/lib/output-guard-seam.d.ts +1 -4
- package/lib/output-guard.d.ts +12 -3
- package/lib/ports.d.ts +59 -0
- package/lib/rebuild.d.ts +5 -4
- package/lib/seams/bootstrap.d.ts +4 -3
- package/lib/seams/compact.d.ts +2 -1
- package/lib/seams/context.d.ts +2 -4
- package/lib/seams/env.d.ts +2 -1
- package/lib/seams/guards.d.ts +22 -34
- package/lib/seams/keeper.d.ts +4 -4
- package/lib/seams/system-prompt.d.ts +1 -5
- package/lib/session-cleanup.d.ts +3 -2
- package/lib/{settings-section-Bm-xG-NR.js → settings-section-DTYZjwUs.js} +70 -15
- package/lib/settings-section.d.ts +14 -35
- package/lib/skiff-core.d.ts +5 -10
- package/lib/skiff-debug.d.ts +15 -21
- package/lib/skiff-registry-FTjoWQTQ.js +25 -0
- package/lib/skiff-registry.d.ts +2 -1
- package/lib/{skiff-role-BYvNnwv1.js → skiff-role-CEHL5cek.js} +1 -1
- package/lib/skiff-role.d.ts +2 -2
- package/lib/skills/opencode-scan.d.ts +3 -2
- package/lib/skills-discovery.d.ts +15 -2
- package/lib/status.d.ts +2 -1
- package/lib/tools/acc-diag.d.ts +22 -0
- package/lib/tools/cce.d.ts +1 -2
- package/lib/tools/container-admin.d.ts +7 -3
- package/lib/tools/eap.d.ts +2 -3
- package/lib/tools/handyman.d.ts +0 -29
- package/lib/tools/msm.d.ts +0 -4
- package/lib/tools/neat.d.ts +1 -2
- package/lib/tools/praxis.d.ts +0 -1
- package/lib/tools/skiff-admin.d.ts +2 -2
- package/lib/tools/{session.d.ts → trajectory.d.ts} +25 -17
- package/lib/totp.d.ts +0 -4
- package/lib/trajectory-assistant.d.ts +2 -1
- package/lib/trajectory-bound-Cax1p9ut.js +190 -0
- package/lib/{session-bound.d.ts → trajectory-bound.d.ts} +5 -6
- package/lib/trajectory-ops-mrXK0H0I.js +410 -0
- package/lib/{session-ops.d.ts → trajectory-ops.d.ts} +27 -36
- package/lib/trajectory-skills.d.ts +71 -0
- package/lib/wake-registry-CYxIb484.js +257 -0
- package/lib/wake-registry.d.ts +3 -11
- package/lib/wake-scheduler.d.ts +23 -20
- package/lib/web-fetch-provider.d.ts +0 -21
- package/lib/{weixin-api-PjEhmjlZ.js → weixin-api-CtFYm53S.js} +3 -9
- package/lib/weixin-api.d.ts +6 -37
- package/lib/weixin-bridge.d.ts +5 -24
- package/lib/weixin-hook.d.ts +6 -12
- package/lib/weixin-output-guard.d.ts +2 -1
- package/lib/{weixin-route-wWk4AIwV.js → weixin-route-B2ajFypI.js} +4 -5
- package/lib/weixin-route.d.ts +0 -2
- package/lib/weixin-send-api.d.ts +15 -6
- package/package.json +3 -5
- package/experiments/autopilot-trajectory/SKILL.md +0 -115
- package/experiments/autopilot-trajectory/scripts/autopilot-trajectory.ts +0 -522
- package/lib/session-bound-NHozeLFc.js +0 -822
- package/lib/skiff-debug-K2k1JnGj.js +0 -2867
- package/lib/tools/autopilot-trajectory.d.ts +0 -25
- package/lib/{session-cleanup-CMT4mHWt.js → session-cleanup-B6IHZgww.js} +1 -1
package/lib/client.js
CHANGED
|
@@ -3844,7 +3844,7 @@ Instruction-following style:
|
|
|
3844
3844
|
* (用户:配置处需能获取 key 和地址——管理员复制分享给使用者)。
|
|
3845
3845
|
*
|
|
3846
3846
|
* 数据通道(plugin 全局):
|
|
3847
|
-
* - GET /serenity/cccs 候选容器(node half
|
|
3847
|
+
* - GET /serenity/cccs 候选容器(node half listCccs)
|
|
3848
3848
|
* - GET /serenity/public-ask key + 地址(x-serenity-ui 头)
|
|
3849
3849
|
* - PUT /serenity/config publicAsk.allowed 白名单保存(accounts-api saveConfig)
|
|
3850
3850
|
*/
|
|
@@ -4118,7 +4118,7 @@ Instruction-following style:
|
|
|
4118
4118
|
* WeixinBridgeEditor.tsx — 「微信桥」配置区块(F4c-3,v1.27.0 实验性)
|
|
4119
4119
|
*
|
|
4120
4120
|
* **CCC 级配置**(S142 用户拍板:dsh 一个进程含多个 CCC,每个 CCC 独立对接微信桥):
|
|
4121
|
-
* - 顶部 **CCC 选择器**(数据源 /serenity/cccs——
|
|
4121
|
+
* - 顶部 **CCC 选择器**(数据源 /serenity/cccs——listCccs 复用)——显式选择配置目标,
|
|
4122
4122
|
* 不隐式依赖"当前活跃会话"(WebUI 顶层全局,微信桥是配置写入必须显式)
|
|
4123
4123
|
* - 选中 CCC 后:总开关 / 账号列表(扫码绑定)/ 路由表(user → role)
|
|
4124
4124
|
* - 扫码绑定:POST login-start → qrcode-generator 生成二维码 SVG(复用 v1.24.6 TOTP 同款机制)
|
|
@@ -4788,13 +4788,15 @@ Instruction-following style:
|
|
|
4788
4788
|
const acpOn = value?.acpEnabled ?? false;
|
|
4789
4789
|
const acpPort = value?.acpHttpPort ?? 3100;
|
|
4790
4790
|
const publicAskOn = value?.publicAskEnabled ?? false;
|
|
4791
|
-
const autopilotOn = value?.autopilotEnabled ?? false;
|
|
4791
|
+
const autopilotOn = value?.autopilotWakeEnabled ?? value?.autopilotEnabled ?? false;
|
|
4792
|
+
const wakeSchedOn = value?.wakeSchedulerEnabled ?? true;
|
|
4792
4793
|
const [openGateway, setOpenGateway] = (0, react.useState)(false);
|
|
4793
4794
|
const [openRebuild, setOpenRebuild] = (0, react.useState)(false);
|
|
4794
4795
|
const [openSkiff, setOpenSkiff] = (0, react.useState)(false);
|
|
4795
4796
|
const [openAcp, setOpenAcp] = (0, react.useState)(false);
|
|
4796
4797
|
const [openPublicAsk, setOpenPublicAsk] = (0, react.useState)(false);
|
|
4797
4798
|
const [openAutopilot, setOpenAutopilot] = (0, react.useState)(false);
|
|
4799
|
+
const [openWakeSched, setOpenWakeSched] = (0, react.useState)(false);
|
|
4798
4800
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4799
4801
|
className: "ss-section",
|
|
4800
4802
|
children: [
|
|
@@ -4832,7 +4834,7 @@ Instruction-following style:
|
|
|
4832
4834
|
title: "上下文",
|
|
4833
4835
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
|
|
4834
4836
|
title: "超限重建",
|
|
4835
|
-
desc: "上下文接近上限时提示调用
|
|
4837
|
+
desc: "上下文接近上限时提示调用 container_trajectory rebuild 清空重建",
|
|
4836
4838
|
expandable: true,
|
|
4837
4839
|
open: openRebuild,
|
|
4838
4840
|
onToggle: setOpenRebuild,
|
|
@@ -4845,7 +4847,7 @@ Instruction-following style:
|
|
|
4845
4847
|
className: "ss-detailStack",
|
|
4846
4848
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4847
4849
|
className: "ss-detailIntro",
|
|
4848
|
-
children: "上下文超限自动重建(
|
|
4850
|
+
children: "上下文超限自动重建(container_trajectory rebuild,v1.33 起 logbook 并入 trajectory):\n· 机制:agent 上下文占用达到阈值时,由 LLM 主动调用重建\n· 语义:完全丢弃当前 dsh 会话 + 自动新建 + 注入「继续原 SESSION 的工作」\n· 效果:SESSION.md 原位不动,认知轨迹延续,上下文归零\n· 关闭后:上下文超限时不再提示,可能导致会话卡顿或丢失"
|
|
4849
4851
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
|
|
4850
4852
|
title: "重建阈值",
|
|
4851
4853
|
desc: "上下文占用达到该 K 数值时提示(单位 K token,默认 400)",
|
|
@@ -4941,22 +4943,40 @@ Instruction-following style:
|
|
|
4941
4943
|
})
|
|
4942
4944
|
}) }),
|
|
4943
4945
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
|
|
4944
|
-
title: "
|
|
4945
|
-
desc: "
|
|
4946
|
+
title: "周期自唤醒(autopilot)",
|
|
4947
|
+
desc: "定时唤起 autopilot 轨迹(全局开关,默认关——只在指定电脑开启)",
|
|
4946
4948
|
expandable: true,
|
|
4947
4949
|
open: openAutopilot,
|
|
4948
4950
|
onToggle: setOpenAutopilot,
|
|
4949
4951
|
control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
4950
4952
|
checked: autopilotOn,
|
|
4951
|
-
onChange: (on) => toggle("
|
|
4953
|
+
onChange: (on) => toggle("autopilotWakeEnabled", on)
|
|
4952
4954
|
}),
|
|
4953
4955
|
detail: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4954
4956
|
className: "ss-detailStack",
|
|
4955
4957
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4956
4958
|
className: "ss-detailIntro",
|
|
4957
|
-
children: "Autopilot Trajectory
|
|
4959
|
+
children: "周期自唤醒全局闸(v1.34 更名收窄,原 Autopilot Trajectory 全局总开关):\n· 作用:控制本机(本 dsh 实例)是否运行**周期**自动巡航唤起\n· 语义边界:**只管周期自唤醒** —— 关掉它不影响一次性唤醒(wake-later,见下一行)\n· 默认关:未开启即使 CCC 配置 enabled=true 也不启动定时器\n· 定位:多台电脑装 dsp 时,只在指定电脑开启(其余默认关)\n· 双重门控:本开关 AND CCC 级 enabled 都满足才运行\n· CCC 级配置(interval/session/偏见脚本/焦点)不受影响"
|
|
4958
4960
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutopilotTrajectoryStatusBlock, { autopilotOn })]
|
|
4959
4961
|
})
|
|
4962
|
+
}) }),
|
|
4963
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
|
|
4964
|
+
title: "唤醒调度器(wake-later)",
|
|
4965
|
+
desc: "投递已登记的“未来时刻 + 一条 message”(全局开关,默认开)",
|
|
4966
|
+
expandable: true,
|
|
4967
|
+
open: openWakeSched,
|
|
4968
|
+
onToggle: setOpenWakeSched,
|
|
4969
|
+
control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
4970
|
+
checked: wakeSchedOn,
|
|
4971
|
+
onChange: (on) => toggle("wakeSchedulerEnabled", on)
|
|
4972
|
+
}),
|
|
4973
|
+
detail: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4974
|
+
className: "ss-detailStack",
|
|
4975
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4976
|
+
className: "ss-detailIntro",
|
|
4977
|
+
children: "唤醒调度器全局闸(v1.34 新增独立开关):\n· 作用:把 CCC 唤醒注册表(AGENT_SESSIONS/wake-registry.json)里到点的条目投递给目标轨迹\n· 条目来源:`container_trajectory wake-later`(对自己或别的 trajectory 预约未来时刻 + 一条 message)\n· 默认开:条目全部由人类/agent 显式登记,无环境自主性 ⇒ 不需要“默认关”的实验保护\n· 与上一行**互不连带**:关掉周期自唤醒不会关掉本调度器(用户 2026-09-15 裁决)\n· 精度:5min tick;补跑窗口 2h(超窗判 missed 留痕);fire-and-forget 无回执"
|
|
4978
|
+
})
|
|
4979
|
+
})
|
|
4960
4980
|
}) })
|
|
4961
4981
|
]
|
|
4962
4982
|
}),
|
|
@@ -5261,7 +5281,7 @@ Instruction-following style:
|
|
|
5261
5281
|
className: "ss-rowCard",
|
|
5262
5282
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefList, { items: [{
|
|
5263
5283
|
term: "唤醒注册表",
|
|
5264
|
-
value: wakes.length === 0 ? "无条目(agent 用
|
|
5284
|
+
value: wakes.length === 0 ? "无条目(agent 用 container_trajectory wake-later 登记:未来时刻 + 一条 message)" : `${wakes.filter((w) => w.state === "pending").length} 条在办 / 共 ${wakes.length} 条`
|
|
5265
5285
|
}, ...wakes.slice(0, 5).map((w) => ({
|
|
5266
5286
|
term: w.state === "pending" ? "· 待唤醒" : `· ${w.state}`,
|
|
5267
5287
|
value: `${new Date(w.at).toLocaleString()} → ${w.target}${w.lastResult ? `(${w.lastResult})` : ""}`
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* clock-runtime.ts — **时钟运行时工厂**(S142 §38 复审候选 C6b,路径 **P2**)
|
|
3
|
+
*
|
|
4
|
+
* 本仓有**两条各自独立运行**的 5min 时钟:
|
|
5
|
+
* · 唤醒调度器(`wake-scheduler.ts`,一次性唤醒,D58)
|
|
6
|
+
* · autopilot 时钟(`autopilot-trajectory.ts`,周期自唤醒,D59)
|
|
7
|
+
* 二者的**业务判据完全不同**(谁来扫 / 扫什么 / 投递给谁 / 按什么周期),但**引擎骨架逐字同形**
|
|
8
|
+
* ——进程态 + 快照 + 复位 + `startTimer` + tick 外壳 + 事件接线 + disposer + `timer.unref()`。
|
|
9
|
+
* 本条把**引擎**抽到本工厂,**各钟仍各持自己的定时器与自己的串行链**。
|
|
10
|
+
*
|
|
11
|
+
* ───────────────────────────────────────────────────────────────────────────
|
|
12
|
+
* 🔴 硬约束一:**两条时钟绝不可共用"排队执行"的链**(这是 P2 与 P1 的分界判据)
|
|
13
|
+
*
|
|
14
|
+
* autopilot 每轮要跑该 CCC 的**偏见脚本**(`fetchBiasContent`,超时 60s),可能阻塞数十秒;
|
|
15
|
+
* 若与唤醒调度器共用一条串行链,会把另一条一起**卡住**(一次性唤醒被无关的偏见脚本拖住)。
|
|
16
|
+
* ⇒ 本工厂把 `chain` 作为**每实例私有状态**:`createClock()` 调用一次 = 一条独立的串行域。
|
|
17
|
+
* 实例之间**零共享**(无模块级单例、无共享 Promise、无共享 map)。
|
|
18
|
+
* ⚠️ 若日后有人把 `chain` 提到模块级"省一次分配",**两条时钟的隔离即刻失效**——不许。
|
|
19
|
+
*
|
|
20
|
+
* 🔴 硬约束二:**武装门只判全局闸**(`gate()`),**不判"本次有无目标"**
|
|
21
|
+
*
|
|
22
|
+
* 2026-09-14 F 段实测缺陷:旧实现把"有 live CCC"当**武装前置条件**,而宿主刚重启时 live 会话
|
|
23
|
+
* 必为空,且**"恢复旧会话"不触发 `session/created`**(只有新建会)⇒ 启动瞬间判定落空 =
|
|
24
|
+
* **时钟永久不武装**(实测 6.6h 零 tick)。⇒ 现在「**全局闸开即武装**」,"有无目标"降级为
|
|
25
|
+
* tick 内的廉价判定。**武装与"本次有无目标"是两件事,本工厂不得把二者耦合。**
|
|
26
|
+
*
|
|
27
|
+
* 🔴 硬约束三:**两条闸必须继续分开传**(v1.34 S-1 解耦)
|
|
28
|
+
*
|
|
29
|
+
* 唤醒调度器 `wakeSchedulerEnabled`(**缺省开**)|autopilot `autopilotWakeEnabled`
|
|
30
|
+
* (**缺省关**)——取值方向相反。工厂取 `gate` **回调**(每次现读),**不做**任何合并或缓存。
|
|
31
|
+
*
|
|
32
|
+
* ───────────────────────────────────────────────────────────────────────────
|
|
33
|
+
* 两条时钟**逐项语义差**(`ClockOptions` 的每个可配项都对应下表一行,不是随意的灵活性):
|
|
34
|
+
*
|
|
35
|
+
* | 项 | 唤醒调度器 | autopilot | 工厂表达 |
|
|
36
|
+
* |----|-----------|-----------|---------|
|
|
37
|
+
* | `chain` | 有(全局串行) | 有(全局串行) | **总是私有**(硬约束一) |
|
|
38
|
+
* | `lastTickLog` | 有(逐行摘要) | **无** | `logFrom` 不给 = 不记 |
|
|
39
|
+
* | `ticks` 记账 | 工厂在 body **完成后**记 | **本钟**在同步段记 | `bodyCountsTick` + `begin` |
|
|
40
|
+
* | body 返回类型 | `string[]`(人读摘要) | `void` | 泛型 `T` |
|
|
41
|
+
* | 启动日志 | 固定串 | 含启用 CCC 计数 | `startLog: () => string` |
|
|
42
|
+
* | body 异常兜底 | 留痕 + `console.warn` | 同 | 工厂统一(**吞异常不改语义**) |
|
|
43
|
+
*
|
|
44
|
+
* ───────────────────────────────────────────────────────────────────────────
|
|
45
|
+
* **本工厂是"加法式"重构**(P2 的性质):不新增任何判定逻辑,只把同形骨架收成一份代码;
|
|
46
|
+
* 两个模块仍各自导出 `wakeSchedulerState()` / `autopilotClockState()` 与各自的
|
|
47
|
+
* `__reset…ForTest()`,**对外可观测面(字段名与语义)零变化**——`acc-diag` ①b 段、
|
|
48
|
+
* `container-status.ts:containerClocks()` 与面板都在读它们(见该文件 :225–250 的设计红线)。
|
|
49
|
+
*
|
|
50
|
+
* 为什么**不**取 P1(真合并成一个 `setInterval` + 两条策略)——2026-09-15 所有者裁决:
|
|
51
|
+
* P1 只多省 ~20 行,却要把 `armed` 拆成"宿主 + 每策略"两层、并强行分开串行域,
|
|
52
|
+
* 即**动两条正在跑的时钟的骨架**;**不值当**(裁决原文见 SESSION §12.8②)。
|
|
53
|
+
*/
|
|
54
|
+
/**
|
|
55
|
+
* 时钟**进程态**(诊断用,模块级 = 进程级,正是诊断对象)。
|
|
56
|
+
*
|
|
57
|
+
* 字段名与语义是**对外契约**(`acc-diag` / `containerClocks` 在读),不得因本重构改名或改义。
|
|
58
|
+
* `lastTickLog` 只有唤醒调度器消费(autopilot 无对应字段),故这里是**可选**。
|
|
59
|
+
*/
|
|
60
|
+
export interface ClockRuntime {
|
|
61
|
+
/** 定时器是否在跑(start 成功 → true;disposer 拆卸 → false) */
|
|
62
|
+
armed: boolean;
|
|
63
|
+
/** 武装时刻(ms;null = 从未) */
|
|
64
|
+
armedAt: number | null;
|
|
65
|
+
/** 上次真正执行 tick 的时刻(ms;null = 从未——被闸跳过的 tick 不刷新它) */
|
|
66
|
+
lastTickAt: number | null;
|
|
67
|
+
/** 真正执行过多少次 tick */
|
|
68
|
+
ticks: number;
|
|
69
|
+
/** 上次被跳过 / 异常的原因(null = 上次正常执行) */
|
|
70
|
+
lastSkipReason: string | null;
|
|
71
|
+
/** 上次 tick 的逐行摘要(**可选**:只有给了 `render` 的钟才有此字段) */
|
|
72
|
+
lastTickLog?: string[];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 一个钟实例(= 一个定时器 + 一条**私有**串行链 + 一份进程态)
|
|
76
|
+
*/
|
|
77
|
+
export interface Clock {
|
|
78
|
+
/** 幂等启动:已武装则原样返回;`gate()` 为假则不武装(零资源占用);成功则立即跑一次 tick */
|
|
79
|
+
start: () => void;
|
|
80
|
+
/** 拆卸:清定时器 + 复位 armed/armedAt + 跑 `onDispose` */
|
|
81
|
+
dispose: () => void;
|
|
82
|
+
/** 进程态快照(只读;`enabled` = `gate()` 的**当前**值,便于区分"未武装"与"闸关") */
|
|
83
|
+
snapshot: () => ClockRuntime & {
|
|
84
|
+
enabled: boolean;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* body 内部留痕"本次跳过原因"(`null` = 本次正常执行)。
|
|
88
|
+
*
|
|
89
|
+
* 为什么需要它:**"没有可扫目标"是 body 才知道的事**(autopilot 的 `无 live+enabled CCC…`
|
|
90
|
+
* 与唤醒调度器的 `无已知 CCC 可扫…` 判定都在 body 内),但该字段是进程态的一部分 ⇒
|
|
91
|
+
* 由 body 经本方法写回,工厂不再替 body 猜。**只有 body 能调**(引擎自身走 `gateOffReason`)。
|
|
92
|
+
*/
|
|
93
|
+
noteSkipReason: (reason: string | null) => void;
|
|
94
|
+
/**
|
|
95
|
+
* 把一段**在飞工作**排到**本钟私有**串行链的尾部(不经 tick 包装:不记账、不写 lastTickLog、不吞异常)。
|
|
96
|
+
*
|
|
97
|
+
* 何时用它:body 在一次 tick 里为**多个目标**各派一件活儿,这些活儿要**依次**跑(防模型并发挤兑),
|
|
98
|
+
* 而它们在**本次 tick 返回之后**仍在飞(autopilot 即此:同 tick 多 CCC 依次唤起)。
|
|
99
|
+
* 若 body 自己另起一条链,就是**第二条串行域**——本钟的"串行"会有两处真相。
|
|
100
|
+
*
|
|
101
|
+
* ⚠️ **风险由调用方担**:本方法**不** try/catch(与 `body` 相反)。调用方必须自带兜底
|
|
102
|
+
* (autopilot 的每件活儿都有自己的 try/catch/finally)——否则一个异常会**毒化整条链**,
|
|
103
|
+
* 该钟此后的 `enqueue` 与 tick 都会静默不执行。
|
|
104
|
+
*/
|
|
105
|
+
enqueue: (work: () => Promise<void> | void) => void;
|
|
106
|
+
/**
|
|
107
|
+
* 记一次 tick(`ticks += 1` + `lastTickAt = now`)。
|
|
108
|
+
*
|
|
109
|
+
* **只有 `bodyCountsTick: true` 时才由 body 调用**(autopilot);缺省时工厂在 body 完成后
|
|
110
|
+
* 自动调用,body 不该再调(会重复计数)。见 {@link ClockOptions.bodyCountsTick}。
|
|
111
|
+
*/
|
|
112
|
+
countTick: () => void;
|
|
113
|
+
/** 测试用:复位进程态(避免用例间串味) */
|
|
114
|
+
reset: () => void;
|
|
115
|
+
}
|
|
116
|
+
/** `createClock` 的可配项(每一项都对应文件头语义差表的一行;**没有"顺手加"的开关**) */
|
|
117
|
+
export interface ClockOptions<T> {
|
|
118
|
+
/** 本钟的**唯一**诊断名(进异常日志,用于人读定位) */
|
|
119
|
+
label: string;
|
|
120
|
+
/**
|
|
121
|
+
* 宿主上下文(**只读它的 `on`**)。装配时赋值(`register*` 的第一件事),
|
|
122
|
+
* `body` / `startLog` / 热启动接线都从**这一个格子**读——避免"三处各存一份 ctx"。
|
|
123
|
+
* 装配前为 `undefined`:那时也没有定时器(tick 无从发起),故不会被读到。
|
|
124
|
+
*
|
|
125
|
+
* 类型取**结构最小面**(不是 `cordis.Context`):本工厂不该依赖宿主的强类型事件表
|
|
126
|
+
* (`on` 在 cordis 上是泛型重载,比 `(name: string, fn) => void` **更窄** ⇒ 直接传 Context
|
|
127
|
+
* 反而不兼容)。装配点传 `ctx` 即可。
|
|
128
|
+
*/
|
|
129
|
+
ctx: unknown;
|
|
130
|
+
/** 热启动触发面事件名(回调恒为 `() => start()`——两条钟的触发面同形,不开放自定义回调) */
|
|
131
|
+
events?: string[];
|
|
132
|
+
/** 全局闸:**每次现读**(不缓存——面板改开关后要能立刻反映)+ 武装门**只**判它 */
|
|
133
|
+
gate: () => boolean;
|
|
134
|
+
/** body 被**闸**跳过时写入 `lastSkipReason` 的文案(文案归各钟,工厂不编) */
|
|
135
|
+
gateOffReason: string;
|
|
136
|
+
/**
|
|
137
|
+
* **同步前置阶段**(在 body 被调用**之前**、同一个 tick 内同步执行)。
|
|
138
|
+
*
|
|
139
|
+
* 存在的理由不是"方便",而是**既有行为要求**(实测被两条回归钉守住):
|
|
140
|
+
* autopilot 的 `ticks` / `lastSkipReason` 是在 tick **同步段**里定下来的——
|
|
141
|
+
* · 枚举到 live+enabled CCC ⇒ 立刻 `countTick()`(早于任何 `await`);
|
|
142
|
+
* · 枚举为空 ⇒ 立刻 `noteSkipReason('无 live+enabled CCC…')` 并**不计 tick**。
|
|
143
|
+
* 若把这些挪进 body(async),观测面会在"启动即 tick"的那一瞬间读到**旧值**
|
|
144
|
+
* (`ticks` 停留在 0、`lastSkipReason` 仍是上一拍的)——诊断面说了假话。
|
|
145
|
+
*
|
|
146
|
+
* 唤醒调度器**不用**本项(它的 `ticks` 在 body 完成后由工厂记,见 `bodyCountsTick`)。
|
|
147
|
+
*/
|
|
148
|
+
begin?: () => void;
|
|
149
|
+
/**
|
|
150
|
+
* 一次 tick 的**业务体**(引擎不关心里面做什么;返回值交给 `logFrom`)
|
|
151
|
+
*/
|
|
152
|
+
body: () => Promise<T> | T;
|
|
153
|
+
/**
|
|
154
|
+
* `ticks` / `lastTickAt` 的**记账时机**(两条钟真的不同,见文件头语义差表):
|
|
155
|
+
*
|
|
156
|
+
* `false`(缺省)= **工厂在 body 完成后**记账 —— 唤醒调度器语义:
|
|
157
|
+
* "tick 数 = 真执行**并完成**过的 tick"。但 `body` 提前返回("无 CCC 可扫")时也照样记账
|
|
158
|
+
* (wake 的既有行为就是如此:`ticks` ≠ "真投递过的 tick")。
|
|
159
|
+
*
|
|
160
|
+
* `true` = **body 自己调 {@link Clock.countTick} 记账** —— autopilot 语义:
|
|
161
|
+
* `ticks`/`lastTickAt` 在**枚举到 live+enabled CCC 之后、任何 await 之前**同步记账;
|
|
162
|
+
* "无 CCC 可扫" 的那一拍**不计**(既有行为:`ticks` 停在 0 直到真有 CCC 可唤起)。
|
|
163
|
+
* 若把它交给工厂"body 前同步记账",就会**在闸之后无条件 +1**——那会把
|
|
164
|
+
* "无 CCC 可扫时不计数"这条既有语义改掉(实测:`autopilot-trajectory.test.ts`
|
|
165
|
+
* 的『启动时无 live 会话』与『配置关闭』两条回归钉立刻变红)。
|
|
166
|
+
*
|
|
167
|
+
* ⚠️ 故本项**不是**"记账早晚"的风格开关,而是"**谁**知道该不该记"的归属划分:
|
|
168
|
+
* 知道"有没有目标"的只有 body ⇒ 由 body 决定何时记账。
|
|
169
|
+
*/
|
|
170
|
+
bodyCountsTick?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* 本钟是否记 tick 日志(`lastTickLog`)。
|
|
173
|
+
* 给了 `logFrom` **才**有此字段与逐行打印——autopilot **没有** `lastTickLog`(现状稿 §2.4),
|
|
174
|
+
* 故它不传本项(情形分布不同:autopilot 的结果进 `wakeHistory` 审计 ring,不走 tick 日志)。
|
|
175
|
+
*/
|
|
176
|
+
logFrom?: {
|
|
177
|
+
prefix: string;
|
|
178
|
+
lines: (value: T) => string[];
|
|
179
|
+
};
|
|
180
|
+
/** 启动成功的日志行(autopilot 需在里面报启用 CCC 计数,故做成回调) */
|
|
181
|
+
startLog: () => string;
|
|
182
|
+
/** 启动时是否立刻跑一次 tick(两条钟皆为 true;留成显式项以免日后被默默改掉)@default true */
|
|
183
|
+
immediate?: boolean;
|
|
184
|
+
/** 拆卸回调(工厂负责清定时器与复位进程态;本项是**额外**清理,如 autopilot 的 `runningByRoot`) */
|
|
185
|
+
onDispose?: () => void;
|
|
186
|
+
/** 测试复位回调(如 autopilot 顺带 `runningByRoot.clear()`) */
|
|
187
|
+
onReset?: () => void;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 建一条时钟(**每钟各调一次**——本工厂**不是**单例,调用次数 = 时钟条数)。
|
|
191
|
+
*
|
|
192
|
+
* 顺序忠实于既有实现:`start()` 先武装并立即跑一次 tick → 再挂事件。
|
|
193
|
+
* 拆卸由调用方经 `registerDisposer(ctx, label, clock.dispose)` 落到宿主的 `ctx.effect`。
|
|
194
|
+
* @param opts 见 {@link ClockOptions}(每项对应一条既有的语义差)
|
|
195
|
+
* @returns 该钟的 `{start, dispose, snapshot, reset}`
|
|
196
|
+
*/
|
|
197
|
+
export declare function createClock<T>(opts: ClockOptions<T>): Clock;
|
package/lib/config-ops.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
/** 高级设定节名(localstore.json 顶层) */
|
|
18
18
|
export declare const ADVANCED_SECTION = "serenityAdvanced";
|
|
19
19
|
/** 一个外部访问账号(密码只存 hash,永不落 wire) */
|
|
20
|
-
|
|
20
|
+
interface GatewayAccount {
|
|
21
21
|
/** 稳定键(UI CRUD 定位) */
|
|
22
22
|
id: string;
|
|
23
23
|
/** 登录用户名 */
|
|
@@ -28,7 +28,7 @@ export interface GatewayAccount {
|
|
|
28
28
|
totpSecret?: string;
|
|
29
29
|
}
|
|
30
30
|
/** F1 双端口网关配置 */
|
|
31
|
-
|
|
31
|
+
interface GatewaySettings {
|
|
32
32
|
enabled: boolean;
|
|
33
33
|
host: string;
|
|
34
34
|
port: number;
|
|
@@ -45,7 +45,7 @@ export interface GatewaySettings {
|
|
|
45
45
|
/** 彩蛋功能:persona 模式(v1.23.1,S142 用户需求)
|
|
46
46
|
* 配置后替换 ACC 系统提示词中"输出约束/指令遵循约束"部分(EAP 块 + MSM 原则段);
|
|
47
47
|
* 未配置(mode 空)→ 完全默认行为,零影响。 */
|
|
48
|
-
|
|
48
|
+
interface PersonaSettings {
|
|
49
49
|
/** 彩蛋模式名(显示用;空 = 彩蛋关闭) */
|
|
50
50
|
mode: string;
|
|
51
51
|
/** 用户替换文本(替代 EAP 块 + MSM 原则段的原文) */
|
|
@@ -54,7 +54,7 @@ export interface PersonaSettings {
|
|
|
54
54
|
/** F4d 建议问答页(v1.26.1,S142 用户:按认知容器暴露问答页供他人验证):
|
|
55
55
|
* 与 ACP HTTP 共用 3100 端口;key 首次启用自动生成(plugin 全局文件固定),无 key 不工作。
|
|
56
56
|
* v1.26.2:按容器权限控制——allowed 白名单(容器名);空 = 全部开放(向后兼容 v1.26.1 全局开放) */
|
|
57
|
-
|
|
57
|
+
interface PublicAskSettings {
|
|
58
58
|
/** 访问 key(空 = 未生成;首次启用时 ensurePublicAskKey 自动生成随机 key 写回固定) */
|
|
59
59
|
key: string;
|
|
60
60
|
/** 开放容器白名单(CCC 目录名,如 home-serenity);空数组 = 全部容器开放 */
|
|
@@ -67,7 +67,7 @@ export interface PublicAskSettings {
|
|
|
67
67
|
* 旧高级 rebuild 字段是死双胞胎(/serenity/config PUT 回显但运行时从不读它)——
|
|
68
68
|
* 删除防误导(用户在高级面板改了却无效)。历史残留字段被 mergeWithDefaults 忽略(幂等安全)。
|
|
69
69
|
*/
|
|
70
|
-
|
|
70
|
+
interface AdvancedSettings {
|
|
71
71
|
gateway: GatewaySettings;
|
|
72
72
|
persona: PersonaSettings;
|
|
73
73
|
publicAsk: PublicAskSettings;
|
|
@@ -78,7 +78,7 @@ export interface AdvancedSettings {
|
|
|
78
78
|
* 主动发送入口配置(v1.30.9,S142 用户需求"微信桥支持被调用发消息")。
|
|
79
79
|
* 只监听 loopback(公网网关 3081 不可达),故不做密钥;`enabled:false` 或 `port:0` 关闭。
|
|
80
80
|
*/
|
|
81
|
-
|
|
81
|
+
interface WeixinApiSettings {
|
|
82
82
|
enabled: boolean;
|
|
83
83
|
port: number;
|
|
84
84
|
}
|
|
@@ -113,12 +113,6 @@ export declare function verifyPublicAskKey(provided: string | undefined): boolea
|
|
|
113
113
|
* @returns 新 key(面板展示给管理员,重新分享给使用者)
|
|
114
114
|
*/
|
|
115
115
|
export declare function rotatePublicAskKey(): string;
|
|
116
|
-
/** 失败锁定阈值(连续失败次数) */
|
|
117
|
-
export declare const PUBLIC_ASK_FAIL_THRESHOLD = 5;
|
|
118
|
-
/** 首次锁定基础时长(指数退避底数) */
|
|
119
|
-
export declare const PUBLIC_ASK_LOCK_BASE_MS: number;
|
|
120
|
-
/** 锁定上限 */
|
|
121
|
-
export declare const PUBLIC_ASK_LOCK_MAX_MS: number;
|
|
122
116
|
/** 重置 IP 失败状态(测试/管理员解封) */
|
|
123
117
|
export declare function resetPublicAskIpFail(ip: string): void;
|
|
124
118
|
/** IP 当前是否锁定(到期自动解锁) */
|
|
@@ -133,7 +127,7 @@ export declare function recordPublicAskFail(ip: string): number;
|
|
|
133
127
|
*/
|
|
134
128
|
export declare function migrateLegacyLocalstore(root: string | null): boolean;
|
|
135
129
|
/** 账号的 wire 形态:只有 id/user + hasPassword/hasTotp(无 hash/secret) */
|
|
136
|
-
|
|
130
|
+
interface GatewayAccountWire {
|
|
137
131
|
id: string;
|
|
138
132
|
user: string;
|
|
139
133
|
hasPassword: boolean;
|
|
@@ -141,7 +135,7 @@ export interface GatewayAccountWire {
|
|
|
141
135
|
hasTotp: boolean;
|
|
142
136
|
}
|
|
143
137
|
/** 设定 wire 形态(GET /serenity/config 返回;gateway 去 hash) */
|
|
144
|
-
|
|
138
|
+
interface AdvancedSettingsWire {
|
|
145
139
|
gateway: {
|
|
146
140
|
enabled: boolean;
|
|
147
141
|
host: string;
|
|
@@ -179,3 +173,4 @@ export declare function projectKnownWorkspaces(workspaces: Array<{
|
|
|
179
173
|
* 新账号(id 不在现有)必须带非空 pass,否则抛错(无法生成 hash)。
|
|
180
174
|
*/
|
|
181
175
|
export declare function applyWirePatch(wire: Partial<AdvancedSettingsWire>): AdvancedSettings;
|
|
176
|
+
export {};
|
package/lib/constants.d.ts
CHANGED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* container-status.ts — 容器状态模型的**取数层唯一出口**(C5「观察面归一」,S142 2026-09-15)
|
|
3
|
+
*
|
|
4
|
+
* 为什么存在(R↓):ACC 有多个观察面(`dashboard health` / `acc-diag` / WebUI 面板 /
|
|
5
|
+
* 系统提示词注入),它们读的是同一批宿主事实。此前"这些事实怎么取"写在**每个消费方各自的
|
|
6
|
+
* 函数体里**——同一份状态有几个读者就有几处取数代码。本模块把取数收成一个出口,消费方只留
|
|
7
|
+
* **渲染**(薄渲染)。
|
|
8
|
+
*
|
|
9
|
+
* 本模块**只做取数 + 形状**(设计红线):
|
|
10
|
+
* - **文案/格式归渲染点**。本模块给判据与事实(`rooted: true` / `configPath: '.opencode/serenity.json'`),
|
|
11
|
+
* **不给**人读句子("✓ .serenity marker found")。同一份事实在 `dashboard health` 与 `acc-diag`
|
|
12
|
+
* 里的措辞不同,正是因为它属渲染。
|
|
13
|
+
* - **不合并两条 registry 判据**(见 {@link checkRegistryHealth} / {@link checkRegistryQuality} 的对照注释)。
|
|
14
|
+
* - **时钟读进程内模块级快照**({@link containerClocks})——**不重算**:调度器的武装态/计数只存在于
|
|
15
|
+
* 其模块级运行时对象里,任何"重新推导"得到的都是与真实调度器不一致的假值。
|
|
16
|
+
*
|
|
17
|
+
* 依赖分层(为什么本模块"重"而 `kit-ops` / `status` 保持"轻"):
|
|
18
|
+
* {@link containerClocks} 必须读 `wake-scheduler` / `autopilot-trajectory` 的进程内快照,而这两个
|
|
19
|
+
* 模块带 **@deepseek-ai 值依赖**(`dsh-llm` 的 `createUserMessage`)。故本模块**只能**被本就重型或
|
|
20
|
+
* 异步的消费方使用:`diag-ops`(静态 import)、`api.ts` / `kit-ops`(`await import(...)`,与
|
|
21
|
+
* `api.ts` 既有的"保持静态链纯净"约定一致)。**轻链模块不得静态 import 本模块**。
|
|
22
|
+
*
|
|
23
|
+
* 已有的单一真相源继续指向原处(**不复制**):
|
|
24
|
+
* L0 根解析 `ccc.ts findSerenityRoot`|L1/L2 根与枚举 `ccc-roots.ts`|宿主契约 `host/contract.ts`
|
|
25
|
+
* |CCC 配置 `ccc.ts loadSerenityConfig`|注册表 `msm-ops.ts`|时钟 `wake-scheduler.ts` /
|
|
26
|
+
* `autopilot-trajectory.ts`|唤醒注册表 `wake-registry.ts`。
|
|
27
|
+
*/
|
|
28
|
+
import { type HostContractReport } from './host/contract.js';
|
|
29
|
+
import { checkRegistryQuality, type RegistryQualityReport } from './msm-ops.js';
|
|
30
|
+
import { type WakeEntry } from './wake-registry.js';
|
|
31
|
+
import { autopilotClockState, getAutopilotStatus } from './autopilot-trajectory.js';
|
|
32
|
+
import { wakeSchedulerState } from './wake-scheduler.js';
|
|
33
|
+
import type { JsonValue } from './json.js';
|
|
34
|
+
export interface ContainerIdentity {
|
|
35
|
+
/** CCC 根(调用方给定;null = 不在任何 CCC 内) */
|
|
36
|
+
root: string | null;
|
|
37
|
+
/** CCC 名(`.serenity` 首行;无根或读不到 → null) */
|
|
38
|
+
ccc: string | null;
|
|
39
|
+
/** ACC 插件版本 */
|
|
40
|
+
accVersion: string;
|
|
41
|
+
/** 已安装 DSH CLI 版本(读不到 → null) */
|
|
42
|
+
dshVersion: string | null;
|
|
43
|
+
/** node 版本(`process.version`) */
|
|
44
|
+
nodeVersion: string;
|
|
45
|
+
}
|
|
46
|
+
/** 身份/版本段取数(版本自省是磁盘/常量事实,与 CCC 内容无关) */
|
|
47
|
+
export declare function containerIdentity(root: string | null): ContainerIdentity;
|
|
48
|
+
export interface ContainerPrinciples {
|
|
49
|
+
/** P1:`.serenity` 存在且非空 */
|
|
50
|
+
rooted: boolean;
|
|
51
|
+
/** P2:位于某个 git 仓库内 */
|
|
52
|
+
gitManaged: boolean;
|
|
53
|
+
/** P2 的证据(git 根绝对路径;null = 不是 git 仓库) */
|
|
54
|
+
gitRoot: string | null;
|
|
55
|
+
/** P3:命中的 DSH/opencode 配置路径(相对 CCC 根);null = 全部未命中 */
|
|
56
|
+
configPath: string | null;
|
|
57
|
+
/** 三项全过(health 的 healthy/degraded 判据之一) */
|
|
58
|
+
allPass: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 三原则取数。
|
|
62
|
+
* ⚠️ 与 `ccc.ts` 的 P1/P2 原语是**同一实现**(`existsSync(.serenity)` / `findGitRoot`),
|
|
63
|
+
* 本函数只把它们组装成"一次检查"的形状;判定语义未变(P1 要求文件非空、P2 要求 `.git` 存在)。
|
|
64
|
+
*/
|
|
65
|
+
export declare function containerPrinciples(root: string | null): ContainerPrinciples;
|
|
66
|
+
export interface RegistryStructureReport {
|
|
67
|
+
/** 聚合档路径(相对 CCC 根);无 cccName → null */
|
|
68
|
+
path: string | null;
|
|
69
|
+
ok: boolean;
|
|
70
|
+
/** 该注册表文件是否存在(不存在 = 未注册任何 MSM,非坏) */
|
|
71
|
+
present: boolean;
|
|
72
|
+
issues: string[];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* **判据 A —— 注册表「结构完整性」**(原 `kit-ops.ts checkRegistryHealth`,C5 迁入本模块)。
|
|
76
|
+
*
|
|
77
|
+
* 回答的问题:**这张表坏没坏**——文件能不能被安全解析(JSON 合法 / 顶层形状 / entry 字段类型 /
|
|
78
|
+
* name 全局唯一 / path 在根内且脚本存在)。
|
|
79
|
+
*
|
|
80
|
+
* 🔴 **为什么不与 {@link checkRegistryQuality} 合并**(设计红线,取证见
|
|
81
|
+
* `acc-c4c5-current-state.md` §⑥ 与 §⑤ 观察面 4/5):两条判据的**主语不同**——
|
|
82
|
+
* - A 的主语是**文件**:"解析它会不会炸"。它**绝不**因为某个 entry 的脚本缺测试文件而报 issue;
|
|
83
|
+
* - B 的主语是**条目契约**:"这条 entry 符合 MSM 的质量规约吗"(DC-M1~M4)。
|
|
84
|
+
*
|
|
85
|
+
* 因此**同一份注册表上两条判据可以给出相反结论**(例:结构完全合法,但没有一条 entry 达标;
|
|
86
|
+
* 或条目全达标,而表里有同名重复 entry)。合并成一个 `ok` 会把"表坏了(要 git restore)"与
|
|
87
|
+
* "表没坏但条目欠火候(去写测试)"两种**修复动作完全不同**的故障压成同一个信号。
|
|
88
|
+
*
|
|
89
|
+
* health 必须**不因坏表抛错**(注册表坏 → `loadMsmEntries` 抛 → `container_admin`/`output-guard`
|
|
90
|
+
* 全崩且自锁无法自救),故本判据独立解析,不走 `loadMsmEntries`。
|
|
91
|
+
*/
|
|
92
|
+
export declare function checkRegistryHealth(root: string): RegistryStructureReport;
|
|
93
|
+
/**
|
|
94
|
+
* **判据 B —— 注册表「质量契约」**(DC-M1~M4;实现在 `msm-ops.ts checkRegistryQuality`,
|
|
95
|
+
* 执行面 `container_admin msm check` 亦走它)。
|
|
96
|
+
*
|
|
97
|
+
* 与判据 A 的关系见 {@link checkRegistryHealth} 的对照注释——**两条判据、两个名字、两份结论**。
|
|
98
|
+
* 本模块只做具名转出(取数出口唯一),不复制其判据实现。
|
|
99
|
+
*/
|
|
100
|
+
export { checkRegistryQuality, type RegistryQualityReport };
|
|
101
|
+
/**
|
|
102
|
+
* 进程内时钟快照类型。
|
|
103
|
+
* ⚠️ 两个时钟的形状由**各自模块**定义(`WakeSchedulerRuntime` / `AutopilotClockRuntime`,
|
|
104
|
+
* 两者都未导出且 `autopilot` 少一个 `lastTickLog` 字段)——故此处取**联合**:它们对外暴露的
|
|
105
|
+
* 诊断字段(armed / enabled / ticks / lastTickAt / armedAt / lastSkipReason)语义同规格,
|
|
106
|
+
* 但类型上不是同一个。**不为了合并类型去改那两个模块的导出面**。
|
|
107
|
+
*/
|
|
108
|
+
export type ClockSnapshot = ReturnType<typeof wakeSchedulerState> | ReturnType<typeof autopilotClockState>;
|
|
109
|
+
export interface ContainerClocks {
|
|
110
|
+
/** 唤醒调度器(一次性唤醒,5min tick)——**模块级快照**,不重算 */
|
|
111
|
+
wake: ClockSnapshot;
|
|
112
|
+
/** autopilot 时钟(周期自唤醒 tick)——**模块级快照**,不重算 */
|
|
113
|
+
autopilot: ClockSnapshot;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 两条时钟的进程内状态("为什么这轮没被唤起"的第一手判据)。
|
|
117
|
+
*
|
|
118
|
+
* 🔴 **只读快照,不重算**(设计红线):`armed`/`ticks`/`lastTickAt`/`lastSkipReason` 只存在于
|
|
119
|
+
* 调度器自己的模块级运行时对象里(`wake-scheduler.ts schedulerRuntime` /
|
|
120
|
+
* `autopilot-trajectory.ts` 同规格对象)。任何"从配置或文件重新推导"得到的值都会与真实
|
|
121
|
+
* 调度器的状态不一致——那比没有可观测量更糟(会给出假的"一切正常")。
|
|
122
|
+
*/
|
|
123
|
+
export declare function containerClocks(): ContainerClocks;
|
|
124
|
+
export interface ContainerWakes {
|
|
125
|
+
/** 注册表文件读取问题(读不到时非空——不得静默) */
|
|
126
|
+
error: string | null;
|
|
127
|
+
/** 全量条目(原样,按 `at` 升序;**投影由各渲染点决定**——面板要 `message`,诊断不要) */
|
|
128
|
+
entries: WakeEntry[];
|
|
129
|
+
/** 在办(`state === 'pending'`)条目数 */
|
|
130
|
+
pending: number;
|
|
131
|
+
}
|
|
132
|
+
/** 唤醒注册表取数(文件 IO:每个渲染点自己决定是否要看它) */
|
|
133
|
+
export declare function containerWakes(root: string): ContainerWakes;
|
|
134
|
+
/**
|
|
135
|
+
* autopilot 目标状态取数(读 CCC 配置 + 目标 SESSION.md 的 mtime 探测)。
|
|
136
|
+
* 与 WebUI 面板 / `acc-diag` 一致——两边渲染的是**同一份** `getAutopilotStatus()` 结果。
|
|
137
|
+
* 类型从该函数的返回类型派生(`AutopilotTrajectoryStatus` 未从 `autopilot-trajectory.ts` 导出,
|
|
138
|
+
* 此处不为了转出而改动那个模块的导出面)。
|
|
139
|
+
*/
|
|
140
|
+
export type AutopilotStatusSnapshot = ReturnType<typeof getAutopilotStatus>;
|
|
141
|
+
/** @returns CCC 根缺失(null)→ null */
|
|
142
|
+
export declare function containerAutopilot(root: string | null): AutopilotStatusSnapshot | null;
|
|
143
|
+
export interface ContainerStatus {
|
|
144
|
+
identity: ContainerIdentity;
|
|
145
|
+
principles: ContainerPrinciples;
|
|
146
|
+
/**
|
|
147
|
+
* 注册表**两条判据**(各自命名、不许合并——见 `checkRegistryHealth` / `checkRegistryQuality`)。
|
|
148
|
+
*/
|
|
149
|
+
registry: {
|
|
150
|
+
/** 判据 A 结构完整性(**总是**算:health 的核心,成本 = 一次 JSON 解析) */
|
|
151
|
+
structure: RegistryStructureReport;
|
|
152
|
+
/**
|
|
153
|
+
* 判据 B 质量契约 DC-M1~M4(**默认不算**:要枚举 `skills/` 下脚本并逐个读源码查 main() 守卫,
|
|
154
|
+
* 是唯一有实打实成本的段)——`withRegistryQuality: true` 才取。
|
|
155
|
+
*/
|
|
156
|
+
quality: RegistryQualityReport | null;
|
|
157
|
+
};
|
|
158
|
+
/** CCC 配置(`ccc.ts loadSerenityConfig`;无根 → null) */
|
|
159
|
+
config: JsonValue | null;
|
|
160
|
+
/** 宿主契约(进程内唯一来源,见 `host/contract.ts hostContractReport`) */
|
|
161
|
+
hostContract: HostContractReport | null;
|
|
162
|
+
}
|
|
163
|
+
export interface ContainerStatusOptions {
|
|
164
|
+
/** CCC 根;null = 不在任何 CCC 内(仍返回降级形状,不抛错) */
|
|
165
|
+
root?: string | null;
|
|
166
|
+
/** CCC 配置候选路径(缺省 `DEFAULT_SERENITY_CONFIG_PATHS`) */
|
|
167
|
+
configPaths?: string[];
|
|
168
|
+
/** 是否取判据 B(注册表质量契约);缺省 false */
|
|
169
|
+
withRegistryQuality?: boolean;
|
|
170
|
+
/**
|
|
171
|
+
* 宿主契约**兜底**捕获用的上下文:快照已存在(apply 时已捕获)时此参数被忽略,
|
|
172
|
+
* 进程内**不会**发生第二次探针。缺省 undefined = 只要快照(拿不到就是 null)。
|
|
173
|
+
*/
|
|
174
|
+
hostCtx?: unknown;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 核心段组装(`dashboard health` 的取数:身份 + 三原则 + 注册表两判据 + 配置 + 宿主契约)。
|
|
178
|
+
*
|
|
179
|
+
* 时间轴三段(时钟/唤醒注册表/autopilot 目标)**不在本组装内**:它们是各自独立消费方的需要
|
|
180
|
+
* (`acc-diag` / `/serenity/trajectory`),硬塞进来会让只想看三原则的调用方付无谓的 IO。
|
|
181
|
+
* 需要时按名字调 {@link containerClocks} / {@link containerWakes} / {@link containerAutopilot}。
|
|
182
|
+
*/
|
|
183
|
+
export declare function containerStatus(opts?: ContainerStatusOptions): ContainerStatus;
|