@akasha-book/sleep 1.5.4 → 1.6.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/README.md CHANGED
@@ -1,56 +1,29 @@
1
1
  # @akasha-book/sleep
2
2
 
3
- > 1.5.4 起新增**称呼行**(`akasha:address`,order 133):每回合 runtime context 注入「对用户称 Master;用户对你是『大肥鱼』」+ 执行点要求——
4
- > 成因见 `docs/observation-ledger.md` 与 `canon-address-drift-fix-20261010`:**规则躺在会话开头的注入里、执行点看不到 ⇒ 长会话中期必漂移**;
5
- > 修法=接进每回合必然经过的面。
3
+ 阿卡夏之书睡眠器 v1.5.5 —— **调度与注入**(蒸馏逻辑归核心库 `<AKASHA_DIR>/sleep.mjs`;手动触发 `node akasha.mjs sleep [--dry]` 与之共用同一水位线)。
6
4
 
7
- > 阿卡夏之书(Akasha Book)· 睡眠器插件
5
+ - **v1.5.5(2026-10-07 复查修复)**:移除死代码 `source==='compact'` 早退(官方 `agent/created` 的 source 只有 startup/resume;压缩信号是 session 事件 `compaction/*`);子代理守卫沿用官方 `header.origin/delegationDepth`(已核真实字段)。
8
6
 
9
- 阿卡夏之书睡眠器 v1.5.1 —— **调度与注入**(蒸馏逻辑归核心库 `../../core/sleep.mjs`;手动触发 `node akasha.mjs sleep [--dry]` 与之共用同一水位线)。
7
+ - **触发**:`agent/status → idle`,去抖 `minIntervalHours`(默认 6);另一路定时兜底 `ctx.interval`(`timerCheckMs`,默认 1h——timer 属混入服务,必须 `inject:['timer']` 才能访问 `ctx.interval`)。跳过也留痕(`sleep-skip`);首次激活即跑一次(`activate`)。
8
+ - **蒸馏(v1.4 起在核心库 `akasha\sleep.mjs`)**:`akasha\logs\hooks.jsonl` 增量(水位线 `processedLines`)→ turns / tools / errors / denials 统计 + 失败备注 + 待办(`buildTodos`:审计警告 → review;工具失败 / 门控拦截 / agent 错误 → 孤案候选);报告 `sleep-<date>.json`(**同日重复跑加时间戳后缀,不覆盖**);有待办时追加 `akasha\logs\inbox.jsonl`。
9
+ - **条子一(每回合)**:`systemPrompt.context`(`akasha:sleep`,order 130)——每个新回合的 runtime context 自动带上「最近一次睡眠」一行(含待办数;渲染自核心库)。
10
+ - **条子二(新会话·唤醒条)**:`agent/created` → 经 `agent.inject()` 把「起床包」摘要递进 next-step inbox(**不唤醒、不打断**;仅当 无睡眠记录 / 有待办 / 审计警告 才发;子代理与 compact 不打扰;消息 `source.kind = "akasha-wake"`)。
11
+ - **条子三(每回合·库脉搏 + 回查)**:`akasha:pulse`(order 132)——六库当前计数 + 最近写入(**写→可见通道**:任何会话 / 脚本写入库后,活跃会话下一回合即见);**v1.5 起**,窗口内(默认 30 分钟)有工具 / agent 失败时,追一行「回查提示」(错误钩子的注入级动作——只提示、不拦截;渲染幂等,同窗口重复渲染结果一致)。
12
+ - **降级(v1.4 切分)**:核心库不可用 → `sleep-error` 观测线 + 条子提示文案;不炸、不失活(插件不再内置蒸馏逻辑,拒绝双份实现)。
13
+ - 观测线:`sleep-armed` / `sleep-done` / `sleep-skip` / `sleep-error` / `wake-note` / `wake-note-error` / `wake-note-llm-error` / `sleep-report-error` / `sleep-state-error` / `sleep-inbox-error` 全部写进 `hooks.jsonl`(报告 / 状态 / inbox 三条由核心库发出)。
14
+ - 自测:`node selftest.mjs`(纯函数直测 `../../core/sleep.mjs`——含 v1.5 `renderRecallLine`;桩 ctx 端到端(含失败→回查行)+ 写失败线 + 无核心降级;临时目录,不碰真库水位线)。
10
15
 
