@shgroup/dsh-serenity-hooks 1.19.3 → 1.19.5

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-serenity-hooks",
3
- "version": "1.19.3",
3
+ "version": "1.19.5",
4
4
  "main": "lib/index.js",
5
5
  "description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/loop + 拦截缝机械约束(safe-mode/路径守卫)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。私有(dsh-external 组织)。",
6
6
  "engines": {
package/lib/index.js CHANGED
@@ -3559,9 +3559,14 @@ const DEFAULT_COMPACTION_TOOLS = [
3559
3559
  "grep",
3560
3560
  "todo_write"
3561
3561
  ];
3562
- /** 默认首轮锚定消息(用户指定:persona 设定 + we/us 人称——首轮模型以 we/us 自称,
3563
- * 对齐 anchored 实测的 "we" 轨迹特征) */
3564
- const DEFAULT_ANCHOR_MESSAGE = "You are a helpful software engineer assistant.The personal pronoun is us/we.";
3562
+ /**
3563
+ * 协议级锚定消息序列(用户确认固化,2026-08-24 S142):任何 CCC 在抽象层都是
3564
+ * 宁静号/ACC——首轮锚定话语统一,无 CCC 配置面。两轮递进:
3565
+ * ① ACC 身份 + EAP 原则 + we/us 人称 + 先锚定后行动
3566
+ * ② 协作协议 5 条 + acknowledge 要求(只回确认,不做事)
3567
+ * 文本 = 原 home-serenity CCC 配置(anchorMessages),随零配置化固化进代码。
3568
+ */
3569
+ const DEFAULT_ANCHOR_MESSAGES = ["You are the operator agent of Serenity — a cognitive container governed by the Abstract Cognitive Container (ACC) protocol.\nWe operate under the Explicit Abstraction Principle (EAP): the functional value of a thought equals its external reconstructability — every output we produce must be explicit (E↑), reconstructable (R↓), and stable (S↑).\nThe personal pronoun is us/we.\nWe anchor first, then act: the abstract layer precedes the concrete.\nPlease simply reply \"acknowledge\" — no action needed.", "Before we proceed, align on how we work:\n1. We read before we write — every decision grounds in what already exists in the container.\n2. Every output records its reasoning (R↓): decisions carry reasons and alternatives.\n3. We never jump levels — abstract layer first, then specifics.\n4. Every artifact we create is a durable cognitive anchor for the work that follows.\n5. We keep the container's state coherent (SESSION.md) as we advance.\nPlease simply reply \"acknowledge\" — no action needed."];
3565
3570
  /**
3566
3571
  * 构建一个 epoch 感知晋升跟踪器(纯逻辑,可单测)。
3567
3572
  * requiredSignals:晋升所需信号数(boundary 后累计;默认 1)。
@@ -3572,9 +3577,10 @@ const DEFAULT_ANCHOR_MESSAGE = "You are a helpful software engineer assistant.Th
3572
3577
  * 某些模型/协议(如 opencode-go-responses)的会话可能不产生标准
3573
3578
  * `assistant/message` 晋升信号 → 永不晋升 → bootstrap 阶段工具被裁空
3574
3579
  * (zeroTools 首请求 0 工具,ACC 工具不可见)。兜底:无论晋升信号是否
3575
- * 到达,观察到的模型回复轮数(assistant/message 事件计数,独立于
3576
- * promoteEvents)达到 maxRoundsFallback 即强制 promoted(开放完整工具)。
3577
- * 正常模型锚定轮数(requiredSignals)通常 ≤ 2 < 默认兜底 3,不受影响。
3580
+ * 到达,观察到的模型 step 数(`step/start` 事件计数,平台稳定事件,
3581
+ * responses/completions 都触发,独立于 promoteEvents)达到 maxRoundsFallback
3582
+ * 即强制 promoted(开放完整工具)。正常模型锚定轮数(requiredSignals
3583
+ * 通常 ≤ 2 < 默认兜底 3,不受影响。
3578
3584
  */
3579
3585
  function createEpochPromotion(promoteEvents, requiredSignals = 1, maxRoundsFallback = 3) {
3580
3586
  /** sessionId -> { boundary, signalCount, rounds }(rounds = 兜底用回复轮计数) */
@@ -3601,7 +3607,7 @@ function createEpochPromotion(promoteEvents, requiredSignals = 1, maxRoundsFallb
3601
3607
  continue;
3602
3608
  }
3603
3609
  if (promoteEvents.has(e.type) && seq > boundary) signalCount++;
3604
- if (e.type === "assistant/message" && seq > boundary) rounds++;
3610
+ if (e.type === "step/start" && seq > boundary) rounds++;
3605
3611
  }
3606
3612
  const entry = {
3607
3613
  boundary,
@@ -3663,7 +3669,7 @@ function createEpochPromotion(promoteEvents, requiredSignals = 1, maxRoundsFallb
3663
3669
  return;
3664
3670
  }
3665
3671
  if (promoteEvents.has(e.type) && seq > entry.boundary) entry.signalCount++;
3666
- if (e.type === "assistant/message" && seq > entry.boundary) entry.rounds++;
3672
+ if (e.type === "step/start" && seq > entry.boundary) entry.rounds++;
3667
3673
  state.set(sid, entry);
3668
3674
  }
3669
3675
  };
