@akasha-book/sleep 1.10.22 → 1.10.31
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 -6
- package/cordis.patch.yml +3 -0
- package/lib/index.js +125 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# @akasha-book/sleep
|
|
2
|
-
|
|
3
|
-
> 2026-10-
|
|
4
|
-
|
|
2
|
+
|
|
3
|
+
> 2026-10-18 压缩后重投(2026-10-18):监听 `compaction/end` 成功后置 `pendingPostCompactWake`,下一回合由 `akasha:post-compact-wake` 条子(order = pulseOrder+4)重投完整起床包(复用 `buildWakeNote`,一次性、每行 ≤80);失败压缩不计;`postCompactWake:false` 可关。来源:拆 Prime Agent 的 Continual Harness(digest 在 compaction head 也投递)。**版本以本包 `package.json` 为准**(本文件不复述,避免文档漂移)。
|
|
4
|
+
>
|
|
5
|
+
> 2026-10-18 并行会话感知(1.10.26-h1):在上一版(独立审核 6 条 P0)基础上再补自排除——`exclude` 增加 `curSid`(事件派生的会话 id,在 retarget 覆盖前捕获),修回合边界自指;其余同上一版:摘要先按 Markdown 结构切段(标题/列表/有序项/✅)再从非首句找「完成/下一步」,排除负例;meta 键统一归一 + 按 source 目录过滤子代理;指针改全 id;`order=131`;注入 `safeInject(..., {untrusted:true})`。
|
|
6
|
+
>
|
|
7
|
+
> 2026-10-18 并行会话感知(1.10.23-h1):新增 `akasha:parallel` runtime context 条——读 `akasha/data/session.jsonl` 的 conclusion 段(独立小索引,不写会话层),把其他主会话最近 60 分钟内的最新结论压成「做了什么 / 完成 / 下一步」三行,每条带 `seq` 指针(深查用 `session_event_read`,不做全局检索);子代理不进;无条目静默。
|
|
8
|
+
>
|
|
9
|
+
> 2026-10-17 本地兼容修复(1.10.22-h2):runtime context 在无内容或降级时统一返回空字符串,避免 Harness 提示词渲染出现 null/indexOf 错误;纯函数和内部状态的 null 含义保持原样。
|
|
10
|
+
|
|
5
11
|
|
|
6
12
|
阿卡夏之书睡眠器 —— **调度与注入**(蒸馏逻辑归核心库 `<AKASHA_DIR>/sleep.mjs`;手动触发 `node akasha.mjs sleep [--dry]` 与之共用同一水位线)。
|
|
7
13
|
|
|
@@ -9,7 +15,7 @@
|
|
|
9
15
|
|
|
10
16
|
- **会话身份隔离(第五轮 · V02)**:C3 与指代检索仅按完整宿主 ID 精确匹配;当前会话无 intent 时保持静默。`session-1`、`1`、`session-session-1` 不互作别名。此前的单前缀兜底也会误读新版完整 ID 记录,现已移除。33037b3 中无身份格式标记但保留完整 ID 的记录仍可精确读取;更早被剥前缀的记录需要人工核对原会话档案后重索引,不自动猜归属或迁移生产库。
|
|
11
17
|
- **v1.10.18-h1(2026-10-17,batch14 · H4-E 睡眠 TEMP 陷阱目录泄漏修复;产源自清—四件测试套件,**未安装、未重启**)**:四套(gate / preflight / route / stateful)在**模块顶层** `mkdtempSync('<名>-default-trap-')` 建陷阱目录、**从无清理** ⇒ 每跑一轮就在 `%TEMP%` 留一个空目录(batch13 清单实测:存量 255、单日 +134)。修法各一行:三件(gate / preflight / stateful)补 `process.on('exit')` 兜底 `rmSync`;route **已有** exit 钩子但 `DEFAULT_TRAP` 从未 push 进 `cleanupDirs` ⇒ 补 push。
|
|
12
|
-
- **两态实测**(`runs/audit-1016-batch14/seg-sleep/landing/logs/regression-run.json
|
|
18
|
+
- **两态实测**(`runs/audit-1016-batch14/seg-sleep/landing/logs/regression-run.json`):`<LOCAL_PATH>` 跑前 255 → 跑后 255、五套逐套即时比对新增 0;**负对照**(去补丁副本,`logs/neg-control.json`)四件各 +1 ⇒ 补丁是「零残余」的有效因子。真家目录(`~/.akasha/logs/` 的 `hooks.jsonl` + `sleep-state.json`)bytes/lines/mtime/sha 四属性**跑前=跑后**;`akasha/test.mjs` 276-0、`node --check` ×7 全绿。
|
|
13
19
|
- **v1.10.17-h1(2026-10-17,batch10 · 处置 batch8 复核 `VERIFY-S4` §5 的三条低级别;改动仅 `route.test.mjs` 一件,**未安装、未重启**)**:
|
|
14
20
|
- **F-S4-2(H+++ "半牙" ⇒ 真增量)**:H+++ 原有三条断言(`{status:3}` / `{code:'ETIMEDOUT'}` / `{code:'ETIMEDOUT',signal:'SIGTERM'}`)与**集成路重复**(分别由 H-5「exit 3 ⇒ raw 3」与 H-3「超时 ⇒ raw 'ETIMEDOUT';真实形状同时带 code+signal」驱动)⇒ 删去,换三条**集成路产不出的类型守卫格**:`{status:0}`(合法退出码,防真假陷阱)/ `{status:'3'}`(非数字 status)/ `{code:42,signal:'SIGKILL'}`(非字符串 code ⇒ 落 signal 格)。
|
|
15
21
|
- **两态 × 四变异实测**(`runs/audit-1016-batch10/seg-sleep/landing/tools/probe-F-S4-2-teeth.mjs`):旧套件对「真假陷阱 / 松类型 status / 松类型 code」三个变异**全绿(抓不到)**;新套件分别在 **421 / 422 / 423** 行当场红。而「signal 提前于 code」的变异**两版都由 H-3(344 行)**抓住 ⇒ 删掉的三条不承重、新加的三条各有独立分辨力。
|
|
@@ -76,7 +82,7 @@
|
|
|
76
82
|
- 齿:阈值**放宽 30 s**(`6*3600_000 + 30_000`,一条很现实的"容差"改动)⇒ **只红 6h00m 格**(`:257`);5h59m / 6h01m 不变(thr5 仍红 `:245`;把 6h00m 格摘掉后 thr7 仍红 6h01m `:259`)。
|
|
77
83
|
- ⚠ 顺序登记:新增格排在 6h01m **之前** ⇒ thr7 变异的**首个**红点由 6h01m 前移到 6h00m(两格对 thr7 都红,先后只由断言顺序决定)。
|
|
78
84
|
- **6.2 · 测试侧两份 6h 常量 ⇒ 合并成一份**(`SIX_H` 提到 `refStamp` 前,refStamp 与 C2b 格偏移共用)。**判断:能安全合并** —— ① 格级探针是**外部**脚本(直接 import 产品件、自造偏移),不读本常量;② 套件的齿来自 `RE_FRESH` / `RE_DATED` 两条语义锚定的正则,**不来自常量** ⇒ 常量改错时格点跟着常量一起移、移完那格落在**另一侧**边界必红(实测 5h ⇒ `:257` 红、7h ⇒ `:245` 红,不是静默绿);反之留两份的代价是**误导性红点**(只改 refStamp 时红在 6h01m 格、文案却指向"参考实现反算",不指向真因=常量漂移)。
|
|
79
|
-
- **变异盘**:`runs/audit-1016-batch18/seg-sleep/landing/logs/b18-plates.json`(10 格;派生副本在 `landing/derived/`,每格**只打一处**变异,记 rc / 红点行 / 断言原文)。**回归**:`node --check` ×9 · 包内 5 套 rc0 · `akasha/test.mjs` 276-0(沙箱副本带 `dist/akasha-oss` 兄弟仓)· `sleep-state.json` 四字段跑前=跑后 ·
|
|
85
|
+
- **变异盘**:`runs/audit-1016-batch18/seg-sleep/landing/logs/b18-plates.json`(10 格;派生副本在 `landing/derived/`,每格**只打一处**变异,记 rc / 红点行 / 断言原文)。**回归**:`node --check` ×9 · 包内 5 套 rc0 · `akasha/test.mjs` 276-0(沙箱副本带 `dist/akasha-oss` 兄弟仓)· `sleep-state.json` 四字段跑前=跑后 · `<LOCAL_PATH>` 九类前缀 0→0。
|
|
80
86
|
- **v1.10.21-h1(2026-10-17 batch17 · **只补测试齿**:拆严格正则 + 6h 边界两格;`lib/` **一字未动**、未安装、未重启)**:`route.test.mjs` 的格式正则原把日期写成**可选**(`(?:\d{2}-\d{2} )?`)⇒ 它自己**不带齿**("恒带日期"也能过),真正钉住「新鲜态不许带日期」的只剩 refStamp 等式,红点文案还看不出意图(VERIFY-S8 §7 O-1)。现**拆两条严格正则**:`RE_FRESH`(新鲜 ⇒ 括号内**无**日期)/ `RE_DATED`(跨日 ⇒ **有**日期),并各配一条「另一式必不匹配」的反向齿。
|
|
81
87
|
- **补 6h 阈值边界两格**(VERIFY-S8 §7 O-2;此前 C2 只测 26h):`5h59m` ⇒ **无**日期、`6h01m` ⇒ **有**日期。方向以源码实际比较符为准 —— `stampOf` 是 `Date.now() - ms < 6 * 3600_000 ? HH:MM : MM-DD HH:MM` ⇒ **≥6h 带日期**(**6h00m 整归带日期一侧**)。
|
|
82
88
|
- **变异验齿**(`runs/audit-1016-batch17/seg-sleep/landing/logs/b17-plates.json`):阈值改 **5h** ⇒ **只有** `5h59m` 格转红;改 **7h** ⇒ **只有** `6h01m` 格转红;「恒带日期」变异 ⇒ 新鲜格(含新反向齿)红。
|
|
@@ -86,7 +92,7 @@
|
|
|
86
92
|
- **时点仍看得见**:`lag-long` 满 **80** 字、尾 `…`,时点仍在**前缀括号内**(行尾会被 clip 先吃掉);跨日时前缀由 14 → 31 字 ⇒ 该格可显示明细 55 → **49 字**(新鲜态不变,仍是 55;属登记代价,不修)。
|
|
87
93
|
- **断言同批放宽 + 加齿**(`route.test.mjs`):格式正则 `检于 \d{2}:\d{2}` → `检于 (?:\d{2}-\d{2} )?\d{2}:\d{2}`;原「显示时点=检查时点」改为**参考实现反算**(测试侧独立实现同一规则);新增 **C2 段**要求跨日**必须带日期**。负控三条实测:① `checkedAt` 再挪一天 ⇒ 期望串不同(断言必红);② 旧形态(只有 `HH:MM`)不匹配;③ 修前发布件在跨日格上严格日期正则 = **false**。
|
|
88
94
|
- 已知边界(如实):6h 内的时点不带日期 —— 该窗口内「今天 HH:MM」不会与「昨天同 HH:MM」同形(要混淆须错位 ≥18h),故不补日期。
|
|
89
|
-
- **v1.10.19(2026-10-17 batch15)**:① 测试件残留兜底两件——`gate.test.mjs` 的 `gate-reg-*`(`mkFix`)纳入 `cleanupDirs` + `exit` 钩子(原只走 happy path,失败/早退即留,化石 3 个:10-15);`selftest.test.mjs` 退出时补一次「非空则留」的 `rmdir
|
|
95
|
+
- **v1.10.19(2026-10-17 batch15)**:① 测试件残留兜底两件——`gate.test.mjs` 的 `gate-reg-*`(`mkFix`)纳入 `cleanupDirs` + `exit` 钩子(原只走 happy path,失败/早退即留,化石 3 个:10-15);`selftest.test.mjs` 退出时补一次「非空则留」的 `rmdir`(`<LOCAL_PATH>` 空容器此前常驻)。② 脉搏「⚠ 审核面滞后」行**附检查时点**`(检于 HH:MM)`——判定(`code`/`raw`/是否显示)与 60s 节流一律不动,只让"这结论是什么时候的"可见(消 VERIFY-A4 §5-O1 的显示面时序分歧:旧结果在 turn/end 驱动的窗口里与实跑 `exit 0` 分歧)。
|
|
90
96
|
- ⚠️ 注意:`ctx.on('tools/result')` 与 `ctx.on('agent/error')` 的监听是 v1.5 新增——宿主 Event 名以 `cordis_inspect_query`(host Event 目录)为准,两个事件均为 emit 语义(失败不打断宿主)。
|
|
91
97
|
|
|
92
98
|
## 打包 / 安装
|
package/cordis.patch.yml
CHANGED
package/lib/index.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// · 条子四(行为层,v1.10;2026-10-13 **按裁定重挂·默认关**):形态 B(无正文 + 无工具)检测 → 观测线 `idle-shape`;
|
|
9
9
|
// `idleResume:true` 时才自动续行(强信号=思维链尾部「好。」;冷却 + 限次;文案禁清单/打勾/句号收尾)
|
|
10
10
|
// · 降级:核心库不可用 → sleep-error 观测线 + 条子提示文案,不炸、不失活。
|
|
11
|
-
import { appendFileSync, closeSync, mkdirSync, openSync, readFileSync, readSync, statSync } from 'node:fs';
|
|
11
|
+
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, statSync } from 'node:fs';
|
|
12
12
|
import { execFileSync } from 'node:child_process';
|
|
13
13
|
import { createRequire } from 'node:module';
|
|
14
14
|
import { homedir } from 'node:os';
|
|
@@ -66,6 +66,33 @@ const DEFAULTS = {
|
|
|
66
66
|
reviewLagTimeoutMs: 5000
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
+
// ── 占位符守卫(2026-10-19 发布面 P0)──────────────────────────────
|
|
70
|
+
// OSS 的 `cordis.patch.yml` 用 `<AKASHA_DIR>` / `<LOCAL_PATH>` 作示例字面量;照抄不改时字面量
|
|
71
|
+
// **优先于** AKASHA_DIR 默认值 ⇒ 睡眠/注入/观测线静默指向不存在的库。这里明确抛错(fail closed)。
|
|
72
|
+
const PLACEHOLDER_TOKEN = /<[A-Za-z][A-Za-z0-9_]{2,}>/; // 大小写都认(审计 B)
|
|
73
|
+
/** 递归找配置里的未替换占位符(只认全大写尖括号 token,不误伤普通文本)。 */
|
|
74
|
+
export function findPlaceholders(value, path = 'config', depth = 0) {
|
|
75
|
+
if (depth > 8) return [];
|
|
76
|
+
if (typeof value === 'string') {
|
|
77
|
+
const m = value.match(PLACEHOLDER_TOKEN);
|
|
78
|
+
return m ? [{ field: path, token: m[0] }] : [];
|
|
79
|
+
}
|
|
80
|
+
if (Array.isArray(value)) return value.flatMap((v, i) => findPlaceholders(v, `${path}[${i}]`, depth + 1));
|
|
81
|
+
if (!value || typeof value !== 'object') return [];
|
|
82
|
+
return Object.entries(value).flatMap(([k, v]) => findPlaceholders(v, `${path}.${k}`, depth + 1));
|
|
83
|
+
}
|
|
84
|
+
export function assertNoPlaceholders(config) {
|
|
85
|
+
const hits = findPlaceholders(config);
|
|
86
|
+
if (!hits.length) return;
|
|
87
|
+
const fields = [...new Set(hits.map((h) => h.field))].join('、');
|
|
88
|
+
throw new Error(
|
|
89
|
+
`akasha-sleep: 配置里还有未替换的占位符 ${hits[0].token}(${fields})。` +
|
|
90
|
+
'请先把 cordis.patch.yml 里的 <AKASHA_DIR> / <LOCAL_PATH> 改成你的实际路径;' +
|
|
91
|
+
'或删掉这些字段,改用 AKASHA_DIR 环境变量。' +
|
|
92
|
+
'(宁可启动失败,也不静默降级——照抄占位符会让睡眠/注入指向不存在的库。)'
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
69
96
|
/** 唤醒条是否值得推(有内容才说话):无睡眠记录 / 有待办 / 审计有警告。 */
|
|
70
97
|
export function isWakeNoteworthy(k) {
|
|
71
98
|
return !k.sleep || (k.inbox?.totalItems ?? 0) > 0 || (k.review?.findings ?? []).some((f) => f.level === 'warn');
|
|
@@ -152,7 +179,13 @@ export function latestIntentGist(text, session) {
|
|
|
152
179
|
if (exact) return exact;
|
|
153
180
|
const norm = (v) => String(v ?? '').replace(/^session-/, '');
|
|
154
181
|
const nw = norm(want);
|
|
155
|
-
|
|
182
|
+
// 2026-10-19 修(OSS review5-identity 2 条单元红;独立审查裁决=真 fail-open,severity 中):
|
|
183
|
+
// 原归一兜底对**任意** want 生效 ⇒ `'1'` 会匹配到 `'session-1'`、`'session-other'` 之类,
|
|
184
|
+
// 把一个不存在的身份"猜"成别的会话(跨会话别名越权)。真库 52046 行全是 UUID 形态,
|
|
185
|
+
// ⇒ 门控到 UUID:只有 `session-<uuid>` / `<uuid>` 这一对等价形态互认,其余一律精确匹配。
|
|
186
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
187
|
+
if (!nw || !UUID_RE.test(nw)) return null;
|
|
188
|
+
return pick((r) => { const rn = norm(r.session); return UUID_RE.test(rn) && rn === nw; }) ?? null;
|
|
156
189
|
}
|
|
157
190
|
|
|
158
191
|
/** 门档触发判据(2026-10-15 落地;**顶层导出**,供自测做等价对照——与 tailReadText/latestIntentGist 同规矩)。
|
|
@@ -219,13 +252,14 @@ export function apply(ctx, config = {}) {
|
|
|
219
252
|
try { (ctx.logger?.info ?? (() => {}))('sleep: abOff=true(A/B 关闭臂)——本插件不注册任何面'); } catch { /* 静默 */ }
|
|
220
253
|
return;
|
|
221
254
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
255
|
+
assertNoPlaceholders(config);
|
|
256
|
+
const cfg = { ...DEFAULTS, ...config };
|
|
257
|
+
// Empty optional prompts must use a string at the Harness API boundary.
|
|
258
|
+
const registerContext = ({ text, ...entry }) => ctx.systemPrompt.context({
|
|
259
|
+
...entry,
|
|
260
|
+
text: typeof text === 'function'
|
|
261
|
+
? (context) => text(context) ?? ''
|
|
262
|
+
: text ?? '',
|
|
229
263
|
});
|
|
230
264
|
const require_ = createRequire(import.meta.url);
|
|
231
265
|
const reportDir = join(cfg.akashaDir, 'logs');
|
|
@@ -509,11 +543,34 @@ export function apply(ctx, config = {}) {
|
|
|
509
543
|
// ⇒ 改工具输出通道(换 stderr / 套一层 wrapper 吞掉 stdout)=改契约,须同批改本判据;
|
|
510
544
|
// 未选「判据放宽到认 stderr 标记」的理由见 batch7 landing README §2-D3:那会为一条**没写下来的
|
|
511
545
|
// 契约**增加新的判据面(stderr 文本匹配),且任何在 stderr 打印该标记的工具都会被算成「有滞后」。
|
|
546
|
+
// D3(2026-10-19 发布面 P1):检查器脚本的**布局**有两种——
|
|
547
|
+
// OSS 仓 / 发布件=扁平 `<akashaDir>/tools-review-lag.mjs`;活树(本仓)=`<akashaDir>/tools/review-lag.mjs`。
|
|
548
|
+
// 旧实现只认后者 ⇒ 装出来的 OSS 包里该路径不存在:node 起得来、在模块解析阶段失败(exit 1、stdout 空)
|
|
549
|
+
// ⇒ 观测线只剩一行无法解读的 code:-1,连"脚本没装"还是"脚本崩了"都分不出。
|
|
550
|
+
// ⇒ 候选链(先扁平、后嵌套)。都不在时落**一行明确的 skip**(kind:'review-lag-skip',带候选清单);
|
|
551
|
+
// 随后仍按旧路径真跑一次——不是拖延,而是为了 raw 记**真因**(route.test.mjs 已把"raw=真实退出码"
|
|
552
|
+
// 钉成契约:伪造 raw 比多跑一次更糟)。
|
|
553
|
+
const reviewLagScripts = (akashaDir) => [
|
|
554
|
+
join(akashaDir, 'tools-review-lag.mjs'), // OSS / 发布件(扁平命名)
|
|
555
|
+
join(akashaDir, 'tools', 'review-lag.mjs'), // 活树(tools/ 目录)
|
|
556
|
+
];
|
|
557
|
+
let reviewLagSkipLogged = null; // skip 行去重:同一候选清单只落一次(不刷屏)
|
|
558
|
+
const noteReviewLagSkip = (candidates) => {
|
|
559
|
+
try {
|
|
560
|
+
const key = candidates.join('|');
|
|
561
|
+
if (key === reviewLagSkipLogged) return;
|
|
562
|
+
reviewLagSkipLogged = key;
|
|
563
|
+
log({ kind: 'review-lag-skip', candidates, why: 'review-lag 脚本不在候选链上(两种布局都没有该文件)' });
|
|
564
|
+
} catch { /* 静默:观测线写不了不拖垮回合 */ }
|
|
565
|
+
};
|
|
512
566
|
const runReviewLag = () => {
|
|
513
567
|
try {
|
|
514
568
|
if (Date.now() - reviewLagState.at < REVIEW_LAG_INTERVAL) return;
|
|
515
569
|
reviewLagState.at = Date.now();
|
|
516
|
-
|
|
570
|
+
const candidates = reviewLagScripts(cfg.akashaDir);
|
|
571
|
+
const scriptPath = candidates.find((p) => existsSync(p));
|
|
572
|
+
if (!scriptPath) noteReviewLagSkip(candidates); // 明确 skip(不再只剩一行 code:-1)
|
|
573
|
+
execFileSync(process.execPath, [scriptPath || candidates[1]],
|
|
517
574
|
{
|
|
518
575
|
// F8(batch8):超时值改 cfg 可注入(默认 5000)——测试实等 5 s 会永久拖慢回归。
|
|
519
576
|
encoding: 'utf8', timeout: cfg.reviewLagTimeoutMs || 5000, stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -561,6 +618,9 @@ export function apply(ctx, config = {}) {
|
|
|
561
618
|
else {
|
|
562
619
|
S().obs.compactions++;
|
|
563
620
|
S().obs.lastCompactionTurn = S().obs.turn; // 脆弱窗判据(压缩补偿行用)
|
|
621
|
+
// 压缩后重投(2026-10-18,拆 Prime Agent 的 digest@compaction-head 落地):
|
|
622
|
+
// 压缩只保话题、丢约定与库状态;下一回合由 `akasha:post-compact-wake` 条子重投完整起床包。
|
|
623
|
+
S().pendingPostCompactWake = { n: S().obs.compactions, at: Date.now() };
|
|
564
624
|
}
|
|
565
625
|
}
|
|
566
626
|
// 触发词路由(2026-10-11 解冻后新增,外部对照启发:灵枢的「触发词路由」):
|
|
@@ -603,6 +663,36 @@ export function apply(ctx, config = {}) {
|
|
|
603
663
|
}
|
|
604
664
|
});
|
|
605
665
|
|
|
666
|
+
// 并行会话感知(2026-10-18 v0):给当前会话一条「其他主会话在做什么」的内部反馈条。
|
|
667
|
+
// 用户口径:只读独立小索引(session.jsonl 的 conclusion 段),不写会话层;只送
|
|
668
|
+
// 「做了什么/完成/下一步」三行;每条带 seq 指针(深查用 session_event_read,不做全局检索);
|
|
669
|
+
// 60 分钟窗口;按 meta 的 source 目录过滤掉子代理(裸 uuid 目录);无条目静默。
|
|
670
|
+
registerContext({
|
|
671
|
+
name: 'akasha:parallel',
|
|
672
|
+
order: cfg.parallelOrder ?? 131,
|
|
673
|
+
text: (context) => {
|
|
674
|
+
const eventSid = curSid; // 上一个事件派生的会话 id(在 retarget 覆盖前取,补自排除)
|
|
675
|
+
retarget(renderSidOf(context));
|
|
676
|
+
try {
|
|
677
|
+
const sid = renderSidOf(context);
|
|
678
|
+
const sessionId = context?.session?.id ?? context?.agent?.session?.id;
|
|
679
|
+
const exclude = [sid, sessionId, eventSid].filter(Boolean);
|
|
680
|
+
if (exclude.length === 0) return null;
|
|
681
|
+
const p = require_(join(cfg.akashaDir, 'parallel.mjs'));
|
|
682
|
+
const r = p.collectParallel({
|
|
683
|
+
file: join(cfg.akashaDir, 'data', 'session.jsonl'),
|
|
684
|
+
metaFile: join(cfg.akashaDir, 'data', 'session-meta.json'),
|
|
685
|
+
exclude,
|
|
686
|
+
nowMs: Date.now(),
|
|
687
|
+
windowMinutes: 60,
|
|
688
|
+
limit: 2
|
|
689
|
+
});
|
|
690
|
+
const feed = p.renderParallelFeed(r);
|
|
691
|
+
return feed ? safeInject(feed, { untrusted: true }) : null;
|
|
692
|
+
} catch { return null; }
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
|
|
606
696
|
// 称呼行(2026-10-10 用户复盘「长会话中期称呼易漂移」):
|
|
607
697
|
// 规则躺在会话开头那坨注入(akasha:self)里,**执行时看不到** ⇒ 必然漂移。
|
|
608
698
|
// 修法=接进每回合必然经过的执行点:这条 runtime context 行每回合都出现,内容渲染自
|
|
@@ -960,6 +1050,31 @@ export function apply(ctx, config = {}) {
|
|
|
960
1050
|
});
|
|
961
1051
|
}
|
|
962
1052
|
|
|
1053
|
+
// 压缩后重投(2026-10-18;来源:拆 Prime Agent 的 Continual Harness —— 他们的 harness digest 在
|
|
1054
|
+
// session start / resume / **compaction head** 三处都投;我们原先只在新会话投,压缩后就只剩补偿提示行)。
|
|
1055
|
+
// 设计:一次性条子——压缩成功时置 `pendingPostCompactWake`,下一回合渲染完整起床包并清除标记。
|
|
1056
|
+
// 行宽:唤醒条每行 ≤80(同其他条子;多行本身允许,见 akasha:parallel)。
|
|
1057
|
+
// 成本:kit() 只在压缩后调一次(读六库),不是每回合。
|
|
1058
|
+
if (cfg.postCompactWake !== false) {
|
|
1059
|
+
registerContext({
|
|
1060
|
+
name: 'akasha:post-compact-wake',
|
|
1061
|
+
order: (cfg.pulseOrder ?? 132) + 4,
|
|
1062
|
+
text: (context) => {
|
|
1063
|
+
retarget(renderSidOf(context));
|
|
1064
|
+
try {
|
|
1065
|
+
const pw = S().pendingPostCompactWake;
|
|
1066
|
+
if (!pw) return null;
|
|
1067
|
+
S().pendingPostCompactWake = null; // 一次性:先清,无论成败都不重投
|
|
1068
|
+
const k = require_(join(cfg.akashaDir, 'lib.mjs')).kit();
|
|
1069
|
+
if (!isWakeNoteworthy(k)) return null;
|
|
1070
|
+
const lines = buildWakeNote(k).split('\n')
|
|
1071
|
+
.map((l) => (l.length <= 80 ? l : l.slice(0, 79) + '…'));
|
|
1072
|
+
return '[压缩后重投] 会话已压缩 ' + pw.n + ' 次(上下文边界),库状态重投:\n' + lines.join('\n');
|
|
1073
|
+
} catch { return null; }
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
|
|
963
1078
|
// 核心约定常驻行(2026-10-11 用户裁定):**防目标漂移**——压缩丢的是"我们怎么做事"(实测五条约定存活 0–21%),
|
|
964
1079
|
// 而每回合注入的称呼层 100% 存活 ⇒ 把核心约定也做成**常驻**。**库驱动**:渲染时读 canon 的
|
|
965
1080
|
// `canon-core-conventions` 当前版本的 `line` 字段 ⇒ **改约定=改条目**(不碰代码);读不到 ⇒ 内置兜底(永不为空)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akasha-book/sleep",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.31",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=18"
|
|
6
6
|
},
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
|
30
30
|
"url": "git+https://github.com/Ersith/akasha-book.git",
|
|
31
|
-
"directory": "
|
|
31
|
+
"directory": "plugins/akasha-sleep"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"test": "node selftest.test.mjs",
|