11
- - **触发**:`agent/status → idle`,去抖 `minIntervalHours`(默认 6);另一路定时兜底 `ctx.interval`(默认 1h——timer 属混入服务,需 `inject:['timer']`)。跳过也留痕(`sleep-skip`);首次激活即跑一次(`activate`)。
12
- - **蒸馏**:`hooks.jsonl` 增量(水位线 `processedLines`)→ 统计 + 失败备注 + 待办(审计警告 → review;工具失败 / 拦截 / agent 错误 → 孤案候选;**失败前未查库的回合 → review `recall-miss`(召回复盘,带会话样本;不自动转孤案),wave1.1**);报告 `sleep-<date>.json`(**同日重复跑加时间戳后缀,不覆盖**);有待办时追加 `logs/inbox.jsonl`。
13
- - **条子一(每回合)**:`akasha:sleep`(order 130)——最近一次睡眠摘要(含待办数)。
14
- - **条子二(新会话·唤醒条)**:`agent/created` → 经 `agent.inject()` 递「起床包」摘要(不唤醒、不打断;仅当 无睡眠记录 / 有待办 / 审计警告 才发)。
15
- - **条子三(每回合·库脉搏 + 回查)**:`akasha:pulse`(order 132)——六库计数 + 最近写入(**写→可见通道**);窗口内(默认 30 分钟)有失败时追一行**回查提示**(注入级,不拦截)。
16
- - **配置**:`akashaDir` / `log` / `stateFile` / `inboxFile` / `appModulesDir`(唤醒条用的宿主模块目录;**留空则跳过并留痕 `wake-note-llm-skip`**)/ `minIntervalHours` / `timerCheckMs` / `contextOrder` / `pulseOrder`。
17
- - 观测线:`sleep-armed` / `sleep-done` / `sleep-skip` / `sleep-error` / `wake-note` / `wake-note-error` / `wake-note-llm-error` / `wake-note-llm-skip` / `sleep-report-error` / `sleep-state-error` / `sleep-inbox-error`。
18
- - 自测:`node selftest.mjs`(纯函数 + 桩 ctx 端到端 + 写失败线 + 无核心降级;不碰真实水位线)。
16
+ ## 版本与重启
19
17
 
20
- ## ⚠️ 版本纪律
21
- 替换已安装包的 JS **无法进程内热更**(模块代缓存)——升级后需重启宿主载入。
18
+ - v1.1.0 事故:访问 `ctx.setInterval` 未 `inject` → 属性访问本身抛错、**apply 整段失败且零日志**(诊断靠 `plugin_manager` 的返回或 `*-armed` 观测线)。v1.1.2 修复 + 入口改 `lib/index.js`。
19
+ - **替换已装包的 JS 无法进程内热更**(toggle / remove+reinstall 都无效)——v1.1.2 / v1.1.1 / v1.2.0 / v1.3.0 / v1.3.1 / v1.4.0 / **v1.5.0** 均需**重启**载入。
20
+ - v1.3.0:库脉搏(写→可见通道);v1.3.1:写路径静默失败补观测线;v1.4.0:逻辑归库(`akasha\sleep.mjs`)+ 手动触发;**v1.5.0:回查提示(失败窗口 → 脉搏条追一行)**。
21
+ - ⚠️ 注意:`ctx.on('tools/result')` 与 `ctx.on('agent/error')` 的监听是 v1.5 新增——宿主 Event 名以 `cordis_inspect_query`(host Event 目录)为准,两个事件均为 emit 语义(失败不打断宿主)。
22
22
 
23
- ## 打包 / 安装(DSH 宿主)
23
+ ## 打包 / 安装
24
24
 
25
- ```bash
25
+ ```powershell
26
+ cd <LOCAL_PATH>
26
27
  npm pack
