@mebular/skill 0.0.0-stage → 0.1.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.
@@ -0,0 +1,104 @@
1
+ # Mebular 记忆使用规约(MEMORY_POLICY)
2
+
3
+ 本文件是 Agent 使用 Mebular 记忆时的行为规约;与 `SKILL.md` 配套分发。
4
+
5
+ ## 1. 先查后写
6
+
7
+ 写入前先用 `memory_query` / `memory_search` 查重;已有等价记忆则不重复写入,必要时用更新语义。避免记忆库被重复条目稀释。
8
+
9
+ ## 2. 类型选择
10
+
11
+ | 内容 | 类型 |
12
+ |------|------|
13
+ | 稳定事实(人、物、关系、客观陈述) | `fact` |
14
+ | 用户偏好(可随时间变化的取向) | `preference` |
15
+ | 会话 / 任务 / 决策 / 报错过程 | `episode` |
16
+ | 可复用的步骤、命令、流程 | `skill` |
17
+ | 对用户或环境的观察 | `observation` |
18
+
19
+ ## 3. 时效
20
+
21
+ - 有有效期的记忆用 `metadata.expiresAt` 标注。
22
+ - 过期事实不要当作现状;需要现状时重新确认。
23
+ - 事实冲突时以更新的 `validFrom` 为准。
24
+
25
+ ## 4. 隐私
26
+
27
+ - 不要写入密钥、口令、令牌、完整证件号等高敏感信息。
28
+ - 只记录完成任务所必需的最小信息。
29
+ - 用户明确要求删除时,尊重删除语义(墓碑)。
30
+
31
+ ## 5. 关系
32
+
33
+ - 相关对象用 `metadata.relatedTo` 关联**已存在**的节点,不要制造悬空引用。
34
+ - 需要结构化关系时优先用既有实体作为端点。
35
+
36
+ ## 6. 无结果别编
37
+
38
+ 召回为空就如实说明「没有相关记忆」,不要凭推测填充。宁可承认缺失,也不写入或返回未经验证的内容。
39
+
40
+ ## 7. 记忆分区与选择性同步(用户向)
41
+
42
+ 记忆可打 `namespace`(分区)标记:协作高频短命记忆与用户长期记忆隔离,召回/同步都能按分区限定;不带分区按 `default`。分区只加组织维度,**不改变一致性模型**。
43
+
44
+ - **分区隔离**:`memory_query` / `memory_search` / `memory_graph` 接受可选 `namespace`(单个/数组);CMF 与 SQLite(namespace 列+索引)同样贯通。
45
+ - **订阅即读**:数据持有者只发给**订阅了该域**的对端;未订阅 = 不给该分区。未订阅分区不会离开持有者,空水位走快照也绕不过;拒绝非静默(`sync-completed.denied`)。
46
+ - **订阅作为记忆**:`namespace_subscription` 落在保留分区 `__policy__`,只有 `author === member` 的自声明被采纳;退订写 `active=false`。
47
+ - **移出**:`device_revoke` 只作用于被移出设备本人;其署名事件在入站与快照两条路都被隔离。恢复用 `device_restore` + 纪元 E-1,之后重新订阅。
48
+ - **水位**:`per-(对端, 分区, 作者)`,订阅后即可回补历史;水位只由 ack 与「已确认快照」推进(自报不抬升)。
49
+
50
+ ## 8. 与其他记忆提供者共存(叠加不接管)
51
+
52
+ Mebular 是**叠加基建**:把「单机记忆」升级为「去中心化记忆」,**不替代、不改造**既有的 memory provider
53
+ (系统自带的记忆/上下文机制照常工作)。**零新增配置项**:行为面靠规则、控制面只给**动作**(订阅 / 归档 / 删除),不给开关。
54
+
55
+ - **定位**:不接管既有 provider 的代码、存储与进程;只通过 MCP 工具面新增一种**跨设备/跨会话**的记忆能力。
56
+ - **不双写**:同一事实只在一个地方作为权威来源(避免两份互相矛盾)。
57
+
58
+ ### 8.1 一句话判据(三问,按序命中即止)
59
+
60
+ - **A. 跨设备、跨会话仍然成立的稳定事实?**(人物 / 偏好 / 约束 / 技能 / 约定)
61
+ → 放 **Mebular**(`fact` / `preference` / `skill`…),随域订阅同步到各端。
62
+ - **B. 本次会话 / 任务的过程产物?**(临时上下文、草稿、推理中间态)
63
+ → **留在原 provider**,不进 Mebular(否则污染跨设备召回)。
64
+ - **C. 外源已有的历史?**(既有笔记 / 日志 / 系统记忆库)
65
+ → **只在导入那一刻判**:按 A/B 决定哪些条目值得进 Mebular;拿不准就不导入(外源仍是权威)。
66
+
67
+ ### 8.2 双闸门(写入 / 导入前两次把关)
68
+
69
+ 1. **隐私闸门**(§4):不导入密钥 / 口令 / 证照等高敏感信息;只取完成任务所需的最小信息。
70
+ 2. **订阅供给**(§7):内容同步到哪些对端,由**本机订阅 ∩ 对端订阅 ∩ 信任边界**决定;未订阅分区不出本机。
71
+
72
+ ### 8.3 外源写权限(默认只读,不做对等双向)
73
+
74
+ - **默认只读**:Mebular 只读取外源做导入;不接管、不修改外源存储。
75
+ - **回写仅追加**:确需回写时(由人显式发起),只能**追加**新条目,不覆盖 / 不删除外源既有内容。
76
+ - **禁止对等双向**:Mebular 与外源**不建立双向同步**(对等双向会放大冲突、丢失溯源)。
77
+
78
+ ### 8.4 互通途径(三选一,按外源能力)
79
+
80
+ 1. MCP 工具面(本 Skill 的 `memory_*`);
81
+ 2. `memory_import` 适配器**显式导入**(把外源历史一次性 / 增量搬进来);
82
+ 3. 外源自带的导入 / 导出接口(由外源提供)。
83
+
84
+ - **导入纪律**:为导入内容使用**专用 `namespace`**(如 `imported-<source>`),并在 `metadata.origin` 标注来源;
85
+ **幂等键去重**(同一来源重复导入 = **零新增**,内容寻址不膨胀);**默认单向**(外源 → Mebular)。
86
+ - **冲突与删除**:一致性裁决(`validFrom` / 墓碑 / 水位)**只在 Mebular 内部**发生、**不外溢**;外源删除**不自动传播**
87
+ 到 Mebular(反之亦然)——两边各自权威。
88
+ - **停用无残留**:导入是**只读外源**;停用 / 卸载 Mebular 不影响外源数据与其原有行为。
89
+
90
+ ### 8.5 删除与归档(生命周期)
91
+
92
+ - **删除 = 墓碑传播**:`memory_delete` 写墓碑(`deletedAt`)并生成 `node_deleted` 事件,**随图同步**到各已订阅对端;
93
+ 删除后**默认不参与任何召回**(`query` / `search` / `profile` / `skills` / `history` / `graph`)。
94
+ 删除是**合作式**的:本端与已同步对端默认不再召回,但**对端已拷贝的旧快照无法强制回收**(不可逆)。
95
+ - **归档 = 标记,默认不召回、可逆**:`memory_archive` 打 `metadata.archivedAt`(`node_updated` 事件,随图同步);
96
+ 归档后默认不参与召回,查询类工具显式 `includeArchived: true` 可查;传 `archived: false` **解除归档**(无损、可逆)。
97
+ 墓碑节点不可归档(跳过)。
98
+ - **动作式控制面(scope 口径)**:
99
+ - **MCP / CLI 按工具 scope**:`memory_delete` = `memory.admin`;`memory_archive` = `memory.write`。
100
+ - **控制台(GUI / HTTP admin 写面)一律 `memory.admin` + CSRF**(含归档 / 解除归档 / 删除)——与既有控制台安全姿态、
101
+ `LIMITATIONS`「写操作需 `memory.admin` + CSRF」一致(fail-safe;不按路径细分 scope)。
102
+ - **不提供开关**——是否召回由上面的默认规则决定。
103
+
104
+ **内核口径**(红线/协议语义/推迟项)见仓库根 [`SEALING.md`](../../SEALING.md);策略不变量矩阵见 [`src/sync/POLICY-INVARIANTS.md`](../../src/sync/POLICY-INVARIANTS.md)。
package/SETUP.md ADDED
@@ -0,0 +1,205 @@
1
+ # Mebular 部署手册(给 Agent 执行)
2
+
3
+ > 面向 **Agent**:本文件是可执行的部署/加入剧本。用户只负责两件事:**说出要做什么**、**转交配对码**。
4
+ > 每一步都给出命令与「期望输出 / 判定」。任何一步失败:先按 §6 处置,不要猜、不要跳过。
5
+
6
+ ## 0. 会话内接入(每次会话第一步)
7
+
8
+ > 目标:**在当前会话里直接拿到 Mebular 的跨设备记忆能力**(MCP 工具面),且**不改动任何既有 memory provider**。
9
+ > 顺序:① 幂等检查 → ② 无 home 指回 §3/§5(**不自建身份**)→ ③ 有 home 未在跑则拉起 → ④ 接入当前客户端并验证 → ⑤ 红线。
10
+
11
+ **0.1 幂等:已装且已在跑就直接用,不要重复安装/重启**
12
+
13
+ ```bash
14
+ command -v mebular # 期望:打印路径;未安装(无输出、exit 1)→ 见 §2
15
+ # 幂等判定**只在 home 已存在时**执行 status(无 home 时它会在默认 home 自举身份材料,见 0.2)
16
+ HOME_DIR="${MEBULAR_HOME:-$HOME/.mebular}"
17
+ if [ -f "$HOME_DIR/config.json" ]; then
18
+ MEBULAR_HOME="$HOME_DIR" mebular status # 判定见下(exit 0)
19
+ else
20
+ echo "无 home → §3 建新 / §5 加入" # 不要在这里跑 status
21
+ fi
22
+ ```
23
+
24
+ 判定「守护已在跑」:`status` 输出里 **`storeLock` 非 null**(形如 `{"pid":…,"startedAt":…,"storagePath":…}`)→
25
+ **直接使用**本机已有实例,不要重复 `install` 或再起 `serve`。
26
+
27
+ > 注意口径:`status.running` 是 **P2P 节点**状态(`network.enabled=true` 才为 true),**不是**守护进程状态;
28
+ > 默认 home 下它常为 `false`,属正常。判定守护进程请用 `storeLock`(或 0.3 的 `service status` / `/healthz`)。
29
+
30
+ **0.2 无 home:不要在这里自建身份**
31
+
32
+ `mebular status` 会在 home 不存在时**自举身份材料**(`user-master-key.json`、身份文件)。因此:
33
+
34
+ - 无 `config.json` → **不要**跑 `status`;按 §3(建新)或 §5(加入)走,**只有用户明确要建新/加入时才创建身份**。
35
+ - 已有 home(`config.json` 在)→ 才继续 0.3/0.4。
36
+
37
+ **0.3 有 home 但未在跑:拉起守护**
38
+
39
+ 优先**常驻**(按 `packages/service` 的平台矩阵:darwin = launchd 用户级 LaunchAgent;linux = `systemd --user`;win32 = 计划任务 onlogon):
40
+
41
+ ```bash
42
+ MEBULAR_HOME=~/.mebular mebular service status # 只读:services[0].registered / running
43
+ MEBULAR_HOME=~/.mebular mebular service install # 常驻 + 自启(不想自启用 --no-autostart)
44
+ MEBULAR_HOME=~/.mebular mebular service status # 判定:services[0].registered === true 且 running === true
45
+ ```
46
+
47
+ > **home 默认已统一**:`mebular` 缺省用 `~/.mebular`(`MEBULAR_HOME` 可覆盖;`bin/mebular.mjs` 与
48
+ > `src/config.mjs` 共用同一真源 `src/home.mjs`)。上面命令的 `MEBULAR_HOME=~/.mebular` 前缀是**显式声明**
49
+ > (等价于缺省),跨环境脚本里保留更直观;service 会把该值写进单元的 `env.MEBULAR_HOME` 与 `workingDir`。
50
+
51
+ 若所在环境不支持常驻(无 launchd/systemd/计划任务的容器等),改**前台**拉起:
52
+
53
+ ```bash
54
+ MEBULAR_HOME=~/.mebular mebular serve --port 7331 # 期望输出含 SERVE_READY {…}
55
+ ```
56
+
57
+ **确认已拉起**(任一即可,判据如下):
58
+
59
+ ```bash
60
+ MEBULAR_HOME=~/.mebular mebular status # 判据:storeLock 非 null
61
+ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:7331/healthz # 判据:200
62
+ ```
63
+
64
+ > 实测(沙箱 home,`mebular serve --port 0`):`storeLock` 由 `null` → `{"pid":…,"startedAt":…}`,`/healthz` = `200`;
65
+ > 停止后 `storeLock` 回到 `null`。`service install` 会注册**真实**常驻服务,故本沙箱未执行,依据 = `mebular service` 用法 +
66
+ > `packages/service/src/units.ts` 平台矩阵 + `service status` 实跑输出。
67
+
68
+ **0.4 接入当前客户端(MCP 片段)**
69
+
70
+ ```bash
71
+ mebular print-config --client <opencode|claude|cursor|dsh|generic> # 远程形态:追加 --url https://<host>/mcp
72
+ ```
73
+
74
+ 1. 把输出片段合入**当前客户端**的 MCP 配置(**先备份**原文件);`dsh` 形态为客户端桥接(只桥接 Tools)。
75
+ 2. **重载客户端**(重启该客户端/会话)后生效。
76
+ 3. 验证:在本会话调用 `memory_status` —— 期望返回 `deviceId` / `running`(P2P 节点)/ 计数等字段。
77
+ 注意:`storeLock` **不在** `memory_status` 的返回里(那是 CLI `mebular status` 追加的字段,见 0.1/0.3)。
78
+ 若「没有 mebular 工具」:片段未生效或未重载客户端,回到第 1–2 步。
79
+
80
+ > 实测:`MEBULAR_HOME=<沙箱> node packages/mcp/bin/mebular.mjs mcp` 上 `tools/call memory_status` 返回
81
+ > `deviceId=device-local`、`running=false`(P2P,默认 home 网络未启用)与 12 个字段;**无 `storeLock`**。
82
+
83
+ **0.5 红线**
84
+
85
+ **不改变任何既有 memory provider 的代码、存储与进程**;Mebular 仅以 MCP 工具面**叠加**提供跨设备记忆。
86
+ 与既有 provider 的分工/导入/冲突口径见 [`MEMORY_POLICY.md`](./MEMORY_POLICY.md) §8。
87
+
88
+ ## 1. 前置检查
89
+
90
+ ```bash
91
+ node -v # 期望:v20 或更高
92
+ npm -v
93
+ ```
94
+
95
+ 判定:`node -v` 输出 `v20+`。否则先让用户安装 Node.js LTS,**不要继续**。
96
+
97
+ ## 2. 安装 CLI(二选一)
98
+
99
+ **A. 从 GitHub 钉住提交(推荐;可复现)**
100
+
101
+ ```bash
102
+ SHA=$(git ls-remote https://github.com/Windsander/Mebular.git refs/heads/main | cut -f1)
103
+ npm i -g "github:Windsander/Mebular#$SHA"
104
+ command -v mebular && command -v fleet
105
+ ```
106
+
107
+ 判定:`command -v mebular && command -v fleet` 均有输出;`mebular --help`(exit 0)与 `fleet --version`(exit 0)可执行;
108
+ `mebular tools` 列出 **29** 个工具;记录 `$SHA` 以便回报。
109
+ (`mebular --version` 不存在:会打印「未知命令:--version」并 exit 2。)
110
+
111
+ > 安装时的 `prepare` 会自动完成三包构建(`mebular` 与 `fleet` 双 bin 随包发布,无需手动 build;缺省 home 为 `~/.mebular`)。
112
+ > **若该命令以 `ENOTDIR` / `git dep preparation failed` 失败**:这是部分 npm(实测 11.19)对**全局 git 依赖**的
113
+ > staging 缺陷——与本仓库内容无关(`prepare` 一旦成功、进入全局 reify 才暴露;用基线 SHA 只是更早失败在 `tsc` 而看不到)。
114
+ > 遇到时改用下面的 **B**(本地仓库),它等价且本机已实测可用。
115
+
116
+ **B. 本地仓库(开发者;也是 A 失败时的等价干净路径)**
117
+
118
+ ```bash
119
+ SHA=<要钉住的提交>
120
+ git clone https://github.com/Windsander/Mebular.git && cd Mebular
121
+ git checkout "$SHA"
122
+ npm ci && npm run build
123
+ npm i -g .
124
+ command -v mebular && command -v fleet
125
+ ```
126
+
127
+ (本机实测:`npm i -g .` → 双 bin 就位、`mebular tools`=29、`fleet --version` 含该 SHA、不设 `MEBULAR_HOME` 起 `serve` → `PROVISION_READY home=~/.mebular`。)
128
+
129
+ ## 3. 建一个新的 Mebular(本机 = 信任根)
130
+
131
+ ```bash
132
+ fleet quickstart --daemon --dir ~/.mebular --device "$(hostname | tr '[:upper:]' '[:lower:]')"
133
+ ```
134
+
135
+ - Windows(PowerShell)把家目录写成:`--dir "$env:USERPROFILE\.mebular"`。
136
+ - 这一条做了什么:生成本机设备身份 + 守护 home + 加入服务;打印的 JSON 里有 `joinEndpoint` 等字段。
137
+
138
+ 判定:命令退出码 0,且 JSON 含 `"ok": true`。随后自检:
139
+
140
+ ```bash
141
+ mebular status # home 由 MEBULAR_HOME 决定,缺省 ~/.mebular
142
+ ```
143
+
144
+ > `mebular status` **没有** `--home` 参数(传了会被忽略);要指定别的 home 用 `MEBULAR_HOME=<dir> mebular status`。
145
+
146
+ ## 4. 出一个邀请(让别的设备加入你)
147
+
148
+ ```bash
149
+ fleet invite --dir ~/.mebular
150
+ ```
151
+
152
+ 输出含:**二维码**(终端渲染)与**文本令牌**(JSON 的 `token` 字段,也含 `qr`/`qrSvg`)。
153
+
154
+ **安全红线(必须遵守)**:
155
+
156
+ - 令牌是**一次性、短时效**(默认 15 分钟)的入网凭证:**只交给用户**,由用户安全转交新设备。
157
+ - **不得**把令牌/二维码写入日志、聊天记录、工单或任何外部服务;**不得**回显密钥材料。
158
+ - 主密钥**永不离开本机**;邀请过程不复制主密钥。
159
+ - 加入后可自行订阅记忆域(零门槛、热生效);不复制主密钥。
160
+
161
+ ## 5. 加入一个已有的 Mebular(新设备)
162
+
163
+ 需要用户提供**二维码内容或令牌**(二者等价):
164
+
165
+ ```bash
166
+ fleet join --qr "<二维码内容>" --daemon --dir ~/.mebular --device "$(hostname | tr '[:upper:]' '[:lower:]')"
167
+ # 等价写法:fleet join --token <令牌文件或内联> --daemon --dir ~/.mebular --device <本机名>
168
+ ```
169
+
170
+ - Windows(PowerShell):`fleet join --qr "<内容>" --daemon --dir "$env:USERPROFILE\.mebular" --device "$env:COMPUTERNAME"`。
171
+ - 一步完成:委派身份(**不复制主密钥**)+ 自动连接 + 按令牌分区自动订阅。
172
+ - **默认不需要批准**:新设备加入后自行 `fleet subscribe` 即可。
173
+
174
+ 判定:退出码 0,JSON 含 `"ok": true`。
175
+
176
+ ## 6. 自检与失败恢复
177
+
178
+ ```bash
179
+ mebular doctor --net # 网络:地址簿 / LAN 发现 / 打洞 / 桥角色 / 下一步建议
180
+ mebular status # 身份 / 存储 / 计数 / 状态哈希
181
+ ```
182
+
183
+ 常见失败与处置(**不要自行改订阅或重置身份**):
184
+
185
+ | 症状 | 处置 |
186
+ |---|---|
187
+ | `MCP_INSECURE_CONFIG`(缺证书 / 非回环组合非法) | 编辑 `~/.mebular/config.json`:把 `mcp.http.host` 改回 `127.0.0.1`,或补齐 `auth` + `tls` + `tlsKey`/`tlsCert`,再重启 `mebular serve` |
188
+ | `MCP_STORAGE_LOCKED`(存储已被占用) | 已有实例持锁:复用该实例,或先停掉它再启动 |
189
+ | 切换 `auth=bearer/oauth` 后控制台 API 401 | 见控制台「设置 → 诊断 → 恢复指引」;bearer 可粘贴 `mebular token grant --scope memory.read,memory.admin` 的 token 自救;oauth 需 env secret,否则改回 `auth=none`(仅回环) |
190
+ | 控制台打不开 | `mebular serve` 是否在跑、日志里是否有上述错误码;再打开 `http://127.0.0.1:7331/console` 的「诊断」页 |
191
+ | 加入后连不上对端 | `mebular doctor --net` 看 `next` 建议(LAN 发现 / relay seeds / 白名单) |
192
+
193
+ 更多运维细节见 [`../../packages/fleet/RUNBOOK.md`](../../packages/fleet/RUNBOOK.md)(§6 控制台、§9 桥角色、§7 配对即连)。
194
+
195
+ ## 7. 回报给用户(Agent 输出模板)
196
+
197
+ ```text
198
+ 部署结果:<新建 | 加入>
199
+ 设备:<device>
200
+ 守护 home:<dir>
201
+ 自检:mebular status = ok,mebular doctor --net 建议:<next 摘要>
202
+ 下一步:<邀请别人:fleet invite | 在控制台打开 http://127.0.0.1:7331/console>
203
+ ```
204
+
205
+ 不要输出令牌、二维码或任何密钥材料;它们只属于用户与新设备之间的转交。
package/SKILL.md ADDED
@@ -0,0 +1,66 @@
1
+ ---
2
+ name: mebular-memory
3
+ description: 通过 Mebular MCP 使用跨设备、离线可用的图式长期记忆:先查后写、类型化节点、时效与关系、隐私红线。
4
+ whenToUse: 需要记住或复用用户偏好/事实/会话/技能,跨会话或跨设备共享 Agent 记忆,或按语义/关系检索既有记忆时。
5
+ ---
6
+
7
+ # Mebular Memory
8
+
9
+ Mebular 是一个本地优先的分布式图记忆层。通过 MCP 工具读写记忆,行为规约见 `MEMORY_POLICY.md`。
10
+
11
+ 它是**叠加**基建:与既有 memory provider **共存、不接管**(不替代、不改造;不双写同一事实)——分工与导入口径见 `MEMORY_POLICY.md` §8。
12
+
13
+ ## 何时使用
14
+
15
+ - 用户透露稳定偏好、事实或约束,且未来会复用时。
16
+ - 需要回顾历史会话、任务过程或既有技能时。
17
+ - 需要按语义(同义不同词)或关系检索既有记忆时。
18
+
19
+ ## 工具(13 个)
20
+
21
+ | 工具 | 用途 |
22
+ |------|------|
23
+ | `memory_write` / `memory_write_batch` | 写入一/多条记忆(fact / preference / episode / observation / skill) |
24
+ | `memory_query` | 语义(配置向量索引)/关键词召回,可按类型与过滤 |
25
+ | `memory_search` | 关键词检索,可选一跳关系 |
26
+ | `memory_profile` | 用户偏好与属性画像 |
27
+ | `memory_skills` | 技能列表(按分类/关键词/标签) |
28
+ | `memory_history` | 会话历史 |
29
+ | `memory_graph` | 从某节点遍历关系图 |
30
+ | `memory_import` | 经适配器导入异构来源(kv / markdown / …) |
31
+ | `memory_status` | 设备/网络/计数/状态哈希/开关 |
32
+ | `memory_sync` | 连接对端并等待一次同步(需 network.enabled) |
33
+ | `memory_delete` | 删除记忆(写墓碑,随图同步;删除后默认不再召回)。**何时用**:内容已过时/错误/不该共享,且希望各端一起不再召回;不可逆(对端旧快照无法强制回收)。需 `memory.admin`。 |
34
+ | `memory_archive` | 归档 / 解除归档记忆(`metadata.archivedAt`,随图同步、可逆)。**何时用**:内容暂时不该参与召回但**将来可能有用**(先归档而非删除);`archived: false` 解除。需 `memory.write`。 |
35
+
36
+ 查询类工具(`memory_query` / `memory_search` / `memory_profile` / `memory_skills` / `memory_history` / `memory_graph`)默认**不返回已归档**;需要时传 `includeArchived: true`(已删除的墓碑始终不召回)。
37
+
38
+ ## 工作流
39
+
40
+ 1. **先查后写**:写入前用 `memory_query`/`memory_search` 查重。
41
+ 2. **选对类型**:稳定事实→`fact`;用户偏好→`preference`;会话/任务过程→`episode`;可复用步骤→`skill`;观察→`observation`。
42
+ 3. **标注时效**:有有效期的用 `metadata.expiresAt`;过期事实不当现状。
43
+ 4. **表达关系**:`metadata.relatedTo` 精确关联已存在节点。
44
+ 5. **诚实回答**:召回为空就如实说明,不要臆造记忆。
45
+
46
+ 完整行为规约见 `MEMORY_POLICY.md`。
47
+
48
+ ## 接入
49
+
50
+ 本 Skill 目录附各客户端 MCP 接入片段(见 `mcp/`);`scripts/install.mjs` 可将本 Skill(含 `mcp/` 片段)安装到常见 Skill 目录。
51
+
52
+ **会话里没有 Mebular 工具时的第一步**(每次会话):
53
+
54
+ 1. 确认守护在跑:`MEBULAR_HOME=~/.mebular mebular status` → `storeLock` 非 null(未跑则先拉起,见 [`SETUP.md`](./SETUP.md) §0.3)。
55
+ **home 不存在时**先按 SETUP §3/§5(建新/加入),**不要跑 `status`**(它会在默认 home 自举身份材料,见 §0.2)。
56
+ 2. 生成当前客户端的接入片段:`mebular print-config --client <opencode|claude|cursor|dsh|generic>`
57
+ (远程形态追加 `--url https://<host>/mcp`),合入客户端 MCP 配置(先备份)并**重载客户端**。
58
+ 3. 用 `memory_status` 验证工具面可用;失败排查见 [`SETUP.md`](./SETUP.md) §0.4。
59
+
60
+ 完整剧本(幂等判定 / 拉起 / 接入 / 红线)见 [`SETUP.md`](./SETUP.md) §0「会话内接入」。
61
+
62
+ ## 部署 / 加入 / 邀请
63
+
64
+ **部署一台新机器、加入别人的 Mebular、生成邀请(二维码 + 令牌)**:见 [`SETUP.md`](./SETUP.md)
65
+ ——面向 Agent 的可执行剧本(前置检查 → 安装 CLI(钉 SHA)→ `fleet quickstart` / `fleet join --qr` →
66
+ `mebular doctor --net` 自检 → 失败恢复 → 安全红线)。
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "mebular": {
4
+ "command": "mebular",
5
+ "args": ["mcp"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "mebular": {
4
+ "command": "mebular",
5
+ "args": ["mcp"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,13 @@
1
+ # DeepSeek Harness(Cordis)— 只桥接 Tools(不桥接 prompts)
2
+ # 行为规约以 SKILL.md + MEMORY_POLICY.md 为主通道。
3
+ plugins:
4
+ - name: '@deepseek-ai/dsh-mcp-client'
5
+ config:
6
+ serverName: mebular
7
+ transport: stdio
8
+ command: mebular
9
+ args: ['mcp']
10
+
11
+ # 远程(Streamable HTTP)用:
12
+ # transport: streamable-http
13
+ # url: http://127.0.0.1:7331/mcp
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "mebular": {
4
+ "command": "mebular",
5
+ "args": ["mcp"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "mcp": {
4
+ "mebular": {
5
+ "type": "local",
6
+ "command": ["mebular", "mcp"]
7
+ }
8
+ }
9
+ }
package/package.json CHANGED
@@ -1,6 +1,26 @@
1
1
  {
2
2
  "name": "@mebular/skill",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Mebular 行为层:可移植的 SKILL.md + MEMORY_POLICY.md 与各 MCP client 接入片段",
5
+ "license": "MIT",
6
+ "private": false,
7
+ "type": "module",
8
+ "files": [
9
+ "SKILL.md",
10
+ "MEMORY_POLICY.md",
11
+ "mcp",
12
+ "scripts",
13
+ "SETUP.md",
14
+ "tasks"
15
+ ],
16
+ "engines": {
17
+ "node": ">=20"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "scripts": {
23
+ "prepack": "node ../../scripts/publish-manifest.mjs set",
24
+ "postpack": "node ../../scripts/publish-manifest.mjs restore"
25
+ }
26
+ }
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ // 安装 Mebular Skills 到常见 Skill 目录(G6.4 + R3):**两个 skill 一起装**
3
+ // · mebular-memory(记忆面:SKILL.md + MEMORY_POLICY.md + SETUP.md)
4
+ // · mebular-tasks (任务面:tasks/SKILL.md + SETUP.md)
5
+ //
6
+ // 用法:
7
+ // node scripts/install.mjs # 探测并安装到 cwd 的 .agents/skills、.dsh/skills(及存在的 .opencode/skills)
8
+ // node scripts/install.mjs --global # 另装到 ~/.agents/skills
9
+ // node scripts/install.mjs --target <dir> # 只装到指定目录(<dir>/mebular-memory 与 <dir>/mebular-tasks,测试/自定义用)
10
+
11
+ import { existsSync } from 'node:fs';
12
+ import { cp, mkdir } from 'node:fs/promises';
13
+ import { homedir } from 'node:os';
14
+ import { dirname, join } from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+
17
+ const pkgRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
18
+ const SKILL_NAME = 'mebular-memory';
19
+ const TASK_SKILL_NAME = 'mebular-tasks';
20
+
21
+ function parseFlags(argv) {
22
+ const flags = {};
23
+ for (let i = 0; i < argv.length; i++) {
24
+ const token = argv[i];
25
+ if (token.startsWith('--')) {
26
+ const key = token.slice(2);
27
+ const next = argv[i + 1];
28
+ if (next === undefined || next.startsWith('--')) flags[key] = true;
29
+ else {
30
+ flags[key] = next;
31
+ i++;
32
+ }
33
+ }
34
+ }
35
+ return flags;
36
+ }
37
+
38
+ const flags = parseFlags(process.argv.slice(2));
39
+ const cwd = process.cwd();
40
+ const targets = [];
41
+ if (typeof flags.target === 'string') {
42
+ targets.push(flags.target);
43
+ } else {
44
+ targets.push(join(cwd, '.agents', 'skills'));
45
+ targets.push(join(cwd, '.dsh', 'skills'));
46
+ if (existsSync(join(cwd, '.opencode'))) targets.push(join(cwd, '.opencode', 'skills'));
47
+ if (flags.global === true) targets.push(join(homedir(), '.agents', 'skills'));
48
+ }
49
+
50
+ const installed = [];
51
+ for (const target of targets) {
52
+ const dest = join(target, SKILL_NAME);
53
+ await mkdir(dest, { recursive: true });
54
+ await cp(join(pkgRoot, 'SKILL.md'), join(dest, 'SKILL.md'));
55
+ await cp(join(pkgRoot, 'MEMORY_POLICY.md'), join(dest, 'MEMORY_POLICY.md'));
56
+ // A:部署手册随 Skill 一起安装(Agent 据此可自动部署/加入)
57
+ await cp(join(pkgRoot, 'SETUP.md'), join(dest, 'SETUP.md'));
58
+ // G1:接入片段随 Skill 一起安装(保持 SKILL.md「见 mcp/」的承诺成立)
59
+ await cp(join(pkgRoot, 'mcp'), join(dest, 'mcp'), { recursive: true });
60
+ installed.push(dest);
61
+ console.log(`installed ${dest}`);
62
+
63
+ // R3:任务面 skill(与记忆面并列安装)
64
+ const taskDest = join(target, TASK_SKILL_NAME);
65
+ await mkdir(taskDest, { recursive: true });
66
+ await cp(join(pkgRoot, 'tasks', 'SKILL.md'), join(taskDest, 'SKILL.md'));
67
+ await cp(join(pkgRoot, 'SETUP.md'), join(taskDest, 'SETUP.md'));
68
+ installed.push(taskDest);
69
+ console.log(`installed ${taskDest}`);
70
+ }
71
+
72
+ if (installed.length === 0) {
73
+ console.error('没有可安装的目标目录');
74
+ process.exit(1);
75
+ }
76
+ console.log(JSON.stringify({ skill: SKILL_NAME, installed }, null, 2));
package/tasks/SKILL.md ADDED
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: mebular-tasks
3
+ description: 通过 Mebular MCP 的任务面把活派给别的设备上的 Agent:任务树/DAG 派生、协商、进度跟踪、配额与公平准入。
4
+ whenToUse: 需要把活派给别的设备上的 Agent、跨设备协作、子任务分解、与其它 Agent 协商、看任务进度时。
5
+ ---
6
+
7
+ # Mebular Tasks
8
+
9
+ 任务面与记忆面**共用同一个 MCP 入口**(`mebular mcp` / HTTP `/mcp`,29 工具中的 16 个 `task_*`/`chatter_*`/`board_create`)。
10
+ 任务与记忆共用同一条加密记忆通道传输,但**任务不是记忆**(见 §6)。
11
+
12
+ ## 1. 何时派活(而不是自己做)
13
+
14
+ 派活,当且仅当:活需要**另一台设备**上的能力/数据(如某台机器的本地文件、某 Agent 的专属工具),或需要**并行/长期**
15
+ 执行而本机不适合占用。反之自己做:一次性、纯本机、无跨设备价值的工作——派活有传输与订阅成本。
16
+
17
+ 判定要点:`task_targets` 里出现合适对象 → 派;没有任何对象 → 先解决订阅/发现,而不是硬发。
18
+
19
+ ## 2. `task_submit` 字段语义(root 或 child)
20
+
21
+ | 字段 | 语义 |
22
+ |---|---|
23
+ | `intent` | 必填。要做什么(自然语言,写给执行方 Agent 看)。 |
24
+ | `to` | 必填。`{ device, agent }`:目标设备与目标 Agent(Agent 名来自对方目录,见 `task_targets`)。 |
25
+ | `payloadRef` | 可选。大负载的**引用**(如记忆节点 id / 文件路径),避免把负载塞进任务体。 |
26
+ | `expiresAt` | 可选。过期时间(epoch ms);过期后不再作为有效任务推进。 |
27
+ | `causedBy` | 可选。把本任务挂到**上游事件/任务**上(因果关系可追溯)。 |
28
+ | `chain` | 可选。链上祖先列表(协助防环与审计;链长上限由预算强制)。 |
29
+ | `budget` | 可选(仅 root)。`{ maxDepth, maxChildren, maxTasks }`:子任务派生预算。 |
30
+ | `dispatch` | 可选(仅 root)。`children-ok`(默认可派生)或 `root-only`(禁止派生)。 |
31
+
32
+ 示例(把「整理会议记录」派给 device-B 的 writer):
33
+
34
+ ```json
35
+ { "intent": "把本周会议记录整理成纪要并回传要点", "to": { "device": "device-B", "agent": "writer" },
36
+ "payloadRef": "<memory-node-id>", "budget": { "maxDepth": 2, "maxChildren": 5, "maxTasks": 20 } }
37
+ ```
38
+
39
+ ## 3. 跟踪进度
40
+
41
+ - `task_status`:单个任务的状态/尝试次数/最近事件。
42
+ - `task_children`:某个任务的子任务(树/DAG 展开)。
43
+ - `task_summarize`:子树摘要(快速看整体做完没)。
44
+ - `task_subscribe`:订阅事件(后续推进以事件送达,不必轮询)。
45
+ - `task_list` / `task_history`:本机视角的任务清单与历史事件。
46
+
47
+ ## 4. 协作三形态与配额
48
+
49
+ 1. **DAG 派生**:子任务经 `causedBy`/`chain` 挂在父任务下(受 `budget` 与链长上限约束)。
50
+ 2. **协商**(`task_negotiate`):与对端 Agent 就范围/代价/交付达成一致后再提交。
51
+ 3. **轻量沟通**(`chatter_send` / `chatter_inbox`):无需建任务的短消息。
52
+
53
+ 配额与建板:`task_quota`(本机对每设备的本地记账与上限)· `task_targets`(可派对象)· `board_create`(建板 = 建域 +
54
+ 双方订阅)。
55
+
56
+ ## 5. 失败处理与非幂等
57
+
58
+ - `task_retry`:重试失败任务;`task_cancel`:取消。
59
+ - **`task_submit` 非幂等**:重复提交 = **新任务**(不会去重)。网络超时后重发前,先 `task_list`/`task_history`
60
+ 确认是否已受理;需要关联同一意图时用 `causedBy`/`chain` 串起来。
61
+
62
+ ## 6. 与记忆面的边界
63
+
64
+ - 任务面是**树/DAG + 事件流**(`task_*` 事件);记忆面是**类型化图**(fact/episode/skill/...)。
65
+ - 任务经**记忆通道传输**(同一加密会话),但**不是记忆**:不要把任务当成记忆去 `memory_query`,也不要把
66
+ 「派活」写进记忆节点。
67
+ - 结果交付:执行方把**结果引用**(`payloadRef`/结果事件)回传;需要长期留存的知识再显式写入记忆面。
68
+
69
+ ## 7. 发现:我能派给谁
70
+
71
+ `task_targets` = **订阅任务域的对端 ∩ 对方 Agent 目录**(返回 `{ device, agent }` 列表)。没有出现的目标**不要**试着
72
+ 绕道派活(不会成功,且是越权)。
73
+
74
+ ## 8. 红线(自动机制,不得绕过)
75
+
76
+ - **预算递减**:子任务预算从父任务扣减,`maxTasks/maxChildren/maxDepth` 越界即被拒。
77
+ - **链长上限**:`chain` 过长会被拒(防无界递归)。
78
+ - **公平准入**:配额与本地记账由系统强制,Agent 不得伪造/复用他人配额。
79
+ - 不要试图在 `payloadRef` 里夹带凭据/密钥;身份与订阅由包层负责,任务体不是权限通道。
80
+
81
+ CLI 等价(同一 handler):`mebular task_submit` / `fleet task_submit`(同名同参),便于脚本与非 MCP 场景。
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.