@shgroup/dsh-serenity-hooks 1.18.2 → 1.18.4

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.18.2",
3
+ "version": "1.18.4",
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
@@ -3524,11 +3524,17 @@ const DEFAULT_COMPACTION_TOOLS = [
3524
3524
  "grep",
3525
3525
  "todo_write"
3526
3526
  ];
3527
- /** 默认首轮锚定问题(用户指定:介绍宁静号,200 字以内) */
3528
- const DEFAULT_ANCHOR_MESSAGE = "请介绍当前宁静号,它是什么,为了什么,200字以内回答";
3529
- /** 构建一个 epoch 感知晋升跟踪器(纯逻辑,可单测) */
3530
- function createEpochPromotion(promoteEvents) {
3531
- /** sessionId -> { boundary, promoted } */
3527
+ /** 默认首轮锚定消息(用户指定:persona 设定 + we/us 人称——首轮模型以 we/us 自称,
3528
+ * 对齐 anchored 实测的 "we" 轨迹特征) */
3529
+ const DEFAULT_ANCHOR_MESSAGE = "You are a helpful software engineer assistant.The personal pronoun is us/we.";
3530
+ /**
3531
+ * 构建一个 epoch 感知晋升跟踪器(纯逻辑,可单测)。
3532
+ * requiredSignals:晋升所需信号数(boundary 后累计;默认 1)。
3533
+ * 多轮锚定(v4):两轮递进锚定时 requiredSignals = 锚定轮数——
3534
+ * 每条锚定回复(assistant/message)计一次,最后一条回复后晋升。
3535
+ */
3536
+ function createEpochPromotion(promoteEvents, requiredSignals = 1) {
3537
+ /** sessionId -> { boundary, signalCount }(boundary 后晋升信号计数) */
3532
3538
  const state = /* @__PURE__ */ new Map();
3533
3539
  const sessionIdOf = (session) => {
3534
3540
  if (session && typeof session === "object") {
@@ -3538,24 +3544,27 @@ function createEpochPromotion(promoteEvents) {
3538
3544
  };
3539
3545
  const scan = (session) => {
3540
3546
  let boundary = -1;
3541
- let promoted = false;
3547
+ let signalCount = 0;
3542
3548
  const events = session?.events;
3543
3549
  if (Array.isArray(events)) for (const event of events) {
3544
3550
  const e = event;
3545
3551
  const seq = typeof e.seq === "number" ? e.seq : 0;
3546
3552
  if (e.type === "compaction/end") {
3547
3553
  boundary = seq;
3548
- promoted = false;
3554
+ signalCount = 0;
3549
3555
  continue;
3550
3556
  }
3551
- if (promoteEvents.has(e.type) && seq > boundary) promoted = true;
3557
+ if (promoteEvents.has(e.type) && seq > boundary) signalCount++;
3552
3558
  }
3553
3559
  const entry = {
3554
3560
  boundary,
3555
- promoted
3561
+ promoted: signalCount >= requiredSignals
3556
3562
  };
3557
3563
  const sid = sessionIdOf(session);
3558
- if (sid) state.set(sid, entry);
3564
+ if (sid) state.set(sid, {
3565
+ boundary,
3566
+ signalCount
3567
+ });
3559
3568
  return entry;
3560
3569
  };
3561
3570
  return {
@@ -3578,7 +3587,12 @@ function createEpochPromotion(promoteEvents) {
3578
3587
  boundary: -1,
3579
3588
  promoted: true
3580
3589
  };
3581
- return state.get(sid) ?? scan(session);
3590
+ const s = state.get(sid);
3591
+ if (s) return {
3592
+ boundary: s.boundary,
3593
+ promoted: s.signalCount >= requiredSignals
3594
+ };
3595
+ return scan(session);
3582
3596
  },
3583
3597
  observe(session, event) {
3584
3598
  const sid = sessionIdOf(session);
@@ -3590,13 +3604,13 @@ function createEpochPromotion(promoteEvents) {
3590
3604
  if (e.type === "compaction/end") {
3591
3605
  state.set(sid, {
3592
3606
  boundary: seq,
3593
- promoted: false
3607
+ signalCount: 0
3594
3608
  });
3595
3609
  return;
3596
3610
  }
3597
- if (promoteEvents.has(e.type) && seq > entry.boundary && !entry.promoted) state.set(sid, {
3598
- ...entry,
3599
- promoted: true
3611
+ if (promoteEvents.has(e.type) && seq > entry.boundary) state.set(sid, {
3612
+ boundary: entry.boundary,
3613
+ signalCount: entry.signalCount + 1
3600
3614
  });
3601
3615
  }
3602
3616
  };
@@ -3619,12 +3633,18 @@ function sourceList(value, field, fallback) {
3619
3633
  function resolveBootstrapSettings(opts) {
3620
3634
  const promoteOn = opts.promoteOn ?? "either";
3621
3635
  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)}`);
3636
+ let anchorMessages;
3637
+ if (Array.isArray(opts.anchorMessages)) {
3638
+ 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`);
3639
+ anchorMessages = opts.anchorMessages;
3640
+ } else anchorMessages = [typeof opts.anchorMessage === "string" && opts.anchorMessage.length > 0 ? opts.anchorMessage : DEFAULT_ANCHOR_MESSAGE];
3622
3641
  return {
3623
3642
  bootstrapTools: stringList(opts.bootstrapTools, "bootstrapTools", DEFAULT_BOOTSTRAP_TOOLS),
3624
3643
  promoteEvents: opts.zeroTools ? PROMOTE_EVENTS["assistant-message"] : PROMOTE_EVENTS[promoteOn],
3644
+ requiredSignals: opts.zeroTools ? anchorMessages.length : 1,
3625
3645
  suppressedSources: sourceList(opts.suppressedContextSources, "suppressedContextSources", DEFAULT_SUPPRESSED_SOURCES),
3626
3646
  compactionTools: stringList(opts.compactionTools, "compactionTools", DEFAULT_COMPACTION_TOOLS),
3627
- anchorMessage: typeof opts.anchorMessage === "string" && opts.anchorMessage.length > 0 ? opts.anchorMessage : DEFAULT_ANCHOR_MESSAGE,
3647
+ anchorMessages,
3628
3648
  zeroTools: opts.zeroTools === true
3629
3649
  };
3630
3650
  }
@@ -3655,6 +3675,7 @@ function readBootstrapConfig(agent) {
3655
3675
  suppressedContextSources: b?.suppressedContextSources,
3656
3676
  compactionTools: b?.compactionTools,
3657
3677
  anchorMessage: b?.anchorMessage,
3678
+ anchorMessages: b?.anchorMessages,
3658
3679
  zeroTools: b?.zeroTools
3659
3680
  });
3660
3681
  }
@@ -3664,7 +3685,7 @@ function registerBootstrap(ctx) {
3664
3685
  const trackerFor = (root, settings) => {
3665
3686
  let t = trackers.get(root);
3666
3687
  if (!t) {
3667
- t = createEpochPromotion(settings.promoteEvents);
3688
+ t = createEpochPromotion(settings.promoteEvents, settings.requiredSignals);
3668
3689
  trackers.set(root, t);
3669
3690
  }
3670
3691
  return t;
@@ -3691,12 +3712,12 @@ function registerBootstrap(ctx) {
3691
3712
  if (message?.source?.kind === "plugin") return;
3692
3713
  const inbox = agent.inbox;
3693
3714
  if (!inbox?.prepend) return;
3694
- inbox.prepend("next-turn", {
3695
- id: `bootstrap-anchor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
3715
+ for (let i = settings.anchorMessages.length - 1; i >= 0; i--) inbox.prepend("next-turn", {
3716
+ id: `bootstrap-anchor-${Date.now()}-${Math.random().toString(36).slice(2, 8)}-${i}`,
3696
3717
  role: "user",
3697
3718
  content: [{
3698
3719
  type: "text",
3699
- text: settings.anchorMessage
3720
+ text: settings.anchorMessages[i]
3700
3721
  }],
3701
3722
  source: {
3702
3723
  kind: "plugin",
@@ -3705,7 +3726,7 @@ function registerBootstrap(ctx) {
3705
3726
  summary: "bootstrap anchor turn"
3706
3727
  }
3707
3728
  });
3708
- warnOnce(`anchor turn injected: "${settings.anchorMessage.slice(0, 40)}…"`);
3729
+ warnOnce(`anchor turns injected: ${settings.anchorMessages.length} 条(${settings.anchorMessages[0].slice(0, 40)}…)`);
3709
3730
  } catch {}
3710
3731
  });
3711
3732
  let warned = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.18.2",
3
+ "version": "1.18.4",
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": {