27
- # 然后:plugin_manager install_bundle <tgz 绝对路径>(新 bundle 热生效;替换已装包需重启宿主)
28
+ # 然后:plugin_manager install_bundle <tgz 绝对路径>(首次安装会 HMR 热生效;替换需重启)
28
29
  ```
29
-
30
- 依赖:DSH 宿主(`systemPrompt` / `timer` 服务与事件面);核心库 `../../core/sleep.mjs` + `lib.mjs`(经 `akashaDir` 动态加载)。
31
-
32
- <!-- store-status -->
33
- ## 兼容与状态(DSH STORE 口径 · 2026-10-10)
34
-
35
- **固定源(immutable source)**:本版本的源码冻结于 Commit `d311ad54d1dc2cd2697c7b9eeac57eaa6466fc04`(对应 `plugins/akasha-sleep/package.json` 的 version)。
36
- 兼容声明见 manifest 的 `dsh.compatibility.dshReleases`:**0.2.0-rc.2 = compatible**(本机实测运行),
37
- `0.2.1-alpha.1` / `0.2.1-alpha.2` 尚未实测 ⇒ 按契约如实写 `unknown`(不猜、不吹)。
38
-
39
- | 证据层 | 状态 | 依据 |
40
- |---|---|---|
41
- | 静态契约(manifest / Bundle Patch / 许可证 / 入口 ID) | **verified** | 官方 `build-dsh-plugin` 审计:静态分见本包审计输出;入口 ID 为插件自有,不 disable/replace 任何 `@deepseek-ai/*` |
42
- | 单元与边界测试(`npm test`) | **verified** | `node selftest.test.mjs` 全绿;覆盖 malformed 输入、并发/节流、replay 一致性;**含"用户消息形状"契约测试**(与宿主 `createUserMessage` 逐字段比对,见 [`docs/upstream-contracts.md`](../../docs/upstream-contracts.md) C1) |
43
- | 一次性 Profile 安装·启动·卸载(E3) | **verified** | 2026-10-10 一次性 DSH_HOME 实跑:install → cold start(HTTP 就绪)→ stop → uninstall → `--dump-config` 逐字回到基线;dsh 0.2.0-rc.2;证据见同目录 `EVIDENCE.json` |
44
- | 真实 Profile 运行 | **verified(本机)** | 桌面端 0.2.0-rc.2 实跑;**他人机器 unverified**(未做外部验收);**称呼行 `akasha:address`(1.5.4,order 133)已活体可见**——每回合 runtime context 带「对用户称 Master / 用户称你大肥鱼」并写明执行点(交付 / 验收 / 复盘开口句) |
45
- | 独立安全审计 / 公开分发(E5) | **unverified** | 未做独立审计;分发前应重评 |
46
-
47
- **下一道门(next gate)**:① 在 0.2.1-alpha.x 上按同一套用例复测(一次性 DSH_HOME),把 `unknown` 改为精确结论(`compatible` 或 `incompatible`);
48
- ② 提交 DSH STORE 上架申请(monorepo 子路径:`tree/main/plugins/<name>`)并跟进机器人预检。
49
- 若任一版本复测失败,该版本标注为 `blocked`(不兼容)并保持其余版本声明不动。
50
-
51
- **权限 / 非目标 / 边界(permissions · non-goals · boundaries)**
52
- - 读取:`logs/hooks.jsonl`(蒸馏输入);写入:**仅在触发时**写睡眠报告、`logs/inbox.jsonl`(候选待办)与水位线 `sleep-state.json`;
53
- 失败路径**不推进水位线**(回滚语义,见测试断言);注入失败只降级显示,不抛。
54
- - **统一非目标(non-goals)**:不修改 DSH 核心与官方包;不替换、禁用或遮蔽任何官方组件;不写真实 Profile(测试一律用系统临时目录);
55
- 不在日志/输出里暴露凭据、完整用户文件或注入上下文。
56
- - **测试隔离**:所有自测只使用 `os.tmpdir()` 下的临时目录;不读写真实库(`~/.akasha`)与真实会话档案。
package/cordis.patch.yml CHANGED
@@ -2,7 +2,11 @@
2
2
  - id: akasha-sleep
3
3
  name: '@akasha-book/sleep'
4
4
  config:
5
- # 路径默认 ~/.akasha(见 lib/index.js 的 DEFAULTS);调度参数如下
5
+ akashaDir: '<AKASHA_DIR>'
6
+ log: '<AKASHA_DIR>/logs\hooks.jsonl'
7
+ stateFile: '<AKASHA_DIR>/logs\sleep-state.json'
8
+ inboxFile: '<AKASHA_DIR>/logs\inbox.jsonl'
9
+ reportDir: '<AKASHA_DIR>/reports'
6
10
  minIntervalHours: 6
7
11
  timerCheckMs: 3600000
8
12
  contextOrder: 130
package/lib/index.js CHANGED
@@ -43,7 +43,9 @@ const DEFAULTS = {
43
43
  timerCheckMs: 3600000,
44
44
  contextOrder: 130,
45
45
  pulseOrder: 132,
46
- addressOrder: 133
46
+ addressOrder: 133,
47
+ preflightOrder: 135, // C1|易错点前置
48
+ statefulOrder: 134 // C3|断言前把关(order 134 < 135 ⇒ 先渲染,命中时 C1 让位)
47
49
  };
48
50
 
49
51
  /** 唤醒条是否值得推(有内容才说话):无睡眠记录 / 有待办 / 审计有警告。 */
