@fanchao8609/agent_brain_sync 1.7.1 → 1.7.3

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/bin/abs.js CHANGED
@@ -83,6 +83,9 @@ const FLAG_SPEC = {
83
83
  'no-skill': { type: 'boolean' },
84
84
  };
85
85
 
86
+ /** 已被"规范键"接管的 raw flag:不再原样漏出(见 parseArgv 返回处的白名单注释)。 */
87
+ const KNOWN_RAW = new Set(['keep-days', 'dry-run', 'no-mcp', 'no-skill']);
88
+
86
89
  function parseArgv(args) {
87
90
  // 坑: parseArgs 会把**任何** `-` 开头的 token 当选项,连正文一起吃:
88
91
  // `abs note "-X 是个坑"` → values={X:true,' ':true,是:true,…},正文全丢(旧手写版只认 `--` 长选项)。
@@ -125,17 +128,39 @@ function parseArgv(args) {
125
128
  if (missing.length) {
126
129
  throw new Error(`✗ ${missing.join('、')} 缺少值\n 用法: --<flag> <值>(如 --dir /path/to/project)`);
127
130
  }
131
+ // 只输出**读者实际用的**规范形状:camelCase 键 + mcp/skill 正向布尔。
132
+ // 坑(OPTS-DOUBLE-KEYS): 曾 `...values` 之后再叠加 camelCase → opts 同时带两份 key
133
+ // (keep-days 与 keepDays、no-mcp 与 mcp),读者得自己猜哪份算数。raw 键无人读,
134
+ // 属纯噪音(grep 验证:opts['keep-days'] 零引用)。
135
+ // 用显式白名单而非 ...values:新增 flag 必须在此声明一次,否则"声明了却没接线"
136
+ // 会静默变成"读不到",而不是意外漏出一个无名键。
128
137
  const o = {
129
- ...values,
130
138
  _: positionals,
139
+ dir: values.dir,
140
+ agent: values.agent,
141
+ id: values.id,
142
+ section: values.section,
143
+ note: values.note,
144
+ as: values.as,
145
+ payload: values.payload,
146
+ tags: values.tags,
147
+ help: !!values.help,
148
+ yes: !!values.yes,
149
+ repair: !!values.repair,
150
+ full: !!values.full,
131
151
  keepDays: values['keep-days'],
132
- dryRun: values['dry-run'],
152
+ dryRun: !!values['dry-run'],
153
+ mcp: !values['no-mcp'],
154
+ skill: !values['no-skill'],
133
155
  };
134
- if (values['no-mcp']) o.mcp = false;
135
- if (values['no-skill']) o.skill = false;
156
+ // 未声明的 `--unknown` 静默收下(旧行为:不进位置参数,也不报错)。
157
+ // 这条保留是因为 rejectExtra 只看位置参数 —— 把未知 flag 放进去会改成报错,
158
+ // 那是另一个行为变更,不在本次范围内。
159
+ for (const [k, v] of Object.entries(values)) {
160
+ if (!(k in o) && !KNOWN_RAW.has(k)) o[k] = v;
161
+ }
136
162
  return o;
137
163
  }
138
-
139
164
  const usage = `abs — agent-brain-sync 记忆工具
140
165
 
141
166
  读:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanchao8609/agent_brain_sync",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "agent-brain-sync: 跨会话 AI 编码记忆 — hook 纯触发 + CLI/MCP 读写 .brain markdown 图谱, 防并发写保护。",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/skill/SKILL.md CHANGED
@@ -145,16 +145,25 @@ monorepo 若多个子包各自独立交付,可各建一份 `.brain/`。`abs st
145
145
  图谱已存在;收到第一个核心开发指令**之前**走这条链载入上下文:
146
146
 
147
147
  1. **读状态**:`abs load`(或 MCP `abs_load`)读 index 路线 + todo 看板 + 最近 log。
148
- > **Done 区是折叠的(按日期计数)**,不是全量 —— Done 是无上限增长的归档区,
149
- > 全量打印会随项目历史线性膨胀,把上下文塞满(曾占 load 输出 68.8%,
150
- > 长历史项目上单次 load 吃掉 40% 上下文)。
151
- > 要 Done 明细:`abs todo --full`,或看 `.brain/sessions/<日期>-todo归档.md`。
152
- > 「最近动作」每条也按语义边界收口 —— 续接只需线索,不需要日志全文。
148
+ > **load 输出是折叠过的,不是全量。** 两个无上限增长的区块在读取侧收口:
149
+ > - **Done 区** → 按日期计数(曾占 load 输出 68.8%,长历史项目上单次 load 吃掉 40% 上下文)
150
+ > - **index 页面清单** → 各分区只给页数(concept 清单占 load 输出 64%,隨图谱线性增长)
151
+ > - 「最近动作」每条按语义边界收口到 220 字符
152
+ >
153
+ > **路线(Roadmap)区原样保留** —— 那是 load 要传达的状态本身。
154
+ > 要全量明细:`abs todo --full` / `abs index`,或直接读 `.brain/` 文件、
155
+ > `.brain/sessions/<日期>-todo归档.md`。
153
156
  2. **对账滞留(强制,别跳过)**:若 `abs load` 顶部出现 `⏳ 上会话滞留`,说明上会话有任务做完/做到一半就断了。**先收尾再开工**:
154
157
  - 快照里的任务现在真做完了 → `abs todo done <id>`(done 后下次 load 滞留自动消失);
155
158
  - 还没做完 → `abs todo note <id> --note "接到哪/改到哪个文件"` 补断点(别空手续接)。
156
159
  滞留没清完就不算接上了状态——这是「任务做完没进 Done」的根治动作。
157
160
  3. **读命中页**:按关键词在 index 定位 → 读对应 concepts/entities 全文。
161
+ > ⚠️ **绝不通读 `.brain/`**。它是一个不断长大的知识图谱,当前仓库 29 页就约 11 万 token
162
+ > (单页最大 16KB)—— 全读会把窗口直接塞满。正确姿势:
163
+ > - 要状态 → `abs load`|要主题 → `abs query <词>`(只回命中几页)
164
+ > - 要某页 → 只读那一页;页太长则只取相关小节
165
+ > - 需要汇总多页/多命令时,用 context-mode 的 `ctx_execute` 类工具在沙箱里处理后
166
+ > **只打印结论**,别把原始文件内容拉进上下文。
158
167
  4. **续 todo**:默认续 todo 分支 → 把顶部未完成项当当前任务开做。
159
168
  5. **登记新任务**:有明确新任务而 todo 没有 → `abs todo add <id> --note 做什么` 登记
160
169
  再动工。不登记,会话一切断就丢。
package/src/store.js CHANGED
@@ -179,7 +179,7 @@ export async function cmdLoad({ dir }) {
179
179
  }
180
180
  sections.push(
181
181
  '--- 当前路线 (index.md) ---',
182
- index || '(index.md 为空)',
182
+ collapseIndex(index) || '(index.md 为空)',
183
183
  '',
184
184
  '--- Todo 看板 (todo.md) ---',
185
185
  collapseDone(todo).text || '(todo.md 为空)',
@@ -205,6 +205,47 @@ export async function cmdLoad({ dir }) {
205
205
  return sections.join('\n');
206
206
  }
207
207
 
208
+ /** index.md 在 `abs load` 里的折叠形态:保留「当前路线」(那是 load 要传达的状态,
209
+ * 且有界),把页面清单各分区折成计数。
210
+ *
211
+ * 坑: index 的 concept 清单带每一页的一句话描述,**隨图谱线性增长** —— 本仓库 17 条
212
+ * 占 load 输出 2286/3571 tok(64%),另一台 40 条的项目约 2.3 倍。它刚成了 Done 之后
213
+ * 最大的单体膨胀源(Done 已折叠,见 collapseDone)。
214
+ *
215
+ * 续接真正需要的只是「有哪些分区、各多少页」(据此知道去哪找),不需要每页写了什么 ——
216
+ * 要那个用 `abs index`(或直接读 index.md / 按词 `abs query`)。
217
+ * `## 当前路线` 不折(它是路线内容本身,非清单)。 */
218
+ export function collapseIndex(text) {
219
+ const s = String(text || '').trim();
220
+ if (!s) return '';
221
+ const out = [];
222
+ let mode = null; // null=逐行透传(路线区/文件头);字符串=当前在计数的分区名
223
+ let n = 0; // mode 非 null 时的清单行计数
224
+ const flush = () => {
225
+ if (mode !== null) out.push(n ? `## ${mode}(${n} 页)` : `## ${mode}`);
226
+ mode = null;
227
+ n = 0;
228
+ };
229
+ for (const l of s.split('\n')) {
230
+ const m = l.match(/^##\s+(.+?)\s*$/);
231
+ if (m) {
232
+ flush();
233
+ const name = m[1].trim();
234
+ if (/路线|Roadmap/i.test(name)) {
235
+ out.push(l); // 「当前路线」是内容不是清单:原样保留
236
+ mode = null;
237
+ } else {
238
+ mode = name; // 页面清单分区:只计数
239
+ }
240
+ continue;
241
+ }
242
+ if (mode === null) out.push(l); // 透传区(含文件头 H1、路线区正文)
243
+ else if (l.trim().startsWith('-')) n++;
244
+ }
245
+ flush();
246
+ return out.join('\n').replace(/\n{3,}/g, '\n\n').trim();
247
+ }
248
+
208
249
  // ---------- wrapup: 滞留快照(B)/ load 内展示由 cmdLoad 完成(A) ----------
209
250
  export async function cmdWrapup({ dir }) {
210
251
  const root = await requireBrain(dir || process.cwd());