@shgroup/dsh-serenity-hooks 1.75.0 → 1.76.0
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/{ccc-roots-BVxn97dY.js → ccc-roots-rwgzt_0F.js} +1 -1
- package/lib/host/storage-domain.d.ts +8 -0
- package/lib/index.js +125 -13
- package/lib/{message-source-JhN-qyfn.js → message-source-C_Zd2vJh.js} +6 -3
- package/lib/{profile-Cz4oBXlI.js → profile-DplLGGqo.js} +14 -1
- package/lib/{settings-CII0Y597.js → settings-f9WZXcgi.js} +1 -1
- package/lib/trajectory/bound.d.ts +3 -0
- package/lib/trajectory/core.d.ts +8 -0
- package/lib/trajectory/user-carrier.d.ts +82 -0
- 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.
|
|
3
|
+
"version": "1.76.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——14 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 认知轨迹日志与原地重建 + 网页登录入口/IM 桥/认知轨迹唤醒注册表。轨迹声明 = 轨迹目录下的 trajectory.json(约束面 + 旧标识 uid + CRO 机器绑定 cro.host;旧名 trajectory-constraint.json / skiff.json 仍在读取族里);轨迹提示词 = 轨迹目录下的 PROMPT.md(一条轨迹「是谁、按什么章程工作」,所有轨迹通用,追加在容器层与质量层之后,不替换它们)。适配 DSH 0.1.7-rc.1 / 0.2.0-rc.1 / 0.2.1-rc.1(三档,deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
|
@@ -227,7 +227,7 @@ async function listCccs(ctx, opts = {}) {
|
|
|
227
227
|
if (typeof defaultRoot === "string" && defaultRoot !== "" && !c.roots.includes(defaultRoot)) c.roots.unshift(defaultRoot);
|
|
228
228
|
let rolesOf = null;
|
|
229
229
|
if (opts.withRoles === true) {
|
|
230
|
-
const { listTrajectoryConstraints } = await import("./profile-
|
|
230
|
+
const { listTrajectoryConstraints } = await import("./profile-DplLGGqo.js").then((n) => n.i);
|
|
231
231
|
rolesOf = (root) => {
|
|
232
232
|
try {
|
|
233
233
|
return listTrajectoryConstraints(root).map((p) => p.code);
|
|
@@ -43,6 +43,14 @@ export interface BindingRecord {
|
|
|
43
43
|
action: string;
|
|
44
44
|
at: number;
|
|
45
45
|
note?: string;
|
|
46
|
+
/**
|
|
47
|
+
* 🆕 **这条载体是 ACC 以"用户开场白"形态建出来的**(2026-10-20 owner 裁 B)。
|
|
48
|
+
*
|
|
49
|
+
* 🔴 为什么必须单列一个字段、而不是靠 `note` 文案判:`note` 是人类可读的自由文本,
|
|
50
|
+
* 判据一旦长在它上面,改一次文案就静默失效(D151 同族:引用与口径会随演进失效)。
|
|
51
|
+
* ⇒ 审计"哪些会话不是真人建的"必须有一个**布尔事实**。
|
|
52
|
+
*/
|
|
53
|
+
createdAsUser?: boolean;
|
|
46
54
|
/** 已被取代(D69:同轨迹多会话只留一条;记录保留、退出"当前") */
|
|
47
55
|
supersededAt?: number;
|
|
48
56
|
}
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { i as __toESM, n as __exportAll } from "./rolldown-runtime-B4iAMlE-.js";
|
|
2
|
-
import { c as hostInjected, d as hostSessions, f as hostSettings, h as hostWebServer, i as cccRootForExec, l as hostLlm, m as hostWeb, n as agentCwdFor, o as listCccs, p as hostSubagents, r as cccRootForCwd, s as hostAgents, t as NO_CCC_FROM_AGENT_CWD, u as hostService } from "./ccc-roots-
|
|
2
|
+
import { c as hostInjected, d as hostSessions, f as hostSettings, h as hostWebServer, i as cccRootForExec, l as hostLlm, m as hostWeb, n as agentCwdFor, o as listCccs, p as hostSubagents, r as cccRootForCwd, s as hostAgents, t as NO_CCC_FROM_AGENT_CWD, u as hostService } from "./ccc-roots-rwgzt_0F.js";
|
|
3
3
|
import { _ as resolveInside, a as findSerenityRoot$1, c as matchBlacklist, d as readCccName$1, f as readCheapWorkerConfig, g as readUtf8, h as readSafeModeHiddenTools, i as findGitRoot, l as pathInside, m as readExclusiveTools, n as SAFE_MODE_MARKER, o as isSafeModeOn, p as readCognitiveTrajectorySkills, r as classifyPath, s as loadSerenityConfig, t as DEFAULT_SERENITY_CONFIG_PATHS, u as readBlacklist } from "./ccc-CyYJL4F2.js";
|
|
4
|
-
import { A as sessionsRoot, B as
|
|
4
|
+
import { A as sessionsRoot, B as localFileStamp, C as namingTitleFor, D as readTrajectoryUid, E as readActiveSessionMd, F as useSession, H as localIdStamp, I as TRAJECTORY_FILENAME, L as TRAJECTORY_LEGACY_FILENAMES, M as showSession, N as summarize, O as resolveSessionByTitle, P as trajectoryDescOf, R as readTrajectoryFile, S as listSessions, T as parseTrajectoryCode, V as localHuman, _ as extractSessionMdPathFromText, a as readTrajectoryConstraintAt, c as registerTrajectorySession$1, d as COGNITIVE_TRAJECTORY_ACTIONS, f as DEFAULT_SESSION_SCOPE, g as createSession, h as clearActiveSessionInfo, j as setActiveSessionInfo, k as sessionEvents$1, l as trajectoryDirNameForSession, m as archiveSession, n as isTrajectoryConstrained, o as readTrajectoryConstraintByCode, p as UID_FILENAME, r as listTrajectoryConstraints, s as trajectoryConstraintForSession, t as TRAJECTORY_CONSTRAINT_FILENAME, u as unregisterTrajectorySession$1, v as findSession, w as parseSessionContextFromEvents, x as listActiveTrajectories, y as getActiveSessionInfo, z as isoLocal } from "./profile-DplLGGqo.js";
|
|
5
5
|
import { _ as runLocalStore, a as readFeishuCredential, d as weixinSessionIdForTrajectory, f as LOCALSTORE_SCOPES, g as readStore, h as readGitTrack, i as matchWeixinRoute, l as sanitizeFileName$1, m as localstorePath, n as extractWeixinText, o as readWeixinCredential, p as checkLocalstoreGitCompliance, r as hasVoiceItem, s as readWeixinSettings, t as extractWeixinMedia, u as weixinInboundDir } from "./route-COOFLTpU.js";
|
|
6
|
-
import { a as buildTrajectoryBasePrompt, c as createProfilePromptReader, d as resolveConstraintSystemPrompt, f as ACC_VERSION, i as TRAJECTORY_CONSTRAINT_HINT, l as profileMsmWhitelist, n as readSimpleSettings, o as constraintCognitiveTrajectory, p as findPackageRoot, r as registerSettingsSection, s as constraintSystemPromptSource, u as profileToolWhitelist } from "./settings-
|
|
7
|
-
import { a as pruneMissingBindings, c as setBindingStore, i as listBoundSessionIds, n as PLUGIN_SOURCE, o as readLastBound, r as appendBound, s as resolveSessionCognitiveTrajectoryLabel, t as ACC_MESSAGE_KIND } from "./message-source-
|
|
6
|
+
import { a as buildTrajectoryBasePrompt, c as createProfilePromptReader, d as resolveConstraintSystemPrompt, f as ACC_VERSION, i as TRAJECTORY_CONSTRAINT_HINT, l as profileMsmWhitelist, n as readSimpleSettings, o as constraintCognitiveTrajectory, p as findPackageRoot, r as registerSettingsSection, s as constraintSystemPromptSource, u as profileToolWhitelist } from "./settings-f9WZXcgi.js";
|
|
7
|
+
import { a as pruneMissingBindings, c as setBindingStore, i as listBoundSessionIds, n as PLUGIN_SOURCE, o as readLastBound, r as appendBound, s as resolveSessionCognitiveTrajectoryLabel, t as ACC_MESSAGE_KIND } from "./message-source-C_Zd2vJh.js";
|
|
8
8
|
import { REGISTERED_TOOLS } from "./invariant.js";
|
|
9
9
|
import { c as sendTextMessage, i as getUpdates, l as sendTyping, n as downloadMedia, o as markdownToPlainText, r as getConfig, s as sendFileMessage, t as TypingStatus, u as sniffImageExt } from "./ilink-BMk2w2KY.js";
|
|
10
10
|
import { a as registerImAccountImpl, i as normalizeAccountChannel, n as getImAccountImpl, r as imAccountChannels } from "./accounts-BHQbakUh.js";
|
|
@@ -10160,6 +10160,110 @@ function listWakes(root, opts = {}) {
|
|
|
10160
10160
|
};
|
|
10161
10161
|
}
|
|
10162
10162
|
//#endregion
|
|
10163
|
+
//#region src/trajectory/user-carrier.ts
|
|
10164
|
+
/**
|
|
10165
|
+
* trajectory/user-carrier.ts — **造一条与"用户人工创建"基本一致的 dsh 会话载体**(判决 D171,owner 2026-10-20 裁 B)
|
|
10166
|
+
*
|
|
10167
|
+
* ## 这个文件解决什么(白话)
|
|
10168
|
+
*
|
|
10169
|
+
* `send-now` 在目标没有活跃会话时会**就地建一条**。它一直能建、也能挂工作区,
|
|
10170
|
+
* 但建出来的东西与用户在 UI 里新建的那条**在宿主眼里不是同一种东西**:
|
|
10171
|
+
*
|
|
10172
|
+
* | 宿主投影 | 用户建 | 我们自建(修前实测) |
|
|
10173
|
+
* |---|---|---|
|
|
10174
|
+
* | `title` | 自动生成 | **永远 `null`** |
|
|
10175
|
+
* | `titleInput.count` | ≥1 | **0** |
|
|
10176
|
+
* | 假首轮(对齐声明 + EAP) | 注入 | **被自家递归守卫挡掉** |
|
|
10177
|
+
*
|
|
10178
|
+
* ## 🔴 根因(读宿主源码,不是推断)
|
|
10179
|
+
*
|
|
10180
|
+
* `dsh-session-title` 的 `sessionTitleUserMessageOf()` **第一行**就是:
|
|
10181
|
+
*
|
|
10182
|
+
* ```js
|
|
10183
|
+
* if (event.type !== "user/message" || event.data.source.kind !== "user") return void 0
|
|
10184
|
+
* ```
|
|
10185
|
+
*
|
|
10186
|
+
* 而 ACC 投递的消息一律是 `{ kind: 'plugin:dsh-serenity-hooks' }`(`kernel/message-source.ts`)
|
|
10187
|
+
* ⇒ **宿主从头到尾不把它当"有真人说过话"的会话** ⇒ 自动命名不触发、`titleInput` 恒 0。
|
|
10188
|
+
*
|
|
10189
|
+
* ## owner 的裁决 = B:**模拟一个用户开场白**
|
|
10190
|
+
*
|
|
10191
|
+
* `MessageSourceMap` 里 `user: { kind: 'user' }`,而 `UserMessage.source` 是**任意**
|
|
10192
|
+
* `MessageSource` ⇒ `createUserMessage({ content, source: { kind: 'user' } })` **类型合法、
|
|
10193
|
+
* 零改 DSH**(D4 仍成立)。
|
|
10194
|
+
*
|
|
10195
|
+
* ## 🔴 这是一次**明知故犯的伪造**,代价写在这里,不许悄悄付
|
|
10196
|
+
*
|
|
10197
|
+
* 1. **伪造用户身份**:与 D160「不再造历史」方向相反。范围**仅限**"载体开场白"这一条消息,
|
|
10198
|
+
* 且正文**逐字自证**是模拟的({@link CARRIER_OPENING_MARK})⇒ 将来翻日志的人一眼能看出。
|
|
10199
|
+
* 2. **污染所有者语料**:`session-corpus` 的"所有者发言"判据**必须**排除这条
|
|
10200
|
+
* (判据 = 正文含 {@link CARRIER_OPENING_MARK})⇒ 否则统计"owner 说过什么"会算进一句
|
|
10201
|
+
* 机器写的开场白。**这一条是同批改动,不是待办。**
|
|
10202
|
+
* 3. **与假首轮的先后**:开场白必须让假首轮先注入(同一次 `agent/inbox/inserted` 里
|
|
10203
|
+
* prepend 天然排在真实消息之前),否则 `hasUserMessageHistory` 会把假首轮挡掉。
|
|
10204
|
+
* ⇒ 单测钉死顺序,不靠"应该会"。
|
|
10205
|
+
*
|
|
10206
|
+
* ## 归属(D23)
|
|
10207
|
+
* 机制在 ACC(怎么建、建什么形状);**内容归 CCC**(开场白正文由调用方给)。
|
|
10208
|
+
*
|
|
10209
|
+
* ## 与 `trajectory/carrier.ts` 的关系
|
|
10210
|
+
* 🔴 **两个文件、两件事**,名字刻意区分:`carrier.ts` 回答"**这条载体跑完没有**"(等待空闲/销毁竞速);
|
|
10211
|
+
* 本文件回答"**怎么造一条载体**"。合在一起会让两条互不相关的依赖链卷成一团。
|
|
10212
|
+
*/
|
|
10213
|
+
/**
|
|
10214
|
+
* 模拟开场白的**自证标记**(逐字)。
|
|
10215
|
+
*
|
|
10216
|
+
* 🔴 三个用途,缺一不可:
|
|
10217
|
+
* ① 人类翻日志时能一眼看出"这不是真主说的";
|
|
10218
|
+
* ② `session-corpus` 用它**排除**语料(不污染"所有者发言");
|
|
10219
|
+
* ③ 单测反向钉住:真实用户发言里**不会**出现这串 ⇒ 断言"语料里 0 条含它"才有意义。
|
|
10220
|
+
*/
|
|
10221
|
+
const CARRIER_OPENING_MARK = "[ACC 代用户开场]";
|
|
10222
|
+
/**
|
|
10223
|
+
* 构造模拟开场白的正文。
|
|
10224
|
+
*
|
|
10225
|
+
* ⚠️ **不含版本号/日期/模型名**(D159:任务书里不得写死版本号 ⇒ 写与版本无关的判据)。
|
|
10226
|
+
* 正文只描述"这是谁、要接着做什么",不描述"哪一版干的"。
|
|
10227
|
+
*
|
|
10228
|
+
* @param code 轨迹编码(`S###` 或自定义)
|
|
10229
|
+
* @param desc 轨迹目录名里那段可读描述(**人起的**,不另造第二真相源)
|
|
10230
|
+
* @returns 一条自证是模拟的开场白正文
|
|
10231
|
+
*/
|
|
10232
|
+
function buildCarrierOpening(code, desc) {
|
|
10233
|
+
const label = desc.trim() === "" ? code : `${code}(${desc})`;
|
|
10234
|
+
return [
|
|
10235
|
+
`${CARRIER_OPENING_MARK} 激活认知轨迹 ${label},接着它 SESSION.md 里的工作往下做。`,
|
|
10236
|
+
"",
|
|
10237
|
+
"(这条开场白由 ACC 代为发出。如此做的目的只有一个:让程序性创建的会话与用户在界面里",
|
|
10238
|
+
"人工创建的会话,在宿主侧具有相同的投影 —— 有标题、有首轮对齐声明。它不是任何人的发言。)"
|
|
10239
|
+
].join("\n");
|
|
10240
|
+
}
|
|
10241
|
+
/**
|
|
10242
|
+
* 投一条"用户形态"的消息进目标 agent(**B 的核心动作**)。
|
|
10243
|
+
*
|
|
10244
|
+
* 🔴 为什么单独成函数而不是就地写:这是**全仓唯一**允许 `kind:'user'` 的地方。
|
|
10245
|
+
* 集中在一处,将来若要收紧(或 owner 改主意回 A),只有一个点要改。
|
|
10246
|
+
*
|
|
10247
|
+
* @param agent 目标 agent(须有 `followup`)
|
|
10248
|
+
* @param text 开场白正文(**必须**由 {@link buildCarrierOpening} 产出,以带上自证标记)
|
|
10249
|
+
* @returns 投递是否成功(失败返回 false,由调用方决定降级 —— 不抛)
|
|
10250
|
+
*/
|
|
10251
|
+
function deliverCarrierOpening(agent, text) {
|
|
10252
|
+
if (typeof agent.followup !== "function") return false;
|
|
10253
|
+
try {
|
|
10254
|
+
agent.followup(createUserMessage({
|
|
10255
|
+
content: [{
|
|
10256
|
+
type: "text",
|
|
10257
|
+
text
|
|
10258
|
+
}],
|
|
10259
|
+
source: { kind: "user" }
|
|
10260
|
+
}));
|
|
10261
|
+
return true;
|
|
10262
|
+
} catch {
|
|
10263
|
+
return false;
|
|
10264
|
+
}
|
|
10265
|
+
}
|
|
10266
|
+
//#endregion
|
|
10163
10267
|
//#region src/cro/core.ts
|
|
10164
10268
|
/**
|
|
10165
10269
|
* cro/core.ts — CRO(Continuous Re-Occurrence · 持续再发生)机制层(S142 §7.8,2026-09-19)
|
|
@@ -11939,10 +12043,12 @@ async function createAndBindTarget(ctx, root, dirName) {
|
|
|
11939
12043
|
} }, "activate", {
|
|
11940
12044
|
dirName,
|
|
11941
12045
|
mdPath: join(root, "AGENT_SESSIONS", dirName, "SESSION.md"),
|
|
11942
|
-
note: "auto-created by send-now"
|
|
12046
|
+
note: "auto-created by send-now",
|
|
12047
|
+
createdAsUser: true
|
|
11943
12048
|
});
|
|
12049
|
+
const openingNote = deliverCarrierOpening(agent, buildCarrierOpening(parseTrajectoryCode(dirName) ?? dirName, trajectoryDescOf(dirName))) ? ", opening-as-user" : ", ⚠️ 开场白未投递";
|
|
11944
12050
|
const wsNote = workspaceId !== void 0 ? "" : await attachToWorkspace(ctx, root, sessionId);
|
|
11945
|
-
const how = `auto-create(${sessionId}${bound ? ", bound" : ", ⚠️ 绑定写入失败"}${workspaceId !== void 0 ? ", via-workspaceId(=用户同一形态)" : ", via-cwd+attach"}${wsNote})`;
|
|
12051
|
+
const how = `auto-create(${sessionId}${bound ? ", bound" : ", ⚠️ 绑定写入失败"}${workspaceId !== void 0 ? ", via-workspaceId(=用户同一形态)" : ", via-cwd+attach"}${openingNote}${wsNote})`;
|
|
11946
12052
|
return {
|
|
11947
12053
|
agent,
|
|
11948
12054
|
how
|
|
@@ -12711,6 +12817,12 @@ function createCognitiveTrajectoryTool(ctx) {
|
|
|
12711
12817
|
"rebuild requires --summary (next-phase summary ≤20 chars) + optional --note (task focus for the rebuilt self).",
|
|
12712
12818
|
"send-later requires target (a code or AGENT_SESSIONS dir name) + at (RFC3339 or +30m/+2h) + message.",
|
|
12713
12819
|
"send-now requires target + message.",
|
|
12820
|
+
"AUTHORIZATION (read this before creating anything): creating a cognitive trajectory or a dsh carrier costs real work,",
|
|
12821
|
+
"and both are meant to serve a human intent — not to be spawned speculatively. Call create only when the user asked for",
|
|
12822
|
+
"a new line of work (or confirmed it), never to \"tidy up\" or to pre-provision something nobody requested.",
|
|
12823
|
+
"send-now creating a missing carrier on demand is likewise acceptable ONLY for a delivery the user actually wants made;",
|
|
12824
|
+
"it is not a way to start work nobody asked for. When in doubt, ask the user instead of creating.",
|
|
12825
|
+
"⚠️ This is a behavioral rule, not a mechanical gate: nothing stops a careless call. Treat it as etiquette with a cost.",
|
|
12714
12826
|
"uid: READS a legacy TRAJECTORY-UID only — setting one is retired (codes replaced it). Use create --id instead.",
|
|
12715
12827
|
"The summary is appended to the dsh session title (S###-YYYY-MM-DD-<summary>); the code and date stay server-derived unless you pass --id."
|
|
12716
12828
|
].join(" "),
|
|
@@ -12747,7 +12859,7 @@ function createCognitiveTrajectoryTool(ctx) {
|
|
|
12747
12859
|
},
|
|
12748
12860
|
desc: {
|
|
12749
12861
|
type: "string",
|
|
12750
|
-
description: "create: short description (any language, ≤5 words; mutually exclusive with issue)"
|
|
12862
|
+
description: "create: short description (any language, ≤5 words; mutually exclusive with issue). 🔴 AUTHORIZATION: create is user-intent-driven — do not create a trajectory the user did not ask for (see the tool description)."
|
|
12751
12863
|
},
|
|
12752
12864
|
id: {
|
|
12753
12865
|
type: "string",
|
|
@@ -12783,7 +12895,7 @@ function createCognitiveTrajectoryTool(ctx) {
|
|
|
12783
12895
|
},
|
|
12784
12896
|
message: {
|
|
12785
12897
|
type: "string",
|
|
12786
|
-
description: "send-later/send-now: the single message delivered to the target cognitive trajectory"
|
|
12898
|
+
description: "send-later/send-now: the single message delivered to the target cognitive trajectory. send-now may create and bind a carrier when the target has no live session — acceptable only for a delivery the user actually wants made (user-intent-driven), not for speculatively starting work."
|
|
12787
12899
|
}
|
|
12788
12900
|
},
|
|
12789
12901
|
output: {
|
|
@@ -16083,7 +16195,7 @@ function registerStatusApi(ctx, opts = {}) {
|
|
|
16083
16195
|
});
|
|
16084
16196
|
}
|
|
16085
16197
|
const { saveWeixinRoutes } = await import("./route-COOFLTpU.js").then((n) => n.c);
|
|
16086
|
-
const { findDirNameByCode } = await import("./profile-
|
|
16198
|
+
const { findDirNameByCode } = await import("./profile-DplLGGqo.js").then((n) => n.i);
|
|
16087
16199
|
for (const r of routes) if (findDirNameByCode(root, r.trajectory) === null) {
|
|
16088
16200
|
sendJson$2(res, 400, { error: `unknown trajectory: ${r.trajectory} (no such trajectory code in ${root})` });
|
|
16089
16201
|
return;
|
|
@@ -21066,7 +21178,7 @@ const MEDIA_MAX_BYTES = 20971520;
|
|
|
21066
21178
|
*/
|
|
21067
21179
|
async function resolveCccRootByAlias(ctx, alias) {
|
|
21068
21180
|
try {
|
|
21069
|
-
const { listCccs } = await import("./ccc-roots-
|
|
21181
|
+
const { listCccs } = await import("./ccc-roots-rwgzt_0F.js").then((n) => n.a);
|
|
21070
21182
|
const entries = await listCccs(ctx);
|
|
21071
21183
|
const byName = entries.find((e) => e.name === alias);
|
|
21072
21184
|
if (byName) return byName.root;
|
|
@@ -21134,7 +21246,7 @@ async function resolveInboundTarget(ctx, input) {
|
|
|
21134
21246
|
});
|
|
21135
21247
|
return null;
|
|
21136
21248
|
}
|
|
21137
|
-
const { findDirNameByCode } = await import("./profile-
|
|
21249
|
+
const { findDirNameByCode } = await import("./profile-DplLGGqo.js").then((n) => n.i);
|
|
21138
21250
|
if (findDirNameByCode(root, target.role) === null) {
|
|
21139
21251
|
const detail = `目标 CCC "${target.ccc}" 内没有编码为 "${target.role}" 的认知轨迹`;
|
|
21140
21252
|
console.error(`[serenity-hooks] ✗ human-channel: ${detail}(account=${input.account} user=${input.user})—— 该消息**未投递**,请改订阅表里的目标编码`);
|
|
@@ -21946,7 +22058,7 @@ function syncHumanChannel(ctx) {
|
|
|
21946
22058
|
(async () => {
|
|
21947
22059
|
try {
|
|
21948
22060
|
stopMachineLoops();
|
|
21949
|
-
const { listCccs } = await import("./ccc-roots-
|
|
22061
|
+
const { listCccs } = await import("./ccc-roots-rwgzt_0F.js").then((n) => n.a);
|
|
21950
22062
|
for (const entry of await listCccs(ctx)) syncCccBridge(ctx, entry.root);
|
|
21951
22063
|
} catch {}
|
|
21952
22064
|
})();
|
|
@@ -22210,7 +22322,7 @@ function matchCcc(input, candidates) {
|
|
|
22210
22322
|
}
|
|
22211
22323
|
/** 组装候选列表(`ccc-roots.listCccs` 投影 + `.serenity` 名;动态 import 保持本模块静态依赖轻量) */
|
|
22212
22324
|
async function collectCandidates(ctx) {
|
|
22213
|
-
const { listCccs } = await import("./ccc-roots-
|
|
22325
|
+
const { listCccs } = await import("./ccc-roots-rwgzt_0F.js").then((n) => n.a);
|
|
22214
22326
|
const entries = await listCccs(ctx, { defaultRoot: process.cwd() });
|
|
22215
22327
|
const seen = /* @__PURE__ */ new Set();
|
|
22216
22328
|
const out = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as cccRootForCwd } from "./ccc-roots-
|
|
2
|
-
import { T as parseTrajectoryCode, b as getLastActiveSessionInfo, k as sessionEvents, y as getActiveSessionInfo } from "./profile-
|
|
1
|
+
import { r as cccRootForCwd } from "./ccc-roots-rwgzt_0F.js";
|
|
2
|
+
import { T as parseTrajectoryCode, b as getLastActiveSessionInfo, k as sessionEvents, y as getActiveSessionInfo } from "./profile-DplLGGqo.js";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
5
5
|
//#region src/trajectory/bound.ts
|
|
@@ -50,6 +50,7 @@ function fromDomainRecord(rec) {
|
|
|
50
50
|
action: rec.action ?? "activate",
|
|
51
51
|
at: typeof rec.at === "number" ? rec.at : 0,
|
|
52
52
|
...rec.note ? { note: rec.note } : {},
|
|
53
|
+
...rec.createdAsUser === true ? { createdAsUser: true } : {},
|
|
53
54
|
...rec.supersededAt !== void 0 ? { supersededAt: rec.supersededAt } : {}
|
|
54
55
|
};
|
|
55
56
|
}
|
|
@@ -62,6 +63,7 @@ function toDomainRecord(rec) {
|
|
|
62
63
|
action: rec.action,
|
|
63
64
|
at: rec.at,
|
|
64
65
|
...rec.note ? { note: rec.note } : {},
|
|
66
|
+
...rec.createdAsUser === true ? { createdAsUser: true } : {},
|
|
65
67
|
...rec.supersededAt !== void 0 ? { supersededAt: rec.supersededAt } : {}
|
|
66
68
|
};
|
|
67
69
|
}
|
|
@@ -394,7 +396,8 @@ function appendBound(session, action, rec) {
|
|
|
394
396
|
...rec.sessionId ? { sessionId: rec.sessionId } : {},
|
|
395
397
|
action,
|
|
396
398
|
at: Date.now(),
|
|
397
|
-
...rec.note ? { note: rec.note } : {}
|
|
399
|
+
...rec.note ? { note: rec.note } : {},
|
|
400
|
+
...rec.createdAsUser === true ? { createdAsUser: true } : {}
|
|
398
401
|
};
|
|
399
402
|
if (domainStore?.available) domainStore.put(id, toDomainRecord(record)).catch(() => {});
|
|
400
403
|
if (!path) return domainStore?.available === true;
|
|
@@ -352,6 +352,19 @@ function parseTrajectoryCode(dirName) {
|
|
|
352
352
|
return code === "" ? null : code;
|
|
353
353
|
}
|
|
354
354
|
/**
|
|
355
|
+
* 从目录名取**可读描述**(编码之后那一段;没有就返回空串)。
|
|
356
|
+
*
|
|
357
|
+
* 用途:给"模拟用户开场白"当标签(D171)。判据 = 与 {@link parseTrajectoryCode} **互逆、同源**:
|
|
358
|
+
* 剥日期前缀 → 第一段是编码 → 其后(去掉前导 `--`)全是描述。
|
|
359
|
+
* ⚠️ 描述里**可以**含 `--`(只有编码不许)⇒ 这里必须取"第一段之后整串",不能 split 再取第二段。
|
|
360
|
+
*/
|
|
361
|
+
function trajectoryDescOf(dirName) {
|
|
362
|
+
if (!DIR_DATE_PREFIX_RE.test(dirName)) return "";
|
|
363
|
+
const rest = dirName.replace(DIR_DATE_PREFIX_RE, "");
|
|
364
|
+
const sep = rest.indexOf("--");
|
|
365
|
+
return sep === -1 ? "" : rest.slice(sep + 2).trim();
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
355
368
|
* 展示用会话 ID(`list` 面板 / 绑定记录的 `sessionId` 字段)。
|
|
356
369
|
*
|
|
357
370
|
* 🔴 2026-10-19 起**编码即 ID**,不再只认 `S###` —— 旧实现只匹配 `--S(\d{3,})--`,
|
|
@@ -1095,4 +1108,4 @@ function isTrajectoryConstrained(root, sessionId) {
|
|
|
1095
1108
|
return trajectoryConstraintForSession(root, sessionId) !== null;
|
|
1096
1109
|
}
|
|
1097
1110
|
//#endregion
|
|
1098
|
-
export { sessionsRoot as A,
|
|
1111
|
+
export { sessionsRoot as A, localFileStamp as B, namingTitleFor as C, readTrajectoryUid as D, readActiveSessionMd as E, useSession as F, localIdStamp as H, TRAJECTORY_FILENAME as I, TRAJECTORY_LEGACY_FILENAMES as L, showSession as M, summarize as N, resolveSessionByTitle as O, trajectoryDescOf as P, readTrajectoryFile as R, listSessions as S, parseTrajectoryCode as T, localHuman as V, extractSessionMdPathFromText as _, readTrajectoryConstraintAt as a, getLastActiveSessionInfo as b, registerTrajectorySession as c, COGNITIVE_TRAJECTORY_ACTIONS as d, DEFAULT_SESSION_SCOPE as f, createSession as g, clearActiveSessionInfo as h, profile_exports as i, setActiveSessionInfo as j, sessionEvents as k, trajectoryDirNameForSession as l, archiveSession as m, isTrajectoryConstrained as n, readTrajectoryConstraintByCode as o, UID_FILENAME as p, listTrajectoryConstraints as r, trajectoryConstraintForSession as s, TRAJECTORY_CONSTRAINT_FILENAME as t, unregisterTrajectorySession as u, findSession as v, parseSessionContextFromEvents as w, listActiveTrajectories as x, getActiveSessionInfo as y, isoLocal as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { f as hostSettings } from "./ccc-roots-
|
|
1
|
+
import { f as hostSettings } from "./ccc-roots-rwgzt_0F.js";
|
|
2
2
|
import { _ as resolveInside, g as readUtf8 } from "./ccc-CyYJL4F2.js";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
@@ -32,6 +32,8 @@ interface SessionBoundRecord {
|
|
|
32
32
|
action: SessionBoundAction;
|
|
33
33
|
at: number;
|
|
34
34
|
note?: string;
|
|
35
|
+
/** 🆕 ACC 以"用户开场白"形态建的载体(判决 D171)。**布尔事实**,不从 `note` 文案推。 */
|
|
36
|
+
createdAsUser?: boolean;
|
|
35
37
|
/**
|
|
36
38
|
* **(b) 已被取代标记**(S142 §0y,所有者 2026-09-18 裁「b 做」)。
|
|
37
39
|
*
|
|
@@ -166,5 +168,6 @@ export declare function appendBound(session: unknown, action: SessionBoundAction
|
|
|
166
168
|
mdPath: string;
|
|
167
169
|
sessionId?: string;
|
|
168
170
|
note?: string;
|
|
171
|
+
createdAsUser?: boolean;
|
|
169
172
|
}): boolean;
|
|
170
173
|
export {};
|
package/lib/trajectory/core.d.ts
CHANGED
|
@@ -109,6 +109,14 @@ export declare function isValidTrajectoryCode(code: string): boolean;
|
|
|
109
109
|
* @returns 编码;目录名不带日期前缀(非本工具建的 / 损坏)→ `null`
|
|
110
110
|
*/
|
|
111
111
|
export declare function parseTrajectoryCode(dirName: string): string | null;
|
|
112
|
+
/**
|
|
113
|
+
* 从目录名取**可读描述**(编码之后那一段;没有就返回空串)。
|
|
114
|
+
*
|
|
115
|
+
* 用途:给"模拟用户开场白"当标签(D171)。判据 = 与 {@link parseTrajectoryCode} **互逆、同源**:
|
|
116
|
+
* 剥日期前缀 → 第一段是编码 → 其后(去掉前导 `--`)全是描述。
|
|
117
|
+
* ⚠️ 描述里**可以**含 `--`(只有编码不许)⇒ 这里必须取"第一段之后整串",不能 split 再取第二段。
|
|
118
|
+
*/
|
|
119
|
+
export declare function trajectoryDescOf(dirName: string): string;
|
|
112
120
|
/**
|
|
113
121
|
* UID 的声明文件名(**固定名、住在轨迹目录内**)。
|
|
114
122
|
*
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* trajectory/user-carrier.ts — **造一条与"用户人工创建"基本一致的 dsh 会话载体**(判决 D171,owner 2026-10-20 裁 B)
|
|
3
|
+
*
|
|
4
|
+
* ## 这个文件解决什么(白话)
|
|
5
|
+
*
|
|
6
|
+
* `send-now` 在目标没有活跃会话时会**就地建一条**。它一直能建、也能挂工作区,
|
|
7
|
+
* 但建出来的东西与用户在 UI 里新建的那条**在宿主眼里不是同一种东西**:
|
|
8
|
+
*
|
|
9
|
+
* | 宿主投影 | 用户建 | 我们自建(修前实测) |
|
|
10
|
+
* |---|---|---|
|
|
11
|
+
* | `title` | 自动生成 | **永远 `null`** |
|
|
12
|
+
* | `titleInput.count` | ≥1 | **0** |
|
|
13
|
+
* | 假首轮(对齐声明 + EAP) | 注入 | **被自家递归守卫挡掉** |
|
|
14
|
+
*
|
|
15
|
+
* ## 🔴 根因(读宿主源码,不是推断)
|
|
16
|
+
*
|
|
17
|
+
* `dsh-session-title` 的 `sessionTitleUserMessageOf()` **第一行**就是:
|
|
18
|
+
*
|
|
19
|
+
* ```js
|
|
20
|
+
* if (event.type !== "user/message" || event.data.source.kind !== "user") return void 0
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* 而 ACC 投递的消息一律是 `{ kind: 'plugin:dsh-serenity-hooks' }`(`kernel/message-source.ts`)
|
|
24
|
+
* ⇒ **宿主从头到尾不把它当"有真人说过话"的会话** ⇒ 自动命名不触发、`titleInput` 恒 0。
|
|
25
|
+
*
|
|
26
|
+
* ## owner 的裁决 = B:**模拟一个用户开场白**
|
|
27
|
+
*
|
|
28
|
+
* `MessageSourceMap` 里 `user: { kind: 'user' }`,而 `UserMessage.source` 是**任意**
|
|
29
|
+
* `MessageSource` ⇒ `createUserMessage({ content, source: { kind: 'user' } })` **类型合法、
|
|
30
|
+
* 零改 DSH**(D4 仍成立)。
|
|
31
|
+
*
|
|
32
|
+
* ## 🔴 这是一次**明知故犯的伪造**,代价写在这里,不许悄悄付
|
|
33
|
+
*
|
|
34
|
+
* 1. **伪造用户身份**:与 D160「不再造历史」方向相反。范围**仅限**"载体开场白"这一条消息,
|
|
35
|
+
* 且正文**逐字自证**是模拟的({@link CARRIER_OPENING_MARK})⇒ 将来翻日志的人一眼能看出。
|
|
36
|
+
* 2. **污染所有者语料**:`session-corpus` 的"所有者发言"判据**必须**排除这条
|
|
37
|
+
* (判据 = 正文含 {@link CARRIER_OPENING_MARK})⇒ 否则统计"owner 说过什么"会算进一句
|
|
38
|
+
* 机器写的开场白。**这一条是同批改动,不是待办。**
|
|
39
|
+
* 3. **与假首轮的先后**:开场白必须让假首轮先注入(同一次 `agent/inbox/inserted` 里
|
|
40
|
+
* prepend 天然排在真实消息之前),否则 `hasUserMessageHistory` 会把假首轮挡掉。
|
|
41
|
+
* ⇒ 单测钉死顺序,不靠"应该会"。
|
|
42
|
+
*
|
|
43
|
+
* ## 归属(D23)
|
|
44
|
+
* 机制在 ACC(怎么建、建什么形状);**内容归 CCC**(开场白正文由调用方给)。
|
|
45
|
+
*
|
|
46
|
+
* ## 与 `trajectory/carrier.ts` 的关系
|
|
47
|
+
* 🔴 **两个文件、两件事**,名字刻意区分:`carrier.ts` 回答"**这条载体跑完没有**"(等待空闲/销毁竞速);
|
|
48
|
+
* 本文件回答"**怎么造一条载体**"。合在一起会让两条互不相关的依赖链卷成一团。
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* 模拟开场白的**自证标记**(逐字)。
|
|
52
|
+
*
|
|
53
|
+
* 🔴 三个用途,缺一不可:
|
|
54
|
+
* ① 人类翻日志时能一眼看出"这不是真主说的";
|
|
55
|
+
* ② `session-corpus` 用它**排除**语料(不污染"所有者发言");
|
|
56
|
+
* ③ 单测反向钉住:真实用户发言里**不会**出现这串 ⇒ 断言"语料里 0 条含它"才有意义。
|
|
57
|
+
*/
|
|
58
|
+
export declare const CARRIER_OPENING_MARK = "[ACC \u4EE3\u7528\u6237\u5F00\u573A]";
|
|
59
|
+
/**
|
|
60
|
+
* 构造模拟开场白的正文。
|
|
61
|
+
*
|
|
62
|
+
* ⚠️ **不含版本号/日期/模型名**(D159:任务书里不得写死版本号 ⇒ 写与版本无关的判据)。
|
|
63
|
+
* 正文只描述"这是谁、要接着做什么",不描述"哪一版干的"。
|
|
64
|
+
*
|
|
65
|
+
* @param code 轨迹编码(`S###` 或自定义)
|
|
66
|
+
* @param desc 轨迹目录名里那段可读描述(**人起的**,不另造第二真相源)
|
|
67
|
+
* @returns 一条自证是模拟的开场白正文
|
|
68
|
+
*/
|
|
69
|
+
export declare function buildCarrierOpening(code: string, desc: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* 投一条"用户形态"的消息进目标 agent(**B 的核心动作**)。
|
|
72
|
+
*
|
|
73
|
+
* 🔴 为什么单独成函数而不是就地写:这是**全仓唯一**允许 `kind:'user'` 的地方。
|
|
74
|
+
* 集中在一处,将来若要收紧(或 owner 改主意回 A),只有一个点要改。
|
|
75
|
+
*
|
|
76
|
+
* @param agent 目标 agent(须有 `followup`)
|
|
77
|
+
* @param text 开场白正文(**必须**由 {@link buildCarrierOpening} 产出,以带上自证标记)
|
|
78
|
+
* @returns 投递是否成功(失败返回 false,由调用方决定降级 —— 不抛)
|
|
79
|
+
*/
|
|
80
|
+
export declare function deliverCarrierOpening(agent: {
|
|
81
|
+
followup?: (msg: unknown) => void;
|
|
82
|
+
}, text: string): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shgroup/dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.76.0",
|
|
4
4
|
"description": "宁静号 ACC harness(Native Cordis 插件)——给 DeepSeek Harness 装一个「AI 工作区」:14 个工具(container_fs/cognitive_trajectory/dashboard/container_git/msm/praxis/ontology/serenity-skill-creator/cheap-worker/localstore/container_admin;另三个 im-bridge/acc-diag/diagram 按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫/对外输出守卫)+ 认知轨迹日志与原地重建 + 网页登录入口/IM 桥/认知轨迹唤醒注册表。轨迹声明 = 轨迹目录下的 trajectory.json(约束面 + 旧标识 uid + CRO 机器绑定 cro.host;旧名 trajectory-constraint.json / skiff.json 仍在读取族里);轨迹提示词 = 轨迹目录下的 PROMPT.md(一条轨迹「是谁、按什么章程工作」,所有轨迹通用,追加在容器层与质量层之后,不替换它们)。适配 DSH 0.1.7-rc.1 / 0.2.0-rc.1 / 0.2.1-rc.1(三档)。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|