@@ -64,6 +66,13 @@ export function buildWakeNote(k) {
64
66
  }
65
67
 
66
68
  export function apply(ctx, config = {}) {
69
+
70
+ // A/B 实验开关(2026-10-10 用户解冻,见 docs/ab-experiment-design.md §6):
71
+ // abOff=true ⇒ **关闭臂**——本插件不注册任何守卫/注入/工具,只记一行观测;库文件与日志照旧(便于事后复盘)。
72
+ if (config.abOff === true) {
73
+ try { (ctx.logger?.info ?? (() => {}))('sleep: abOff=true(A/B 关闭臂)——本插件不注册任何面'); } catch { /* 静默 */ }
74
+ return;
75
+ }
67
76
  const cfg = { ...DEFAULTS, ...config };
68
77
  const require_ = createRequire(import.meta.url);
69
78
  const reportDir = join(cfg.akashaDir, 'logs');
@@ -191,6 +200,121 @@ export function apply(ctx, config = {}) {
191
200
  }
192
201
  });
193
202
 
203
+ // C3|断言前把关(stateful-fact gate,2026-10-10;评审 v2 定稿=触发改到提问侧)
204
+ // 为什么改触发:context 行在回合开始渲染、回复尚未产生;且本插件看不到用户消息事件 ⇒
205
+ // 取**会话层最近一条 intent 段**(跳过注入样式的段)做 6 类关键词判定。
206
+ // 只提醒不阻断;statefulGate:false ⇒ 提示与事件双停。
207
+ const gateState = { c3Cat: null, c3At: 0, c3Fired: false };
208
+ if (cfg.statefulGate !== false) {
209
+ const STATEFUL = [
210
+ { cat: "发布", re: /已发布|未发布|上架|没过审|已过审|待审/ },
211
+ { cat: "安装", re: /已安装|未安装|装好了|装上了/ },
212
+ { cat: "版本", re: /版本|version/i },
213
+ { cat: "开关/运行", re: /开关|启用|禁用|默认开|默认关|开着|关着|在跑|跑着|还在吗|开着吗|装着吗|有没有开/ },
214
+ { cat: "存在", re: /是否存在|有没有|在不在|还在吗/ },
215
+ ];
216
+ ctx.systemPrompt.context({
217
+ name: "akasha:stateful",
218
+ order: cfg.statefulOrder,
219
+ text: () => {
220
+ try {
221
+ const path = join(cfg.akashaDir, "data", "session.jsonl");
222
+ const lines = readFileSync(path, "utf8").split("\n").slice(-200);
223
+ let gist = null;
224
+ for (let i = lines.length - 1; i >= 0; i--) {
225
+ if (!lines[i].includes("\"kind\":\"intent\"")) continue;
226
+ let r; try { r = JSON.parse(lines[i]); } catch { continue; }
227
+ const g = String(r.gist || "");
228
+ if (!g) continue;
229
+ // 规则化跳过注入段(2026-10-10 生产核对发现:除 runtime context 外还有 openviking / hindsight 等注入块被记成 intent)
230
+ const injected = g.startsWith("<") || g.length > 800
231
+ || /Current runtime context|Relevant memory from|Hindsight|openviking-context|阿卡夏·/.test(g);
232
+ if (injected) continue;
233
+ gist = g; break;
234
+ }
235
+ if (!gist) return null;
236
+ const hit = STATEFUL.find((k) => k.re.test(gist));
237
+ if (!hit) return null;
238
+ const now = Date.now();
239
+ if (gateState.c3Cat === hit.cat && now - gateState.c3At < 30 * 60 * 1000) return null; // 同类 30 分钟去重
240
+ gateState.c3Cat = hit.cat; gateState.c3At = now; gateState.c3Fired = true;
241
+ try {
242
+ appendFileSync(join(cfg.akashaDir, "logs", "hooks.jsonl"),
243
+ JSON.stringify({ ts: new Date().toISOString(), kind: "stateful-reminder", cat: hit.cat }) + "\n", "utf8");
244
+ } catch { /* 事件失败不影响提示 */ }
245
+ return "[断言提醒] 状态性事实——先查再答(例:versions + dist-tags 两处核对)";
246
+ } catch { return null; }
247
+ }
248
+ });
249
+ }
250
+
251
+ // C1|易错点前置(pre-flight hint,2026-10-10 解冻后实现;评审 v2 定稿)
252
+ // 依据:可预防漏召率 91.2%(回合级)、会话级 100% ⇒ 缺的不是知识,是"动作前把库拉进来"。
253
+ // 形态:一行 ≤80 字,只提示不阻断;关(preflightHints:false)则**提示与事件双停**(不写假触发)。
254
+ // 近似说明(如实):context 行在**回合开始**渲染,此刻还不知道本回合会调用什么工具,
255
+ // 故用"最近失败的工具"作为**预提示**(近 30 分钟窗口 + 同工具去重);"本回合尚未查库"这一前置
256
+ // 在渲染时无法判定,改为"上一个回合没有查库动作时更倾向提示"的弱化版(v1 取"总是可提示",由去重与上限约束)。
257
+ const preflightState = { tool: null, at: 0 };
258
+ if (cfg.preflightHints !== false) {
259
+ ctx.systemPrompt.context({
260
+ name: 'akasha:preflight',
261
+ order: cfg.preflightOrder,
262
+ text: () => {
263
+ try {
264
+ if (gateState.c3Fired) return null; // C3 优先(同回合只出一条)
265
+ const lib = require_(join(cfg.akashaDir, 'lib.mjs'));
266
+ const now = Date.now();
267
+ const WINDOW = 30 * 60 * 1000;
268
+ const recent = (recentFailures || []).filter((f) => now - Number(f.ts ?? f.at) <= WINDOW); // 字段是 ts(见 noteFailure)
269
+ if (!recent.length) return null;
270
+ const last = recent[recent.length - 1];
271
+ const tool = String(last.tool || '');
272
+ const map = lib.RECALL_TRAP_MAP || {};
273
+ const ids = map[tool];
274
+ if (!ids || !ids.length) return null; // 不在映射表 ⇒ 不提示
275
+ if (preflightState.tool === tool && now - preflightState.at < WINDOW) return null; // 同工具 30 分钟去重
276
+ // 2026-10-11 修复(用户裁定:反射要能随工程知识纠错与优化):
277
+ // **反射文本随条目走** —— 不再只认写死的表。
278
+ // ① 链感知解析(id 或 id-rN 取链尾);② 条目缺失/已退役 ⇒ **不打**(fail closed,不执行过期反射);
279
+ // ③ 优先用条目自带 `hint`(≤80 字反射文本:**改条目=改反射**);④ `hint_until` 过期 ⇒ 跳过;
280
+ // ⑤ 内置表降级为**过渡兜底**;⑥ 都取不到 ⇒ 不打(宁缺勿滥)。
281
+ // 该表仅作过渡:条目补上 hint 后即成为唯一来源。
282
+ const FALLBACK_ACTIONS = {
283
+ 'canon-trap-edit-context-mismatch': '先 read 原文再改、改完复核',
284
+ 'canon-trap-read-offset-range': '先用 grep 拿真实行号再读',
285
+ 'canon-trap-grep-exit2-path': '换浅范围/排除 node_modules 再 grep',
286
+ 'canon-trap-unknown-tool-name': '只从本会话可见工具面选名字',
287
+ 'canon-trap-provider-method-list': '先列方法清单再调用',
288
+ };
289
+ let canonRecs = [];
290
+ try { canonRecs = lib.currentRecords(lib.loadStore('canon').records); } catch { /* 读不到 ⇒ 只走兜底 */ }
291
+ const resolveEntry = (cid) => canonRecs.filter((r) => String(r.id) === cid || String(r.id).startsWith(cid + '-r')).pop() || null;
292
+ const isRetired = (rec) => !!rec && (/已退役|retired/i.test(String(rec.claim ?? '')) || String(rec.id).endsWith('-retired'));
293
+ const today = new Date().toISOString().slice(0, 10);
294
+ let id = null, act = null, hintSource = null;
295
+ for (const cand of ids) {
296
+ if (canonRecs.length) {
297
+ const rec = resolveEntry(cand);
298
+ if (!rec) continue; // 链上已无此条 ⇒ 跳过
299
+ if (isRetired(rec)) continue; // 已退役 ⇒ 不执行过期反射
300
+ if (rec.hint_until && String(rec.hint_until) < today) continue; // 反射有效期已过 ⇒ 跳过
301
+ if (typeof rec.hint === 'string' && rec.hint.trim()) { id = cand; act = rec.hint.trim(); hintSource = 'entry'; break; }
302
+ }
303
+ if (FALLBACK_ACTIONS[cand]) { id = cand; act = FALLBACK_ACTIONS[cand]; hintSource = 'fallback'; break; }
304
+ }
305
+ if (!id || !act) return null; // fail closed:没有现行条目/没有反射文本 ⇒ 不打
306
+ const line = '[坑前提示] ' + tool + ' 前:' + act + ' —— 条目 ' + id;
307
+ preflightState.tool = tool; preflightState.at = now;
308
+ try { // 事件:关闭时走不到这里(双停)
309
+ appendFileSync(join(cfg.akashaDir, 'logs', 'hooks.jsonl'), // 用文件顶部已导入的 appendFileSync
310
+ JSON.stringify({ ts: new Date().toISOString(), kind: 'preflight', tool, entry: id, hintSource }) + '\n', 'utf8');
311
+ } catch { /* 事件失败不影响提示 */ }
312
+ return line.length <= 80 ? line : line.slice(0, 79) + '…';
313
+ } catch { return null; }
314
+ }
315
+ });
316
+ }
317
+
194
318
  // 空闲触发(事件失败开放)。
