@shgroup/dsh-serenity-hooks 1.45.0 → 1.45.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/dsh.plugin.json +1 -1
- package/lib/clock-runtime.d.ts +5 -3
- package/lib/index.js +18 -7
- package/lib/tools/trajectory.d.ts +3 -0
- package/lib/{trajectory-bound-BzdzsDPI.js → trajectory-bound-BPWKkzJC.js} +31 -47
- package/lib/trajectory-bound.d.ts +5 -0
- package/lib/{wake-scheduler-fVe71jkg.js → wake-scheduler-DF-YWcX5.js} +6 -4
- package/lib/wake-scheduler.d.ts +3 -2
- package/package.json +1 -1
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.45.
|
|
3
|
+
"version": "1.45.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——11 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/im-bridge/acc-diag;后两个按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 轨迹日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.5-rc.2(deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
package/lib/clock-runtime.d.ts
CHANGED
|
@@ -24,10 +24,12 @@
|
|
|
24
24
|
* **时钟永久不武装**(实测 6.6h 零 tick)。⇒ 现在「**全局闸开即武装**」,"有无目标"降级为
|
|
25
25
|
* tick 内的廉价判定。**武装与"本次有无目标"是两件事,本工厂不得把二者耦合。**
|
|
26
26
|
*
|
|
27
|
-
* 🔴
|
|
27
|
+
* 🔴 硬约束三:**闸是可选能力,工厂不得替调用方假设"必须有闸"**(v1.34 S-1 解耦 → 2026-09-21 收窄)
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* 现只余 **autopilot `autopilotWakeEnabled`**(**缺省关**)一条;**唤醒调度器已无闸**
|
|
30
|
+
* (原 `wakeSchedulerEnabled` 于 2026-09-21 所有者令砍掉 ⇒ 调用方**不传** `gate`
|
|
31
|
+
* = 恒武装、永不因闸跳过、`enabled` 恒 `true`)。工厂取 `gate` **回调**(每次现读),
|
|
32
|
+
* **不做**任何合并或缓存;**缺省无闸是合法形态,不是漏配**。
|
|
31
33
|
*
|
|
32
34
|
* ───────────────────────────────────────────────────────────────────────────
|
|
33
35
|
* 两条时钟**逐项语义差**(`ClockOptions` 的每个可配项都对应下表一行,不是随意的灵活性):
|
package/lib/index.js
CHANGED
|
@@ -2,13 +2,13 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
|
2
2
|
import { a as hostSettings, c as hostWebServer, i as hostSessions, n as hostInjected, o as hostSubagents, r as hostService, s as hostWeb, t as hostAgents } from "./access-fiehjxV6.js";
|
|
3
3
|
import { a as findSerenityRoot, c as matchBlacklist, d as readCccName$1, f as readExclusiveTools, g as resolveInside, i as findGitRoot, l as pathInside, m as readTrajectorySkills, n as SAFE_MODE_MARKER, o as isSafeModeOn, p as readHandymanConfig, r as classifyPath, s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS, u as readBlacklist } from "./ccc-DG4Oc7I1.js";
|
|
4
4
|
import { i as cccRootForExec, n as agentCwdFor, o as listCccs, r as cccRootForCwd, t as NO_CCC_FROM_AGENT_CWD } from "./ccc-roots-FxWXuZPw.js";
|
|
5
|
-
import { C as
|
|
5
|
+
import { C as useSession, S as summarize, T as localFileStamp, _ as resolveSessionByTitle, a as resolveSessionTrajectoryLabel, b as setActiveSessionInfo, c as TRAJECTORY_ACTIONS, d as extractSessionMdPathFromText, f as findSession, g as readActiveSessionMd, h as parseSessionContextFromEvents, i as readLastBound, l as clearActiveSessionInfo, m as listSessions, o as setBindingStore, p as getActiveSessionInfo, r as pruneMissingBindings, s as DEFAULT_SESSION_SCOPE, t as appendBound, u as createSession, v as sessionEvents$1, w as isoLocal, x as showSession, y as sessionsRoot } from "./trajectory-bound-BPWKkzJC.js";
|
|
6
6
|
import { a as readWeixinCredential, c as weixinInboundDir, d as LOCALSTORE_SCOPES, f as checkLocalstoreGitCompliance, g as runLocalStore, h as readStore, i as matchWeixinRoute, l as weixinSessionIdFor, m as readGitTrack, n as extractWeixinText, o as readWeixinSettings, p as localstorePath, r as hasVoiceItem, s as sanitizeFileName$1, t as extractWeixinMedia } from "./weixin-route-CWMRa36W.js";
|
|
7
7
|
import { a as unregisterSkiffSession$1, i as skiffSessionSnapshot$1, n as skiffRoleFor$1, o as ACC_VERSION, r as skiffSessionInfo$1, t as registerSkiffSession$1 } from "./skiff-registry-BjIX_KD1.js";
|
|
8
8
|
import { a as readSkiffRoles, c as roleMsmWhitelist, d as systemPromptSource, f as trajectorySubset, i as isSkiffSessionId, l as roleToolWhitelist, n as buildSkiffBasePrompt, o as resolveRoleSystemPrompt, r as createRolePromptReader, s as resolveSkiffKind } from "./skiff-role-KqQA6pkr.js";
|
|
9
9
|
import { a as FACE_PORTS, c as MECHANISM_PORTS, i as ACP_HTTP_PORT, l as SKIFF_DEBUG_PORT, n as registerSettingsSection, o as GATEWAY_PORT, s as MAIN_WEB_PORT, t as readSimpleSettings, u as WEIXIN_SEND_PORT } from "./settings-section-CIuyoSOX.js";
|
|
10
10
|
import { r as sessionsRootDir, t as hasSessionLogById } from "./session-cleanup-BtkSmry8.js";
|
|
11
|
-
import { a as registerDisposer, c as addWake, i as registerCroTurnTracking, l as listWakes, n as sendToTrajectory, o as buildCroSnapshot, r as wakeSchedulerState, s as WAKE_CATCH_UP_MS, t as registerWakeScheduler } from "./wake-scheduler-
|
|
11
|
+
import { a as registerDisposer, c as addWake, i as registerCroTurnTracking, l as listWakes, n as sendToTrajectory, o as buildCroSnapshot, r as wakeSchedulerState, s as WAKE_CATCH_UP_MS, t as registerWakeScheduler } from "./wake-scheduler-DF-YWcX5.js";
|
|
12
12
|
import { a as markdownToPlainText, c as sendTyping, i as getUpdates, l as sniffImageExt, n as downloadMedia, o as sendFileMessage, r as getConfig, s as sendTextMessage, t as TypingStatus } from "./weixin-api-CtFYm53S.js";
|
|
13
13
|
import z from "@deepseek-ai/schemastery";
|
|
14
14
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
@@ -4497,6 +4497,9 @@ ${renderCroSampleSnapshot()}
|
|
|
4497
4497
|
* ⇒ 族名取共享词干 **`send-`**、轴取 **`-now` / `-later`**(同构)。**硬切无别名**(D46/D61 先例);
|
|
4498
4498
|
* 机制层词汇(`wake-registry.json` / `w-*` id / `WakeEntry` / 调度器名 / 配置键 `wakeSchedulerEnabled`)
|
|
4499
4499
|
* **一律不动** —— 接受"机制叫 wake、动作叫 send-later"的**分层命名**(二者本是两层)。
|
|
4500
|
+
* 🔴 **2026-09-21 补注(不改写历史,只标失效时点)**:上句里那个**配置键 `wakeSchedulerEnabled`
|
|
4501
|
+
* 已随后续所有者令被砍**(唤醒调度器无闸、恒武装)⇒ 该词从"机制层词汇"里**自然减员**;
|
|
4502
|
+
* 现行总闸键是 CRO 阶段的 **`croEnabled`**。
|
|
4500
4503
|
*
|
|
4501
4504
|
* 与旧面(logbook 11 动作 + trajectory 12 动作)的对应(用户逐条裁决,R↓):
|
|
4502
4505
|
* · `summary` → 并入 `list`(全库统计随清单一起给)
|
|
@@ -4520,10 +4523,21 @@ ${renderCroSampleSnapshot()}
|
|
|
4520
4523
|
function agentScope$1(exec) {
|
|
4521
4524
|
return exec.agent?.session?.id ?? "default";
|
|
4522
4525
|
}
|
|
4523
|
-
/**
|
|
4526
|
+
/**
|
|
4527
|
+
* 当前 dsh 会话对象(绑定的读写都要用它);无 `append` → null。
|
|
4528
|
+
*
|
|
4529
|
+
* 🔴 **2026-09-21 修 F3(原实现是 F1 的上游成因)**:本函数原先把会话**削成只带 `append` 的包装对象**。
|
|
4530
|
+
* 但 `appendBound` / `readLastBound` 定位"这是哪条会话、哪个 CCC 根"靠的是
|
|
4531
|
+
* `session.header.id` 与 `session.header.cwd`(见 `trajectory-bound.ts` 的 `sessionHeader`)——
|
|
4532
|
+
* **包装对象没有 header** ⇒ ① `appendBound` **在读 id 处直接 `return false`**(静默 no-op)
|
|
4533
|
+
* ⇒ **`use` 这条路从来不写当前载体的绑定**(实证吻合:S142 §7.4 记录"当前载体的绑定**直到
|
|
4534
|
+
* 17:05 那次 rebuild 才写入**")② `readLastBound` 同样恒 null ⇒ G1 切换守卫只能靠内存回退。
|
|
4535
|
+
* ⇒ 改为**返回原会话对象**(只增字段、不削字段):只用 `append` 的调用点行为不变,
|
|
4536
|
+
* 而绑定读写从此拿得到 header。
|
|
4537
|
+
*/
|
|
4524
4538
|
function agentDshSession(exec) {
|
|
4525
4539
|
const s = exec.agent?.session;
|
|
4526
|
-
return s && typeof s.append === "function" ?
|
|
4540
|
+
return s && typeof s.append === "function" ? s : null;
|
|
4527
4541
|
}
|
|
4528
4542
|
/**
|
|
4529
4543
|
* 当前绑定的权威 dirName(优先持久化 bound——防内存被误 use 污染;无 bound 回退内存 active)。
|
|
@@ -4759,9 +4773,6 @@ function createTrajectoryTool(ctx) {
|
|
|
4759
4773
|
};
|
|
4760
4774
|
if (advisory) out.advisory = advisory;
|
|
4761
4775
|
if (dsh) {
|
|
4762
|
-
const selfId = String(dsh.header?.id ?? "");
|
|
4763
|
-
const superseded = supersedeOtherBindings(root, info?.dirName ?? targetDirName, selfId === "" ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([selfId]));
|
|
4764
|
-
if (superseded.length > 0) out.supersededBindings = superseded;
|
|
4765
4776
|
const pruned = pruneMissingBindings(root, (id) => !hasSessionLogById(sessionsRootDir(), id));
|
|
4766
4777
|
if (pruned.length > 0) out.prunedBindings = pruned;
|
|
4767
4778
|
}
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
* ⇒ 族名取共享词干 **`send-`**、轴取 **`-now` / `-later`**(同构)。**硬切无别名**(D46/D61 先例);
|
|
16
16
|
* 机制层词汇(`wake-registry.json` / `w-*` id / `WakeEntry` / 调度器名 / 配置键 `wakeSchedulerEnabled`)
|
|
17
17
|
* **一律不动** —— 接受"机制叫 wake、动作叫 send-later"的**分层命名**(二者本是两层)。
|
|
18
|
+
* 🔴 **2026-09-21 补注(不改写历史,只标失效时点)**:上句里那个**配置键 `wakeSchedulerEnabled`
|
|
19
|
+
* 已随后续所有者令被砍**(唤醒调度器无闸、恒武装)⇒ 该词从"机制层词汇"里**自然减员**;
|
|
20
|
+
* 现行总闸键是 CRO 阶段的 **`croEnabled`**。
|
|
18
21
|
*
|
|
19
22
|
* 与旧面(logbook 11 动作 + trajectory 12 动作)的对应(用户逐条裁决,R↓):
|
|
20
23
|
* · `summary` → 并入 `list`(全库统计随清单一起给)
|
|
@@ -801,66 +801,30 @@ function listBoundSessionIds(root, dirName) {
|
|
|
801
801
|
return hits.sort((a, b) => b.at - a.at).map((h) => h.id);
|
|
802
802
|
}
|
|
803
803
|
/**
|
|
804
|
-
*
|
|
804
|
+
* 🔴 **「只留一条」的唯一判据**(2026-09-21 收进单一实现;此前同一判据在域侧/文件侧各写一遍)。
|
|
805
805
|
*
|
|
806
|
-
*
|
|
807
|
-
*
|
|
806
|
+
* 判据:同 `dirName` ∧ **不是** `keepIds` 里的 ∧ **尚未** `supersededAt`。
|
|
807
|
+
* 域侧与文件侧**同判据**——历史缺陷(2026-09-19)正是"只在一侧收集 ⇒ 返回值恒空",
|
|
808
|
+
* 见 {@link supersedeOtherBindings} 的注释。
|
|
808
809
|
*
|
|
809
|
-
*
|
|
810
|
-
*
|
|
811
|
-
* 而 `acquireWakeAgent` 是"遍历全部绑定 id、任一条 live 就用它"——**两条 live 都能被选中**。
|
|
812
|
-
*
|
|
813
|
-
* @param root CCC 根
|
|
814
|
-
* @param dirName 目标 trajectory 目录名
|
|
815
|
-
* @param keepIds 保留(不标记)的会话 id 集合——通常是"当前正在 use 的这条"
|
|
816
|
-
* @returns **实际被标记**的会话 id(升序稳定;供调用方如实报告,未标记任何一条 → `[]`)
|
|
810
|
+
* @param fileSessions 旧文件表的记录集
|
|
811
|
+
* @param domainEntries 域侧条目(域不可用时传 `undefined` = 不参与判定)
|
|
817
812
|
*/
|
|
818
|
-
function
|
|
819
|
-
const path = join(root, BINDINGS_REL_PATH);
|
|
820
|
-
const file = readBindingsFile(path);
|
|
821
|
-
const at = Date.now();
|
|
822
|
-
/**
|
|
823
|
-
* 需要退休的会话 id 集合。
|
|
824
|
-
*
|
|
825
|
-
* 🔴 必须取**域 ∪ 文件的并集**(实测缺陷,2026-09-19):
|
|
826
|
-
* 首版实现只在**文件循环**里 `marked.push(id)`,于是"记录只在域里"时
|
|
827
|
-
* 返回值恒为 `[]` —— 而调用方(`tools/trajectory.ts` 的 `use`)**靠这个返回值**决定
|
|
828
|
-
* 是否回报 `supersededBindings`,并且早先用 `marked.length === 0` 短路**跳过了写盘**。
|
|
829
|
-
* ⇒ 症状是"D69 只留一条**静默不生效**"(记录没被标记,返回也看不出异常)。
|
|
830
|
-
* 由 `tests/trajectory-bound.test.ts` 的 D69 域路径用例抓到。
|
|
831
|
-
*/
|
|
813
|
+
function collectSupersedeTargets(dirName, keepIds, fileSessions, domainEntries) {
|
|
832
814
|
const toMark = /* @__PURE__ */ new Set();
|
|
833
|
-
if (
|
|
815
|
+
if (domainEntries) for (const [id, raw] of domainEntries) {
|
|
834
816
|
const rec = fromDomainRecord(raw);
|
|
835
817
|
if (rec.dirName !== dirName) continue;
|
|
836
818
|
if (keepIds.has(id) || rec.supersededAt !== void 0) continue;
|
|
837
819
|
toMark.add(id);
|
|
838
820
|
}
|
|
839
|
-
for (const [id, raw] of Object.entries(
|
|
821
|
+
for (const [id, raw] of Object.entries(fileSessions)) {
|
|
840
822
|
const rec = asBoundRecord(raw);
|
|
841
823
|
if (!rec || rec.dirName !== dirName) continue;
|
|
842
824
|
if (keepIds.has(id) || rec.supersededAt !== void 0) continue;
|
|
843
825
|
toMark.add(id);
|
|
844
826
|
}
|
|
845
|
-
|
|
846
|
-
if (domainStore?.available) for (const id of toMark) {
|
|
847
|
-
const raw = domainStore.get(id);
|
|
848
|
-
if (!raw) continue;
|
|
849
|
-
domainStore.put(id, toDomainRecord({
|
|
850
|
-
...fromDomainRecord(raw),
|
|
851
|
-
supersededAt: at
|
|
852
|
-
})).catch(() => {});
|
|
853
|
-
}
|
|
854
|
-
for (const id of toMark) {
|
|
855
|
-
const rec = asBoundRecord(file.sessions[id]);
|
|
856
|
-
if (!rec) continue;
|
|
857
|
-
rec.supersededAt = at;
|
|
858
|
-
file.sessions[id] = rec;
|
|
859
|
-
}
|
|
860
|
-
try {
|
|
861
|
-
writeBindingsFile(path, file);
|
|
862
|
-
} catch {}
|
|
863
|
-
return [...toMark].sort();
|
|
827
|
+
return toMark;
|
|
864
828
|
}
|
|
865
829
|
/**
|
|
866
830
|
* **(c) 绑定一致性兜底**(S142 §0y,所有者 2026-09-18 裁「c 也算个兜底」):
|
|
@@ -906,6 +870,11 @@ function pruneMissingBindings(root, isMissing) {
|
|
|
906
870
|
* 写入绑定(latest-wins 覆盖该会话记录)。
|
|
907
871
|
*
|
|
908
872
|
* 绑定持久化尽力而为:无法定位 CCC 根 / 无会话 id / 写盘失败 → 返回 false,不阻断主流程。
|
|
873
|
+
*
|
|
874
|
+
* 🔴 **同时是「只留一条」(D69)的唯一写入口**(2026-09-21 起):每写一条,就在**同一次 RMW** 里
|
|
875
|
+
* 把同轨迹的**其它**条标 `supersededAt`(自己除外)。⇒ 任何调用路径(`create`/`activate`/`switch`/
|
|
876
|
+
* `rebuild`/`reconcile`)**都自动满足"只留一条"**,调用方**不需要**(也**不应当**)自己算 selfId。
|
|
877
|
+
*
|
|
909
878
|
* @param session 目标 dsh 会话(需 `header.id` + `header.cwd` 可定位 CCC 根)
|
|
910
879
|
* @param action 绑定动作
|
|
911
880
|
* @param rec 绑定记录(dirName + mdPath 必填;sessionId 可选展示码)
|
|
@@ -927,11 +896,26 @@ function appendBound(session, action, rec) {
|
|
|
927
896
|
try {
|
|
928
897
|
const file = readBindingsFile(path);
|
|
929
898
|
file.sessions[id] = record;
|
|
899
|
+
const targets = collectSupersedeTargets(rec.dirName, /* @__PURE__ */ new Set([id]), file.sessions, domainStore?.available ? domainStore.entries() : void 0);
|
|
900
|
+
for (const other of targets) {
|
|
901
|
+
const otherRec = asBoundRecord(file.sessions[other]);
|
|
902
|
+
if (!otherRec) continue;
|
|
903
|
+
otherRec.supersededAt = record.at;
|
|
904
|
+
file.sessions[other] = otherRec;
|
|
905
|
+
}
|
|
930
906
|
writeBindingsFile(path, file);
|
|
907
|
+
if (domainStore?.available) for (const other of targets) {
|
|
908
|
+
const raw = domainStore.get(other);
|
|
909
|
+
if (!raw) continue;
|
|
910
|
+
domainStore.put(other, toDomainRecord({
|
|
911
|
+
...fromDomainRecord(raw),
|
|
912
|
+
supersededAt: record.at
|
|
913
|
+
})).catch(() => {});
|
|
914
|
+
}
|
|
931
915
|
return true;
|
|
932
916
|
} catch {
|
|
933
917
|
return domainStore?.available === true;
|
|
934
918
|
}
|
|
935
919
|
}
|
|
936
920
|
//#endregion
|
|
937
|
-
export {
|
|
921
|
+
export { useSession as C, localIdStamp as D, localHuman as E, summarize as S, localFileStamp as T, resolveSessionByTitle as _, resolveSessionTrajectoryLabel as a, setActiveSessionInfo as b, TRAJECTORY_ACTIONS as c, extractSessionMdPathFromText as d, findSession as f, readActiveSessionMd as g, parseSessionContextFromEvents as h, readLastBound as i, clearActiveSessionInfo as l, listSessions as m, listBoundSessionIds as n, setBindingStore as o, getActiveSessionInfo as p, pruneMissingBindings as r, DEFAULT_SESSION_SCOPE as s, appendBound as t, createSession as u, sessionEvents as v, isoLocal as w, showSession as x, sessionsRoot as y };
|
|
@@ -169,6 +169,11 @@ export declare function pruneMissingBindings(root: string, isMissing: (sessionId
|
|
|
169
169
|
* 写入绑定(latest-wins 覆盖该会话记录)。
|
|
170
170
|
*
|
|
171
171
|
* 绑定持久化尽力而为:无法定位 CCC 根 / 无会话 id / 写盘失败 → 返回 false,不阻断主流程。
|
|
172
|
+
*
|
|
173
|
+
* 🔴 **同时是「只留一条」(D69)的唯一写入口**(2026-09-21 起):每写一条,就在**同一次 RMW** 里
|
|
174
|
+
* 把同轨迹的**其它**条标 `supersededAt`(自己除外)。⇒ 任何调用路径(`create`/`activate`/`switch`/
|
|
175
|
+
* `rebuild`/`reconcile`)**都自动满足"只留一条"**,调用方**不需要**(也**不应当**)自己算 selfId。
|
|
176
|
+
*
|
|
172
177
|
* @param session 目标 dsh 会话(需 `header.id` + `header.cwd` 可定位 CCC 根)
|
|
173
178
|
* @param action 绑定动作
|
|
174
179
|
* @param rec 绑定记录(dirName + mdPath 必填;sessionId 可选展示码)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as hostService, t as hostAgents } from "./access-fiehjxV6.js";
|
|
2
2
|
import { g as resolveInside } from "./ccc-DG4Oc7I1.js";
|
|
3
3
|
import { o as listCccs } from "./ccc-roots-FxWXuZPw.js";
|
|
4
|
-
import { D as
|
|
4
|
+
import { D as localIdStamp, E as localHuman, f as findSession, n as listBoundSessionIds, w as isoLocal, y as sessionsRoot } from "./trajectory-bound-BPWKkzJC.js";
|
|
5
5
|
import { t as readSimpleSettings } from "./settings-section-CIuyoSOX.js";
|
|
6
6
|
import { basename, dirname, join } from "node:path";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -1190,10 +1190,12 @@ function appendCroWakeLog(root, dirName, input, nowMs = Date.now()) {
|
|
|
1190
1190
|
* **时钟永久不武装**(实测 6.6h 零 tick)。⇒ 现在「**全局闸开即武装**」,"有无目标"降级为
|
|
1191
1191
|
* tick 内的廉价判定。**武装与"本次有无目标"是两件事,本工厂不得把二者耦合。**
|
|
1192
1192
|
*
|
|
1193
|
-
* 🔴
|
|
1193
|
+
* 🔴 硬约束三:**闸是可选能力,工厂不得替调用方假设"必须有闸"**(v1.34 S-1 解耦 → 2026-09-21 收窄)
|
|
1194
1194
|
*
|
|
1195
|
-
*
|
|
1196
|
-
*
|
|
1195
|
+
* 现只余 **autopilot `autopilotWakeEnabled`**(**缺省关**)一条;**唤醒调度器已无闸**
|
|
1196
|
+
* (原 `wakeSchedulerEnabled` 于 2026-09-21 所有者令砍掉 ⇒ 调用方**不传** `gate`
|
|
1197
|
+
* = 恒武装、永不因闸跳过、`enabled` 恒 `true`)。工厂取 `gate` **回调**(每次现读),
|
|
1198
|
+
* **不做**任何合并或缓存;**缺省无闸是合法形态,不是漏配**。
|
|
1197
1199
|
*
|
|
1198
1200
|
* ───────────────────────────────────────────────────────────────────────────
|
|
1199
1201
|
* 两条时钟**逐项语义差**(`ClockOptions` 的每个可配项都对应下表一行,不是随意的灵活性):
|
package/lib/wake-scheduler.d.ts
CHANGED
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
* 而非"投递失败",见 `WakeDeliveryResult.notReady` —— 启动那一拍早于懒服务就绪是常态)
|
|
19
19
|
* 4. 投递:`agent.followup(...)`("Queue an ordinary follow-up turn and wake the driver")
|
|
20
20
|
*
|
|
21
|
-
* 守卫(
|
|
22
|
-
* `autopilotEnabled
|
|
21
|
+
* 守卫(2026-09-21 起**本钟无闸**):🔴 **恒武装**——原 `wakeSchedulerEnabled` 已砍,
|
|
22
|
+
* 本钟不再有「可被误关的开关」;旧配置残留该键**静默忽略**,且**不**回退 `autopilotEnabled`|
|
|
23
|
+
* CRO 阶段另有**独立**总闸 `croEnabled`(只停 CRO,**不影响**本注册表投递)|
|
|
23
24
|
* 补跑窗口 2h(超窗置 missed 留痕)|同 tick 串行|唤起后维持 live(人类可介入)。
|
|
24
25
|
*/
|
|
25
26
|
import type { Context } from 'cordis';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.45.
|
|
3
|
+
"version": "1.45.1",
|
|
4
4
|
"description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:11 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/im-bridge/acc-diag)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 工作日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.5-rc.2。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|