@@ -3673,41 +3679,27 @@ const PROMOTE_EVENTS = {
3673
3679
  "assistant-message": /* @__PURE__ */ new Set(["assistant/message"]),
3674
3680
  either: /* @__PURE__ */ new Set(["tool/call", "assistant/message"])
3675
3681
  };
3676
- function stringList(value, field, fallback) {
3677
- if (value === void 0) return [...fallback];
3678
- if (!Array.isArray(value) || value.length === 0 || value.some((item) => typeof item !== "string" || item.length === 0)) throw new TypeError(`bootstrap: ${field} must be a non-empty array of non-empty strings`);
3679
- return [...new Set(value)];
3680
- }
3681
- function sourceList(value, field, fallback) {
3682
- if (value === void 0) return new Set(fallback);
3683
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || item.length === 0)) throw new TypeError(`bootstrap: ${field} must be an array of non-empty strings`);
3684
- return new Set(value);
3685
- }
3686
- function resolveBootstrapSettings(opts) {
3687
- const promoteOn = opts.promoteOn ?? "either";
3688
- if (promoteOn !== "either" && promoteOn !== "tool-call" && promoteOn !== "assistant-message") throw new TypeError(`bootstrap: promoteOn must be one of "tool-call", "assistant-message", "either"; got ${JSON.stringify(promoteOn)}`);
3689
- let anchorMessages;
3690
- if (Array.isArray(opts.anchorMessages)) {
3691
- if (opts.anchorMessages.length === 0 || opts.anchorMessages.some((m) => typeof m !== "string" || m.length === 0)) throw new TypeError(`bootstrap: anchorMessages must be a non-empty array of non-empty strings`);
3692
- anchorMessages = opts.anchorMessages;
3693
- } else anchorMessages = [typeof opts.anchorMessage === "string" && opts.anchorMessage.length > 0 ? opts.anchorMessage : DEFAULT_ANCHOR_MESSAGE];
3682
+ /** 协议固有 bootstrap 设置:zeroTools=true(首请求 0 工具纯文字锚定轮)、
3683
+ * 晋升信号仅 assistant/message(对齐 zero-anchored-standard)、
3684
+ * requiredSignals = 锚定轮数(2 条消息 2 条回复后晋升)。无参——零配置面。 */
3685
+ function resolveBootstrapSettings() {
3694
3686
  return {
3695
- bootstrapTools: stringList(opts.bootstrapTools, "bootstrapTools", DEFAULT_BOOTSTRAP_TOOLS),
3696
- promoteEvents: opts.zeroTools ? PROMOTE_EVENTS["assistant-message"] : PROMOTE_EVENTS[promoteOn],
3697
- requiredSignals: opts.zeroTools ? anchorMessages.length : 1,
3698
- suppressedSources: sourceList(opts.suppressedContextSources, "suppressedContextSources", DEFAULT_SUPPRESSED_SOURCES),
3699
- compactionTools: stringList(opts.compactionTools, "compactionTools", DEFAULT_COMPACTION_TOOLS),
3700
- anchorMessages,
3701
- zeroTools: opts.zeroTools === true
3687
+ bootstrapTools: [...DEFAULT_BOOTSTRAP_TOOLS],
3688
+ promoteEvents: PROMOTE_EVENTS["assistant-message"],
3689
+ requiredSignals: DEFAULT_ANCHOR_MESSAGES.length,
3690
+ suppressedSources: new Set(DEFAULT_SUPPRESSED_SOURCES),
3691
+ compactionTools: [...DEFAULT_COMPACTION_TOOLS],
3692
+ anchorMessages: [...DEFAULT_ANCHOR_MESSAGES],
3693
+ zeroTools: true
3702
3694
  };
3703
3695
  }
3704
3696
  /**
3705
- * 注册 Anchored bootstrap 机制(按 agent cwd 动态解析 CCC 配置——多 CCC 架构,与 guards 同模式):
3706
- * 1. session/event 观察晋升信号(tool/call + assistant/message + compaction/end)
3697
+ * 注册 Anchored bootstrap 机制(协议固有,零配置面——S142;按 agent cwd 定位 CCC root,
3698
+ * 晋升状态按 root 隔离,但设置全局一致):
3699
+ * 1. session/event 观察晋升信号(assistant/message + step/start 兜底 + compaction/end)
3707
3700
  * 2. system-prompt/assemble:bootstrap 阶段目录窄化到 bootstrapTools(+compaction 后 compactionTools)
3708
3701
  * 3. agent/pre-step:bootstrap 阶段剥离 suppressedSources 注入消息(降级保留全部)
3709
3702
  *
3710
- * CCC 的 serenity.json 配置 `bootstrap.enabled: true` 才生效(否则零影响);
3711
3703
  * 摘除 = 删除 index.ts 中本注册行(独立模块)。
3712
3704
  */
3713
3705
  /** 从 agent 解析 CCC 根(宽松;无 agent/无 CCC 返回 null) */
@@ -3716,31 +3708,16 @@ function agentRoot(agent) {
3716
3708
  if (typeof cwd !== "string") return null;
3717
3709
  return findSerenityRoot(cwd);
3718
3710
  }
3719
- /** agent cwd 解析 bootstrap 配置(总是生效——无 enabled 开关,用户明确"直接开启不能关";
3720
- * CCC serenity.json bootstrap 段仅用于调参数,缺省用默认设置) */
3721
- function readBootstrapConfig(agent) {
3722
- const root = agentRoot(agent);
3723
- if (!root) return resolveBootstrapSettings({});
3724
- const b = loadSerenityConfig(root).bootstrap;
3725
- return resolveBootstrapSettings({
3726
- bootstrapTools: b?.bootstrapTools,
3727
- promoteOn: b?.promoteOn,
3728
- suppressedContextSources: b?.suppressedContextSources,
3729
- compactionTools: b?.compactionTools,
3730
- anchorMessage: b?.anchorMessage,
3731
- anchorMessages: b?.anchorMessages,
3732
- zeroTools: b?.zeroTools
3733
- });
3734
- }
3711
+ /** 协议固有设置(零配置面):所有 CCC 使用同一固化设置 */
3712
+ const SETTINGS = resolveBootstrapSettings();
3735
3713
  function registerBootstrap(ctx) {
3736
- const settingsByRoot = /* @__PURE__ */ new Map();
3737
3714
  const trackers = /* @__PURE__ */ new Map();
3738
3715
  /** 已锚定会话(进程内防重:子 agent 每会话只锚定一次) */
3739
3716
  const anchoredSessions = /* @__PURE__ */ new Set();
3740
- const trackerFor = (root, settings) => {
3717
+ const trackerFor = (root) => {
3741
3718
  let t = trackers.get(root);
3742
3719
  if (!t) {
3743
- t = createEpochPromotion(settings.promoteEvents, settings.requiredSignals);
3720
+ t = createEpochPromotion(SETTINGS.promoteEvents, SETTINGS.requiredSignals);
3744
3721
  trackers.set(root, t);
3745
3722
  }
3746
3723
  return t;
@@ -3751,16 +3728,12 @@ function registerBootstrap(ctx) {
3751
3728
  if (typeof cwd !== "string") return;
3752
3729
  const root = findSerenityRoot(cwd);
3753
3730
  if (!root) return;
3754
- const settings = settingsByRoot.get(root) ?? readBootstrapConfig({ session });
3755
- settingsByRoot.set(root, settings);
3756
- trackerFor(root, settings).observe(session, event);
3731
+ trackerFor(root).observe(session, event);
3757
3732
  } catch {}
3758
3733
  });
3759
3734
  ctx.on("agent/inbox/inserted", ({ agent, message }) => {
3760
3735
  try {
3761
- const root = agentRoot(agent);
3762
- if (!root) return;
3763
- const settings = settingsByRoot.get(root) ?? readBootstrapConfig(agent);
3736
+ if (!agentRoot(agent)) return;
3764
3737
  const session = agent.session;
3765
3738
  const depth = session?.header?.delegationDepth ?? 0;
3766
3739
  const sid = typeof session?.id === "string" ? session.id : void 0;
@@ -3771,12 +3744,12 @@ function registerBootstrap(ctx) {
3771
3744
  if (message?.source?.kind === "plugin") return;
3772
3745
  const inbox = agent.inbox;
3773
3746
  if (!inbox?.prepend) return;
3774
- for (let i = settings.anchorMessages.length - 1; i >= 0; i--) inbox.prepend("next-turn", {
3747
+ for (let i = SETTINGS.anchorMessages.length - 1; i >= 0; i--) inbox.prepend("next-turn", {
3775
3748
  id: `bootstrap-anchor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}-${i}`,
3776
3749
  role: "user",
3777
3750
  content: [{
3778
3751
  type: "text",
3779
- text: settings.anchorMessages[i]
3752
+ text: SETTINGS.anchorMessages[i]
3780
3753
  }],
3781
3754
  source: {
3782
3755
  kind: "plugin",
@@ -3786,7 +3759,7 @@ function registerBootstrap(ctx) {
3786
3759
  }
3787
3760
  });
3788
3761
  if (sid !== void 0) anchoredSessions.add(sid);
3789
- warnOnce(`anchor turns injected: ${settings.anchorMessages.length} 条(${settings.anchorMessages[0].slice(0, 40)}…)`);
3762
+ warnOnce(`anchor turns injected: ${SETTINGS.anchorMessages.length} 条(${SETTINGS.anchorMessages[0].slice(0, 40)}…)`);
3790
3763
  } catch {}
3791
3764
  });
3792
3765
  let warned = false;
@@ -3803,19 +3776,17 @@ function registerBootstrap(ctx) {
3803
3776
  const agent = context.agent;
3804
3777
  const root = agentRoot(agent);
3805
3778
  if (!root) return assembled;
3806
- const settings = settingsByRoot.get(root) ?? readBootstrapConfig(agent);
3807
- settingsByRoot.set(root, settings);
3808
- const status = trackerFor(root, settings).status(agent);
3779
+ const status = trackerFor(root).status(agent);
3809
3780
  if (status.promoted) return assembled;
3810
3781
  const tools = assembled.tools;
3811
3782
  if (!Array.isArray(tools)) return assembled;
3812
3783
  const available = new Set(tools.map((tool) => tool.name).filter((n) => typeof n === "string"));
3813
- if (settings.zeroTools) {
3784
+ if (SETTINGS.zeroTools) {
3814
3785
  if (status.boundary < 0) return {
3815
3786
  ...assembled,
3816
3787
  tools: []
3817
3788
  };
3818
- const keep = new Set(settings.compactionTools);
3789
+ const keep = new Set(SETTINGS.compactionTools);
3819
3790
  const missing = [...keep].filter((name) => !available.has(name));
3820
3791
  if (missing.length > 0) {
3821
3792
  warnOnce(`expected compaction tools missing=${JSON.stringify(missing)} — bootstrap disabled, full catalog exposed`);
@@ -3826,8 +3797,8 @@ function registerBootstrap(ctx) {
3826
3797
  tools: tools.filter((tool) => typeof tool.name === "string" && keep.has(tool.name))
3827
3798
  };
3828
3799
  }
3829
- const keep = new Set(settings.bootstrapTools);
3830
- if (status.boundary >= 0) for (const toolName of settings.compactionTools) keep.add(toolName);
3800
+ const keep = new Set(SETTINGS.bootstrapTools);
3801
+ if (status.boundary >= 0) for (const toolName of SETTINGS.compactionTools) keep.add(toolName);
3831
3802
  const missing = [...keep].filter((name) => !available.has(name));
3832
3803
  if (missing.length > 0) {
3833
3804
  warnOnce(`expected bootstrap tools missing=${JSON.stringify(missing)} — bootstrap disabled, full catalog exposed`);
@@ -3848,14 +3819,12 @@ function registerBootstrap(ctx) {
3848
3819
  try {
3849
3820
  const root = agentRoot(agent);
3850
3821
  if (!root) return decision;
3851
- const settings = settingsByRoot.get(root) ?? readBootstrapConfig(agent);
3852
- settingsByRoot.set(root, settings);
3853
- if (trackerFor(root, settings).status(agent).promoted || settings.suppressedSources.size === 0) return decision;
3822
+ if (trackerFor(root).status(agent).promoted || SETTINGS.suppressedSources.size === 0) return decision;
3854
3823
  const messages = decision.messages;
3855
3824
  if (!Array.isArray(messages)) return decision;
3856
3825
  const kept = messages.filter((message) => {
3857
3826
  const kind = message?.source?.kind;
3858
- return typeof kind !== "string" || !settings.suppressedSources.has(kind);
3827
+ return typeof kind !== "string" || !SETTINGS.suppressedSources.has(kind);
3859
3828
  });
3860
3829
  return kept.length === messages.length ? decision : {
3861
3830
  ...decision,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.19.3",
3
+ "version": "1.19.5",
4
4
  "description": "宁静号 ACC harness — Native Cordis 插件(DeepSeek Harness 运行时)。真实 DSH 工具注册(cc_fs/session/acc_msm 等 9 工具)+ 拦截缝机械约束(safe-mode/路径守卫/会话落盘)+ 系统提示词注入(ACC/CCE/Constraints/SKILL/Session 五块)。适配 DSH 公开版(deepseek-ai/deepseek-harness 0.1.0-rc)。",
5
5
  "license": "MIT",
6
6
  "repository": {