195
319
  ctx.on('agent/status', (payload) => {
196
320
  try { if (payload?.status === 'idle') maybeSleep('idle'); } catch { /* 静默 */ }
package/package.json CHANGED
@@ -1,24 +1,25 @@
1
1
  {
2
2
  "name": "@akasha-book/sleep",
3
- "version": "1.5.4",
4
- "repository": { "type": "git", "url": "https://github.com/Ersith/akasha-book.git", "directory": "plugins/akasha-sleep" },
5
- "engines": { "node": ">=18" },
6
- "license": "MIT",
3
+ "version": "1.6.5",
4
+ "engines": {
5
+ "node": ">=18"
6
+ },
7
7
  "type": "module",
8
- "description": "阿卡夏之书睡眠器 v1.5:调度与注入(蒸馏逻辑归核心库 sleep.mjs,可手动 node akasha.mjs sleep)——空闲/定时触发 + 每回合条子 + 新会话唤醒条 + 库脉搏(写→可见通道)+ 回查提示(窗口内失败追一行)",
9
- "exports": { ".": "./lib/index.js" },
10
- "files": ["lib/index.js", "cordis.patch.yml", "README.md"],
11
- "scripts": { "test": "node selftest.test.mjs" },
8
+ "description": "阿卡夏之书睡眠器 v1.5:调度与注入(蒸馏逻辑归核心库 akasha\\sleep.mjs,可手动 node akasha.mjs sleep)——空闲/定时触发 + 每回合条子 + 新会话唤醒条 + 库脉搏(写→可见通道)+ 回查提示(窗口内失败追一行,错误钩子注入级)",
9
+ "exports": {
10
+ ".": "./lib/index.js"
11
+ },
12
+ "files": [
13
+ "lib/index.js",
14
+ "cordis.patch.yml",
15
+ "README.md"
16
+ ],
12
17
  "dsh": {
13
18
  "bundle": {
14
19
  "patch": "./cordis.patch.yml"
15
- },
16
- "compatibility": {
17
- "dshReleases": {
18
- "0.2.0-rc.2": "compatible",
19
- "0.2.1-alpha.1": "compatible",
20
- "0.2.1-alpha.2": "compatible"
21
- }
22
20
  }
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
23
24
  }
24
- }
25
+ }