@fanchao8609/agent_brain_sync 1.26.0 → 1.27.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/README.md CHANGED
@@ -122,11 +122,11 @@ abs log "完成 X" # 记一行流水;abs log 无参 =
122
122
  abs query <词> # 检索图谱(多词 OR);已被推翻的经验默认隐藏(--all 可看)
123
123
  abs capture [--layer 1-6] [--kind …] "一句话" # 按七层判层后落到位(L7 用 abs note;--kind: gotcha|decision|tradeoff|howto)
124
124
  abs db rebuild # 扫所有登记项目 → 建图数据库(~/.abs/graph.db)
125
- abs db search <词> [--full] [--no-rules] # 走库检索:亮度排序+跨项目;--full 附正文,--no-rules 省铁律
125
+ abs search <词> [--full] [--rules] # 检索:亮度排序+跨项目;--full 附正文,--rules 带铁律
126
126
  abs db status # 库体检:七层分布 / 悬挂链接 / 已入库项目
127
127
  abs db add # 把当前项目登记进 ~/.abs/projects.json
128
128
  abs db evolve # 知识进化体检:被推翻/断链/主题堆积/僵化页
129
- abs summon [--status] # 列出还没落页的会话(只读,不写盘)
129
+ abs ingest --list # 列出还没落页的会话(只读,不写盘)
130
130
  abs ingest <会话文件或 id> # 把一场 pi 会话落成会话页(session-id 双向回溯)
131
131
  # 已填 → 亮度×0.5;未填 → 整页不进检索
132
132
  abs resolve <页名或id> # 反查页面路径(页改名后 id 不变)
package/bin/abs.js CHANGED
@@ -151,6 +151,8 @@ const FLAG_SPEC = {
151
151
  'force': { type: 'boolean' },
152
152
  // ingest 用:--last 取最近一场会话(hook 在 session_shutdown 调,不用给 id);
153
153
  // --auto 只落真改过文件的会话(纯聊天不落页)。
154
+ // ingest 用:--list 只看「哪些会话没落页」不写入(原 abs summon 的职责)
155
+ 'list': { type: 'boolean' },
154
156
  'last': { type: 'boolean' },
155
157
  'auto': { type: 'boolean' },
156
158
  // db search 用:不输出 L1 铁律(查主题时它们是噪音;开工看铁律是 load 的职责)。
@@ -247,36 +249,51 @@ function parseArgv(args) {
247
249
  }
248
250
  return o;
249
251
  }
250
- const usage = `abs — 跨会话记忆工具(.brain/ 图谱)
252
+ const usage = `abs — 跨会话记忆(.brain/ 图谱)
251
253
 
252
- 常用:
253
- abs load 开工先跑: 读状态、接上次的活
254
- abs todo add X --note "做什么" 登记任务 (done/state/note 管后续)
255
- abs note "经验一句话" 随手记经验; abs log "完成 X" 记成果
256
- abs query <词…> 检索 .brain/; abs todo 看任务板
257
- abs recall [词…] 卡住时主动取相关页(不给词就按当前处境推)
254
+ 怎么用:按你要做的事找,不用记命令名。旧名都还能用,会自动提示新名。
258
255
 
259
- 全部命令 (细节: abs <命令> --help):
260
- init [--repair] 建图谱 (当前目录)
261
- load 开机读状态
262
- todo 任务看板 (add/note/state/done/archive)
263
- index | log | status 索引 / 流水 / 概要
264
- note <经验> [--tags a,b] 经验暂存 → sources/
265
- capture [--layer 1-6] "…" 按层判定落点后直接写入 (不传=L4; L7 用 abs note)
266
- summon [--mark|--status] 会话总结托底: 列出未总结/有更新的会话 (不写盘)
267
- ingest <会话文件> 把一场 pi 会话落成会话页 (带 session id 双向回溯)
268
- concept <slug> --title … 建概念页骨架
269
- query <词…> [--all] 检索知识页 (多词 OR)
270
- db rebuild|search|status|evolve 图数据库: 建库 / 亮度搜索 / 体检 / 进化体检
271
- resolve <页名…> 反查页面路径
272
- supersede <页名> [--by 页] 标经验已失效
273
- review [--accept 页…|--reject 页…] 待确认页队列 (draft 升 active/否决)
274
- lint 图谱体检 (死链/超限)
275
- rule [add "一句话"] 硬规则读写
276
- install|uninstall [--agent <宿主>] [--no-mcp] [--no-skill]
277
- update 升级并刷新 hook/skill
278
- config [set user <名字>] 使用者姓名 (写操作需先设置)
279
- --version | help 版本 / 本帮助
256
+ 【开工】读状态,接上次的活
257
+ abs load 必跑。Rules + 图谱计数 + 任务板 + 最近流水
258
+ abs recall [词…] 卡住时用:按当前处境推相关页(不给词也行)
259
+
260
+ 【找东西】
261
+ abs search <词> 推荐。亮度排序 + 邻居扩散 + 跨项目
262
+ abs query <词…> [--all] 要字面精确时用:多词 OR,输出更短
263
+ abs resolve <页名…> 有了页名,反查文件路径
264
+
265
+ 【写知识】(三者落点不同,别混)
266
+ abs note "一句话" 随手一句经验 → sources/ 待提炼
267
+ abs concept <slug> --title "…" 要成页 → concepts/(自动带四段骨架)
268
+ abs rule add "一句话" 要约束 → index 的 Rules(≤42 字)
269
+
270
+ 【写任务】
271
+ abs todo 看板
272
+ abs todo add <id> --note "做什么"
273
+ abs todo note <id> --note "进度" 追加子项
274
+ abs todo done <id> --as 落地|否决|仅方案 [结语]
275
+ abs todo state <id> --note 进行中|讨论中|滞留中|搁置
276
+ abs todo remove <id> 删除(连子项,不可恢复)
277
+
278
+ 【会话】
279
+ abs ingest [--list] 把一场 pi 会话落成结构化页;--list 看还有哪些没落
280
+
281
+ 【维护】
282
+ abs lint 体检:死链 / 超限 / 待提炼
283
+ abs review 待确认的 draft 页(升 active 或否决)
284
+ abs supersede <页> --by <新页> 标经验已失效(不删文件)
285
+ abs show index|log|status 看完整索引 / 流水 / 概要
286
+ abs db rebuild|status|evolve 重建库 / 库体检 / 进化体检
287
+ abs init [--repair] 建图谱
288
+
289
+ 【其它】
290
+ abs install|uninstall [--agent <宿主>] [--no-mcp] [--no-skill]
291
+ abs update 升级并刷新 hook/skill
292
+ abs config set user <名字> 使用者姓名(写操作需先设置)
293
+
294
+ 旧名(仍可用,会提示新名):
295
+ index/log/status → show | capture → concept | db search → search
296
+ summon → ingest --list | db add → init
280
297
 
281
298
  注: wrapup / teardown-check 是 hook 内部命令。
282
299
  `;
@@ -351,6 +368,7 @@ const subUsage = {
351
368
  ' abs todo child-undone <id> [--n N] 取消勾',
352
369
  ' abs todo memo <id> "随手记(可多句)" 任务笔记 → sessions/,不上看板;无文字=查看',
353
370
  ' abs todo state <id> --note 进行中|讨论中|滞留中|搁置',
371
+ ' abs todo remove <id> 删除任务(连子项,不可恢复;只是先不做请用 state 搁置)',
354
372
  ' abs todo done <id> [--as 落地|否决|仅方案] [结语文字]',
355
373
  ' abs todo archive [--keep-days N] [--dry-run]',
356
374
  '',
@@ -431,6 +449,12 @@ const TODO_ACTIONS = {
431
449
  state: 'state', // 改行首状态标记:进行中|讨论中|滞留中|搁置(原地,不搬区)
432
450
  rename: 'rename', // 改任务 id:人工起错名、或旧 id 不可读时用
433
451
  done: 'done',
452
+ // 删除任务(2026-11-05 用户要求):连子项一起移除,不可恢复。
453
+ // 与 state=搁置 语义不同 —— 搁置是「先不做,还留在看板上」,删除是「从未登记过」。
454
+ // rm 是别名:用户说「删除」时想敲的通常是 rm/del。
455
+ remove: 'remove',
456
+ rm: 'remove',
457
+ del: 'remove',
434
458
  };
435
459
 
436
460
  /** abs config —— 读/写用户设置(目前只有 user)。 */
@@ -486,26 +510,70 @@ async function main() {
486
510
  rejectExtra(opts._, 'abs load');
487
511
  console.log(await cmdLoad({ dir: opts.dir }));
488
512
  break;
513
+ // 顶层 search(2026-11-06):MCP 侧一直叫 abs_search,CLI 却要敲 `db search` —— 名实不符。
514
+ // 现在 CLI 与 MCP 同名,`db search` 保留为别名(转指向这里并提示一次)。
515
+ case 'search': {
516
+ if (opts.help) {
517
+ console.log('abs search — 按亮度检索知识图谱\n\n'
518
+ + '用法: abs search <词> [--limit N] [--full] [--no-rules] [--rules]\n\n'
519
+ + ' 亮度排序 + 邻居扩散 + 跨项目(标 [跨项目])。\n'
520
+ + ' 默认省略 L1 铁律(开工时 abs load 会给);要看加 --rules。\n'
521
+ + ' --full 附正文;--limit 最多几页(默认 8)。\n\n'
522
+ + '与 abs query 的区别:这是详略两档不是重复 ——\n'
523
+ + ' query 给字面 OR 命中的页名+摘要,最省 token;\n'
524
+ + ' search 给亮度与扩散,找「我上次怎么解决 X」更准。');
525
+ break;
526
+ }
527
+ if (!opts._.length) throw new Error('✗ 缺检索词\n 用法: abs search <词> [--limit N] [--full] [--no-rules]');
528
+ // 顶层 search 默认省略铁律(2026-11-06):它是「查一个主题」的工具,
529
+ // 18 条铁律占输出近一半、每次都是噪音。要看铁律显式 --rules,或跑 abs load。
530
+ // db search 那个别名仍保持旧默认(带铁律),不改变老脚本的行为。
531
+ console.log(await cmdDbSearch({
532
+ query: opts._.join(' '), limit: Number(opts.limit) || 8,
533
+ full: !!opts.full, noRules: !opts.rules, cmdName: 'search',
534
+ }));
535
+ break;
536
+ }
489
537
  case 'recall': {
490
538
  const limit = Number(opts.limit) > 0 ? Number(opts.limit) : 5;
491
539
  console.log(await cmdRecall({ dir: opts.dir, terms: opts._, limit }));
492
540
  break;
493
541
  }
542
+ // ── 只读视图:统一到 abs show <视图>,旧名保留为别名并提示 ──
543
+ // (2026-11-06 命令面整理:index/log/status 都是「看某个文件的现状」,
544
+ // 三个顶层命令占三个名额却只有一个心智动作 —— 看。合成 show 一个入口。)
545
+ case 'show': {
546
+ const v = opts._[0];
547
+ if (!v) {
548
+ console.log('用法: abs show index|log|status\n index=完整索引 log=操作流水 status=图谱概要');
549
+ break;
550
+ }
551
+ rejectExtra(opts._.slice(1), 'abs show index|log|status');
552
+ if (v === 'status') console.log(await cmdStatus({ dir: opts.dir }));
553
+ else if (v === 'index' || v === 'log') console.log(await cmdShow({ dir: opts.dir, view: v }));
554
+ else console.log(`✗ 未知视图 "${v}"。可用: index | log | status`);
555
+ break;
556
+ }
494
557
  case 'index':
495
558
  rejectExtra(opts._, 'abs index');
559
+ console.log('(abs index 已改名 → abs show index)');
496
560
  console.log(await cmdShow({ dir: opts.dir, view: 'index' }));
497
561
  break;
498
562
  case 'log': {
499
563
  // 无参=查看 log.md;带参=追加一行 (用户/AI 主动记; hook 生命周期事件走技术日志 hooks.log, 不经这里)
564
+ // ★ log 有双职责,不能并进 show:带参时它是**写**操作。
565
+ // 所以只把「无参查看」这一半指向 show,写的那半保持不变、也不提示改名。
500
566
  if (opts._.length) {
501
567
  console.log(await cmdLog({ dir: opts.dir, title: opts._.join(' '), kind: opts.kind }));
502
568
  } else {
569
+ console.log('(查看流水已改名 → abs show log;abs log "完成 X" 仍是记成果)');
503
570
  console.log(await cmdShow({ dir: opts.dir, view: 'log' }));
504
571
  }
505
572
  break;
506
573
  }
507
574
  case 'status':
508
575
  rejectExtra(opts._, 'abs status');
576
+ console.log('(abs status 已改名 → abs show status)');
509
577
  console.log(await cmdStatus({ dir: opts.dir }));
510
578
  break;
511
579
  // abs todo —— 无子命令=看板;带子命令=任务写操作
@@ -565,10 +633,18 @@ async function main() {
565
633
  break;
566
634
  }
567
635
  case 'summon': {
636
+ // 别名(2026-11-06):并进 ingest --list —— 两者是同一件事的两半
637
+ // (summon 说「哪些没落页」,ingest 负责落)。分两个顶层命令只是多记一个词。
638
+ console.log('(abs summon 已改名 → abs ingest --list)');
568
639
  console.log(await cmdSummon({ dir: opts.dir, mark: !!opts.mark, full: !!opts.full, status: !!opts.status, limit: Number(opts.limit) || 15 }));
569
640
  break;
570
641
  }
571
642
  case 'ingest': {
643
+ // --list:只看「还有哪些会话没落页」,不写入(原来的 abs summon)
644
+ if (opts.list) {
645
+ console.log(await cmdSummon({ dir: opts.dir, mark: false, full: !!opts.full, status: false, limit: Number(opts.limit) || 15 }));
646
+ break;
647
+ }
572
648
  console.log(await cmdIngest({
573
649
  dir: opts.dir, file: opts._.join(' '), force: !!opts.force, mark: !!opts.mark,
574
650
  last: !!opts.last, auto: !!opts.auto, session: opts.session,
@@ -621,7 +697,13 @@ async function main() {
621
697
  const sub = opts._[0];
622
698
  const rest = opts._.slice(1);
623
699
  if (sub === 'rebuild') { console.log(await cmdDbRebuild({ dir: opts.dir })); break; }
624
- if (sub === 'search') { console.log(await cmdDbSearch({ query: rest.join(' '), limit: Number(opts.limit) || 8, full: !!opts.full, noRules: !!opts['no-rules'] })); break; }
700
+ if (sub === 'search') {
701
+ // 别名(2026-11-06):顶层已改叫 abs search。留着是为了不打断现有习惯与脚本,
702
+ // 但每次提示一次 —— 不提示的话旧名会永远活着,命令面又变宽。
703
+ console.log('(abs db search 已改名 → abs search)');
704
+ console.log(await cmdDbSearch({ query: rest.join(' '), limit: Number(opts.limit) || 8, full: !!opts.full, noRules: !!opts['no-rules'] }));
705
+ break;
706
+ }
625
707
  if (sub === 'status') { console.log(await cmdDbStatus()); break; }
626
708
  if (sub === 'evolve') { console.log(await cmdDbEvolve({ staleDays: Number(opts.staleDays) || 90 })); break; }
627
709
  if (sub === 'add') {
package/bin/mcp.js CHANGED
@@ -117,10 +117,10 @@ tool(
117
117
  'abs_task',
118
118
  '任务实时落盘(幂等键 = id)。start 登记进 Todo / note 补子项(**追加**,标准 md 嵌套列表,`abs todo note`)/ child_done、child_undone 勾/取消勾子项(n=第几条,缺省最后一条)/ memo 任务随手记(多句/追加/不上看板)/ state 改状态 / done 完成归位 Done(done 时 note=结语文字,as=结语类型:落地|否决|仅方案)。必填: cwd, action, id。多会话并行时,start/add 带上 session(值见 system prompt 的 [会话] 段)以标记「这条任务谁在做」。',
119
119
  {
120
- action: z.enum(['add', 'start', 'done', 'note', 'child_done', 'child_undone', 'memo', 'state']),
120
+ action: z.enum(['add', 'start', 'done', 'note', 'child_done', 'child_undone', 'memo', 'state', 'remove']),
121
121
  id: z.string().describe('任务幂等键,如 TASK-xxx 或子任务名'),
122
122
  n: z.number().int().positive().optional().describe('child_done/child_undone 用:第几条子项(1-based,缺省=最后一条)'),
123
- cwd: z.string().describe('项目根目录(.brain/ 所在处)'), note: z.string().optional().describe('add/start=做什么; note=追加一条子项(改到哪/下一步,一句话); memo=随手记(可多句、不定长,追加式;不传=查看已有笔记); state=进行中|讨论中|滞留中|搁置(搁置=用户改方向/不做了;滞留中=还要做只是卡住); done=结语文字'),
123
+ cwd: z.string().describe('项目根目录(.brain/ 所在处)'), note: z.string().optional().describe('add/start=做什么; note=追加一条子项(改到哪/下一步,一句话); memo=随手记(可多句、不定长,追加式;不传=查看已有笔记); state=进行中|讨论中|滞留中|搁置(搁置=用户改方向/不做了;滞留中=还要做只是卡住); done=结语文字(remove 不用此字段)'),
124
124
  as: z.enum(['落地', '否决', '仅方案']).optional().describe('仅 done:结语类型。默认 落地。做了又撤/评估后不做用 否决,只设计过用 仅方案 —— 别让假【落地】污染看板'),
125
125
  // 会话 id:多会话并行时标记「这条任务是谁在做」。
126
126
  // 值取自 system prompt 里的 `[会话] 本会话 id = xxx`(hook 注入),由模型原样回传。
package/hooks/abs.pi.ts CHANGED
@@ -307,9 +307,25 @@ async function hasBrain(cwd: string): Promise<boolean> {
307
307
  * 07:40:17 agent_end load_delivered cwd=~/.agents ← 置位
308
308
  * 07:40:43 before_agent_start load_guide=skip cwd=agent_brain_sync ← ✗ 被跳过
309
309
  * 而 pi 一个会话里 `turn_end` 会在多个 cwd 间交替(多个项目目录同时挂着)。
310
- * **不要再改回单个布尔量** —— 一改回去就重现「在 A 说过话,B 再也看不到 load」。 */
310
+ * **不要再改回单个布尔量** —— 一改回去就重现「在 A 说过话,B 再也看不到 load」。
311
+ *
312
+ * ★ 语义三:**按「会话 + 目录」分,不是只按目录**(2026-11-06 用户实报后修的第三个 bug)。
313
+ * 病根:这个 Set 只在 `session_start` 清空,而**一个会话可能持续好几天、跨几十次 cwd 切换**,
314
+ * 期间的 `new`(在同一进程里新建会话)不一定重发带 ctx 的 `session_start`。
315
+ * 于是某个目录只要注入过一次,此后整个进程生命周期里永远 skip。
316
+ * 日志实证(~/.abs/log/hooks.log 2026-11-06):agent_brain_sync 出现 4 次全是 skip,
317
+ * 一次 on 都没有;而 Code/ren 连着 3 次 on。用户原话:
318
+ * 「用 new 开新会话,没有主动运行 abs,只有当我输入 abs 的时候铁律和知识才加载进来」。
319
+ * 修法:key 带上会话 id —— 换会话就该重新摆一次开局状态。
320
+ * **不要再改回只按 cwd** —— 那就重现「新会话开局是空的」。 */
311
321
  const loadInjected = new Set<string>()
312
322
 
323
+ /** 注入去重用的 key:会话 id + cwd。
324
+ * 会话 id 取不到时退化为纯 cwd(老行为,至少不会因空 id 而每轮重注入刷屏)。 */
325
+ function loadKeyOf(cwd: string, sid: string): string {
326
+ return sid ? `${sid}::${cwd}` : cwd
327
+ }
328
+
313
329
  /** 本轮已注入 load、正等 `agent_end` 确认送达的 **cwd**(见 loadInjected 的注解)。
314
330
  * 与 loadInjected 的分工:这是「抛出去了」,那是「对方接到了」。
315
331
  * 空串 = 无待确认(不用 null,避免每次都要判空类型)。 */
@@ -1175,7 +1191,8 @@ export default function absPiHook(pi: ExtensionAPI): void {
1175
1191
  // 注意这里**不置 loadInjected** —— 注入点只是在 prompt 提交后、agent loop 前,
1176
1192
  // 对话还没发出去;此刻置位会让被中断的那轮白烧掉标记(见 loadInjected 注解)。
1177
1193
  let loadState = 'skip'
1178
- if (!loadInjected.has(cwd)) {
1194
+ const loadKey = loadKeyOf(cwd, sidNow)
1195
+ if (!loadInjected.has(loadKey)) {
1179
1196
  const loadText = await readLoadForGuide(cwd)
1180
1197
  // 首轮硬规则(方案 B,2026-10-06)—— 与 load 同一机会(同目录只一次)。
1181
1198
  // 为何挂在这里而不另设 flag:两者都是「开工那一刻只说一次」,
@@ -1183,11 +1200,11 @@ export default function absPiHook(pi: ExtensionAPI): void {
1183
1200
  const rulesOn = injectOpeningRules(event?.systemPromptOptions)
1184
1201
  if (loadText) {
1185
1202
  injectLoadGuideline(event?.systemPromptOptions, loadText)
1186
- loadPending = cwd // 送达确认交给 agent_end
1203
+ loadPending = loadKey // 送达确认交给 agent_end(key 与注入判定同源)
1187
1204
  loadState = 'on'
1188
1205
  } else {
1189
1206
  loadState = 'empty'
1190
- loadInjected.add(cwd) // 失败也不重试:不每轮白查一次盘
1207
+ loadInjected.add(loadKey) // 失败也不重试:不每轮白查一次盘
1191
1208
  }
1192
1209
  if (rulesOn) openingRulesLogged = true
1193
1210
  }
@@ -1220,13 +1237,13 @@ export default function absPiHook(pi: ExtensionAPI): void {
1220
1237
  await logHook(`agent_end:seen cwd=${cwd} brain=${brain || 'none'}`).catch(() => {})
1221
1238
  }
1222
1239
  // 送达确认(2026-10-06 方案 A):走到这里 = 这轮真跑完了 → 才算“LLM 看到了”。
1223
- // 中断/ESC 掉的那轮不会到 agent_end → 该 cwd 入不了集合 → 下轮自动补注入。
1240
+ // 中断/ESC 掉的那轮不会到 agent_end → 该 key 入不了集合 → 下轮自动补注入。
1224
1241
  // 这是**唯一**该写 loadInjected 的地方(别挪回 before_agent_start)。
1225
1242
  if (loadPending) {
1226
1243
  loadInjected.add(loadPending)
1227
1244
  const done = loadPending
1228
1245
  loadPending = ''
1229
- await logHook(`agent_end load_delivered cwd=${done} seen=[${[...loadInjected].join(',')}]`).catch(() => {})
1246
+ await logHook(`agent_end load_delivered key=${done} seen=[${[...loadInjected].join(',')}]`).catch(() => {})
1230
1247
  }
1231
1248
  // 每轮 spawn 已删除(2026-10-05 用户实报"卡顿"):agentEndSeen 一旦置位,
1232
1249
  // 下面那个条件就恒真 → 每轮结束都起一个 node 进程,纯属白烧。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanchao8609/agent_brain_sync",
3
- "version": "1.26.0",
3
+ "version": "1.27.0",
4
4
  "description": "agent-brain-sync: 跨会话 AI 编码记忆 — hook 纯触发 + CLI/MCP 读写 .brain markdown 图谱, 防并发写保护。",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -5,296 +5,103 @@ description: "USE FOR abs / agent-brain-sync 跨会话记忆与任务续接。
5
5
 
6
6
  # abs — 跨会话记忆 (agent-brain-sync)
7
7
 
8
- ## 你有知识库,随时都能查
9
-
10
8
  `.brain/` 是**你自己的跨会话记忆库**:踩过的坑、做过的决定、验证过的做法都在里面。
11
9
 
12
- **查它是你的决定,不是别人提醒你才做。** 干活中一旦心里形成关键词、对某件事有疑问(这个坑以前踩过吗?这个约定是谁定的?),那一刻就主动查,**不要等报错、不要等用户提醒、不要等开工那一秒**。
13
-
14
- 怎么查:
15
-
16
- ```bash
17
- abs recall <关键词> # 有疑问时用:按亮度出最相关的几页(不给词就从当前处境推)
18
- abs query <词> # 多词 OR,枚举全图字面命中;输出短(页名+摘要),省 token
19
- abs db search <词> # CLI:亮度排序 + 邻居扩散 + 跨项目;加 --no-rules 省掉 18 条铁律
20
- abs resolve <页名> # 拿到页名后反查路径,只读那一页
21
- ```
22
-
23
- MCP 侧走 `abs_search`(等价于 `abs db search --no-rules`)—— 比 `abs_query` 强:
24
- 带亮度排序、能从邻居页扩散、能查到别的项目(标 `[跨项目]`)。
25
- 两者是**详略两档**,不是重复:`abs_query` 给字面命中的页名+摘要,最省;
26
- `abs_search` 给亮度与扩散,找「我上次怎么解决 X」时更准。
27
-
28
- 查完只读命中那几页,**绝不通读 `.brain/`**。答用 `[[页面名]]` 标来源。
29
-
30
- ## 触发器
31
-
32
- **关键词不是触发器,意图才是。**句子里出现 todo / 沉淀 / load / note 这些词,若是谈论、提问、定规则,只回应不执行。
10
+ **查它是你的决定,不是别人提醒你才做。** 干活中一旦心里形成关键词、对某件事有疑问
11
+ (这个坑以前踩过吗?这个约定是谁定的?),那一刻就主动查 —— 不要等报错、不要等用户提醒。
33
12
 
34
- 唯一例外:用户直接输入 `abs`(单独一个词,或 `abs` + 命令,如 `abs 开工`)—— 这是明确要用 abs,直接执行;无子命令时走开工续接。
35
-
36
- ## 命令速查
37
-
38
- 完整帮助 `abs help`。读写优先走 MCP(`abs_load`/`abs_task`/`abs_note`/`abs_search`/`abs_query`/`abs_lint`/`abs_rule`),比 CLI 快;`abs wrapup`/`abs teardown-check` 是 hook 内部命令。分工:hook 记技术日志;CLI/MCP 实时落盘;skill 负责深提炼 + 收尾 + 修 index。
13
+ ## 开工:跑一句就够
39
14
 
40
15
  ```bash
41
- abs load # 开机读状态
42
- abs query <词> # 字面 OR 命中,输出短;MCP 侧更推荐 abs_search(更准)
43
- abs todo add <id> --note "做什么" # 登记;note/memo/state/done 见「进行中」
44
- abs capture [--layer 1-6] [--kind …] "…" # 按七层判定落点后写入(L7 走 abs note)
45
- abs summon # 列出没落页的会话(只读,不写盘)
46
- abs ingest <会话文件或 id> # 把一场 pi 会话落成会话页(带 session id 双向回溯)
47
- abs note "经验" [--tags a,b] # 暂存经验(一律 L7 混沌层)
48
- abs concept <slug> --title "…" # 建概念页骨架
49
- abs rule add "一句话" # 加 Rules;abs lint 体检;abs init 建图谱
16
+ abs load
50
17
  ```
51
18
 
52
- ## 文档精简(硬规则,写 todo / 知识库文档必须遵守)
53
-
54
- 1. 所有内容必须服务于主题目标,与主题目标无关的直接去掉。
55
- 2. 不允许盲目总结,没有经过验证的经验和总结,直接去掉。
56
- 3. 文档永远保持秩序,提高可阅读性,层次分明。
57
- 4. 清爽的文字风格,禁止反转反问、猜测。
58
- 5. 加快运行速度,提高运行效率。
59
- 6. 拒绝重复,其他文档存在的方法优先引用,拒绝反反复复写。
60
- 7. 禁令内容不要唠叨,直接了当。
61
- 8. 不要过度揣测:用户没说的不要替他补,给了要求就做要求内的。
62
- 9. 说中文,说人话;表达通畅、有前因后果,不堆抽象名词、不自造新词。已经说过、已经确定的事不重复。
19
+ 它给:Rules(铁律,最先读)+ 图谱计数 + 任务板 + 最近流水 + 未填会话页提醒。
20
+ 顶部若有 `⏳ 上会话滞留`,先对账再开工 —— 做完的 `abs todo done <id>`,
21
+ 没做完的 `abs todo note <id> --note "接到哪"`。
63
22
 
64
- 写入 `.brain/` 的 todo 行、log 行、知识页、sessions 快照,生成时按上面九条自检。
23
+ **绝不 `cat .brain/` 通读**。要主题用检索,要单页用 `abs resolve` 后只读那一页。
65
24
 
66
- ## 入口:先找图谱再分流
25
+ ## 找东西:三档,按精确度选
67
26
 
68
- 1. **找图谱**:只看**当前目录**是否含 `.brain/`,先 cd 到项目根。不向上搜索(会命中 `~/.brain`,把项目挂错)。
69
- 2. **没有图谱**:意图是沉淀或即将开工的长期任务("帮我做 X / 开工 / 修 X")→ 先 `abs init`;闲聊、一次性问句、明说不要建档、只读目录 → 不建档。
70
- 3. **分流**:
71
-
72
- | 用户意图 | 走哪 |
27
+ | 你在干什么 | 用哪个 |
73
28
  |---|---|
74
- | 总结经验 / 结束了 / "把这次记下来" | 收尾循环 |
75
- | 查询坑 / "我上次怎么解决 X" | `abs query` |
76
- | 体检图谱 | `abs lint` |
77
- | 开新任务 / 继续开发 | 开场 Init Sync |
78
- | 报 bug / 要求加功能 | 受理协议 |
79
- | 意图不明 | 续 todo |
80
-
81
- 意图不明且项目有 `.brain/` 时,默认续 todo。
82
-
83
- ## 新需求受理协议(先方案 → 再登记 → 问开工)
84
-
85
- 用户报 bug 或要求加功能时先别动代码:
86
-
87
- 1. **总结方案**(一屏内):准确复述需求(不确定就写明假设);bug 给根因,功能给做法;要改哪些文件、怎么验证。
88
- 2. **登记 todo**:`abs todo add <id> --note "<需求+关键约束>"`;根因/取舍用 `abs todo note <id>` 追加成子项。
89
- 3. **问是否开工**:明确问一句,等确认再改代码。
90
-
91
- **例外(可直接开工,回复里说明援引哪一条)**:用户已说"开工/直接做/修它";一行级修字、纯查询、纯收尾沉淀;同一需求已登记且用户确认过。
92
-
93
- ## `.brain/` 怎么组织
94
-
95
- `.brain/` 放项目根,一个项目一份,`abs status` 显示当前定位。
96
-
97
- | 位置 | 放什么 | 硬约束 |
98
- |---|---|---|
99
- | `index.md` | `## Rules` 铁律 + 各类页清单 | Rules 一句一条不带链接,只有「违反会丢数据/静默失效/白干活」级才进,>42 字符或含链接被拒;清单每页一行 `- [[slug]] — 一句话` |
100
- | `log.md` | 成果流水,倒序一行 | 只记成果,不记工具动作 |
101
- | `todo.md` | 活看板 | 只有 `## Todo`/`## Done`;Done 必带 `【落地/否决/仅方案】`+`(完成 YYYY-MM-DD)` |
102
- | `entities/` `concepts/` | 具名事物(`Docker.md`)/ 可复用规律坑(`docker-prisma-429.md`) | 拿不准默认进 `concepts/` |
103
- | `sources/` `syntheses/` | 经验暂存 / 横向选型取舍 | sources 是暂存,提炼后删 |
104
- | `sessions/` | 会话快照 + 当日归档段 | **一天只允许一个 `log-<日期>.md`**,多主题写多个 `##` 段 |
105
-
106
- `todo.md` 行形态:`- [ ] [进行中] <id> [[认领人]] — 说明 (认领 YYYY-MM-DD)`(标记还有 `[讨论中]`/`[滞留中]`;`[[认领人]]` 是使用者名)。`abs todo done <id>` 勾选并归位到 Done 日期组顶部,已勾子项随迁;超 3 天**且整天已完成**的组由 `abs wrapup` 迁进当天快照归档段(任一天还有未完成则整天不归档)。
107
-
108
- `sessions/` 快照 = 正文 + `## 关联连接` + `## 🪝 Next Session Hook`(强制)+ `## 📦 任务归档`(机器写勿手改)。归档唯一动作 `abs todo archive`:已有快照只替换归档段,段外逐字保留;那天没有快照就建一个只含归档段的页;同日重复归档在段内追加。
109
-
110
- ### 容量纪律(写任何页之前过四关)
111
-
112
- ① **再命中** —— 下会话不知道这条会踩同坑/重做同决定?不会就不存,grep 得到的不记。② **单页上限** —— `entities/concepts/syntheses` 单页 <150 行且 <8KB,超了拆或外链。③ **sources 是暂存** —— 提炼后删并清引用。④ 能用一行链接代替新增整页吗?
113
-
114
- ## 开场:Init Sync(开工 / 默认续 todo)
115
-
116
- 1. **读状态**:`abs load`(MCP `abs_load`)读 Rules + 图谱计数 + todo + 最近 log,**先看 `## Rules`**。输出已折叠,全量明细用 `abs todo --full` / `abs index`。
117
- 2. **对账滞留(强制)**:顶部出现 `⏳ 上会话滞留` 说明上会话断了,先收尾再开工 —— 做完的 `abs todo done <id>`;没做完的 `abs todo note <id> --note "接到哪"`。
118
- 3. **读命中页**:`abs query <词>` → `abs resolve <页名或id>` 拿路径,**只读命中那几页**,绝不通读 `.brain/`;多文件汇总交 `ctx_execute` 在沙箱处理,只打印结论。
119
- 4. **续 todo**:把顶部未完成项当当前任务开做;有新任务而 todo 没有 → `abs todo add <id> --note 做什么` 再动工。
120
-
121
- ## 按七层总结(总结前必读)
122
-
123
- 七层不是分类好看,是**检索权重不同**:L1 永不衰减,L7 几乎不参与。所以总结时必须先判层,判完直接落到位 —— 一律塞 sources/ 会让 44% 的知识按错误的权重参与检索。
124
-
125
- | 层 | 判据 | 落点 | 怎么落 |
126
- |---|---|---|---|
127
- | L1 铁律 | 违反就必须停下 | index 的 `## Rules` | `abs capture --layer 1`(≤42 字、禁链接) |
128
- | L2 规则 | 这个项目要遵守的做法 | `concepts/` + `layer: 2` | `abs capture --layer 2` |
129
- | L3 工具 | 某工具怎么用、有什么坑 | `concepts/` + `layer: 3` | `abs capture --layer 3` |
130
- | L4 认知 | 踩坑的根因与解法 | `concepts/` + `layer: 4` | `abs capture "…"`(默认) |
131
- | L5 会话 | 这次做了什么 | `log.md` / `sessions/` | `abs log`(当天工作)/ `abs ingest`(一场会话) |
132
- | L6 断点 | 双链词 | 不立页,机器自动抽 | 不接手写 |
133
- | L7 混沌 | 还没想清的碎片 | `sources/` | `abs note`(capture 的 L7 已拒,同一个落点) |
134
-
135
- 判据不明时用 L4 —— 但**知道是工具经验就写 L3**:实测算过,本仓 52 页 concepts 里 23 页其实是 L3。
136
-
137
- **`--kind` 是另一条正交轴**(借 cl​aude-mem 的 observation 类型):`layer` 说「什么性质」,`kind` 说「起什么作用」。
138
-
139
- | kind | 含义 | 何时用 |
140
- |---|---|---|
141
- | `gotcha` | 关键坑 | 踩了会白干、想不到的那种 |
142
- | `decision` | 决策 | 记「当时为什么这么选」 |
143
- | `tradeoff` | 权衡 | A 好但 B 也有理,最后选了哪个 |
144
- | `howto` | 做法 | 这类事该怎么做 |
145
-
146
- 不传就不写(旧页留空,不强制补)。实测只有 `gotcha` 能靠 tags/标题机械识别,
147
- 另三类判据在内容里 —— 别拿关键词瞎猜。
29
+ | 不知道找什么,卡住了 | `abs recall [词…]` —— 按当前处境推(不给词也行) |
30
+ | 知道关键词,要最准 | `abs search <词>` —— 亮度排序 + 邻居扩散 + 跨项目 |
31
+ | 要字面精确、输出短 | `abs query <词…>` —— 多词 OR 命中 |
148
32
 
149
- **尾巴按 kind 分档**(`abs lint` 的 NO-TAIL):`gotcha`/`howto` 必须有验证命令;
150
- `decision`/`tradeoff` 写「当时依据什么选的」(取舍依据,不是可跑的命令);
151
- 无 `kind` 的旧页保持原要求。理由:决策类知识天生没有验证命令,硬要写就是编。
33
+ `abs search` 与 `abs query` 是**详略两档,不是重复**:前者带亮度和扩散更准,
34
+ 后者只给页名+摘要更省 token。MCP 侧分别对应 `abs_search` / `abs_query`。
152
35
 
153
- ## 会话总结(把整场会话变成知识)
36
+ 拿到页名后 `abs resolve <页名>` 反查路径,只读命中的那几页。答时用 `[[页面名]]` 标来源。
154
37
 
155
- abs 不只记编程经验 —— **会话本身的结论也是知识**。两条路径,用途不同:
38
+ ## 写知识:三个落点,别混
156
39
 
157
- | 想要 | 命令 | 产出 |
40
+ | 你手上的东西 | 落点 | 命令 |
158
41
  |---|---|---|
159
- | 一场会话干了什么/谈成了什么 | `abs ingest <会话文件或 id 前 8 位>` | `sessions/session-<日期>-s<id8>.md`,带三种骨架之一 |
160
- | 还没落页的会话 | `abs summon` | 清单,不写盘 |
42
+ | 一句经验,还没想清 | `sources/` 待提炼 | `abs note "一句话"` |
43
+ | 要成页(有骨架好填) | `concepts/` | `abs concept <slug> --title "…"` |
44
+ | 一句话记下,日期即时间线 | `concepts/` | `abs capture --layer 2/3/4 "…"` |
45
+ | 违反就必须停下的硬约束 | index 的 `## Rules` | `abs rule add "≤42 字"` |
161
46
 
162
- `abs ingest` 按「改过什么文件」机械判形状,不让模型猜:
47
+ `concept` 与 `capture` 都写 `concepts/`,但产出不同:前者带四段骨架(触发场景/表现/解法/验证),
48
+ 后者只落一句话 + 日期前缀。要「写细」用 concept,要「快记」用 capture。
163
49
 
164
- - **技术类**(改了代码)→ 出了什么问题 / 怎么解决的 / 验证什么命令
165
- - **业务操作类**(只改数据/配置/文档)→ 做了什么操作 / 结果怎样 / 下次注意事项
166
- - **讨论类**(一个文件没改)→ 谈成了什么 / 没结论的地方
50
+ **写完跑 `abs lint`**,它报死链、超限、无尾(`NO-TAIL`:页要有「做完怎么确认」那段)。
167
51
 
168
- 它只给骨架和素材(用户原话、改过的文件、工具调用次数),**不写结论** —— 内容要读会话后填。
169
-
170
- **与会话的双向挂钩**(不要手改这三行):`session`(pi 会话 id)、`session-file`(jsonl 文件名)、
171
- `project`(会话发生时的 cwd)。页文件名也带会话 id 前 8 位,拿会话文件能反查有没有总结过。
172
-
173
- 会话页在检索里的待遇按「填没填」分两档(判据 `digestFilled`,`layers.js`):
174
-
175
- | 状态 | 检索 |
176
- |---|---|
177
- | **已填**(骨架段有真内容) | 亮度乘 0.5,能搜到也能扩散,但不抢知识页位置 |
178
- | **未填**(骨架段只有占位注释) | **整页排除**,种子和扩散都进不来 |
179
-
180
- 未填整页排除的理由(实测):空骨架的「用户原话」段词频高、正文又短,bm25 天然占优。
181
- 造 20 张空骨架后查「登录超时」,前 12 名全是空页,真正讲过该问题的知识页被彻底挤出结果。
182
-
183
- `abs load` 顶部会列出未填的张数(最多 5 个页名,按日期倒序)。**不必全部填** ——
184
- 挑最近、有结论的几场;其余留着当流水,不填也不会污染检索。
185
-
186
- `abs capture` 之后跑 `abs db rebuild` 让图数据库收录,否则检索拿不到它。
187
-
188
- ## 进行中:什么时候动它
189
-
190
- todo 是随改随写的活看板,和 git commit 同反射。
191
-
192
- | 时机 | `abs_task` action | 落到哪 |
193
- |---|---|---|
194
- | 认领新任务 | `start` + note 做什么 | Todo `[进行中]` |
195
- | 只讨论没动手 / 卡住等人等数据 | `state` + note 讨论中\|滞留中 | 原地改标记 |
196
- | 被打断 / 干到一半 | `note` + 改到哪个文件哪一步 | 任务下追加一条子项(**一句话**) |
197
- | 干活中随手记多句发现 | `memo` + 原文 | `sessions/` 当日笔记,**不上看板** |
198
- | 子任务做完 | `done` + note 结语 + as 落地\|否决\|仅方案 | Done |
199
- | 总结出经验/坑/规律 | `abs capture --layer N`(先按上表判层) | 按层落到位 |
200
-
201
- **四个落点的区别**:
202
-
203
- - `note` = **子项**,一句话**追加式**(每次多一条,不覆盖),上看板。
204
- - `memo` = **随手记**,可多句**追加式**,不占看板。
205
- - `abs_note` = 提炼过的**经验/坑**,一句话结论 → `sources/` 待提炼。
206
- - `abs log` = 一轮干完的**成果流水**行,不占看板。
207
-
208
- 过程随手记走 `memo`,别塞 `todo.md`(Todo 区有**白名单闸门**:只收任务行、缩进子项、空行、标题,其余拒写报错)。
52
+ ## 写任务:todo 是活看板
209
53
 
210
54
  ```bash
211
- abs todo memo <id> "第一句:根因是判据极性。第二句:改成白名单就不漏了。" # 记(可多句)
212
- abs todo memo <id> # 查看
55
+ abs todo add <id> --note "做什么" # 登记
56
+ abs todo note <id> --note "到哪一步" # 追加子项(一句话)
57
+ abs todo done <id> --as 落地|否决|仅方案 "结语"
58
+ abs todo state <id> --note 进行中|讨论中|滞留中|搁置
59
+ abs todo remove <id> # 删除(连子项,不可恢复)
213
60
  ```
214
61
 
215
- 任务 `done` 后笔记文件留在 `sessions/`,随当日归档。
62
+ - **开工前先登记**:要动文件/跑命令就先 `start`,名字粗糙没关系(事后可 `rename`)。
63
+ - **一段活干完立刻 done**:别攒着等大需求收尾。
64
+ - `搁置` = 先不做、还留在看板上;`remove` = 当作没登记过。**两者别混**。
65
+ - 随手记多句发现用 `abs todo memo <id> "…"`,不占看板。
216
66
 
217
- **开工前三条硬规则**:
67
+ ## 触发器:意图,不是关键词
218
68
 
219
- 1. **开工前先登记** —— 认领任何要动文件/跑命令的任务,第一步是 `abs_task` action=start,然后才读第一个文件。名字想不到就先起粗糙的(`fix-hook-nudge`):名字可事后改,**未登记的开工补不回来**。
220
- - 登记只能由你主动做(hook 看不到"这是件什么事");别抄用户原话。
221
- - 改 id:`abs todo rename <旧id> --note "<新id>"`。
222
- 2. **一段活儿干完立刻 done** —— 不等整个需求收尾。宁可拆 5 条小的,别攒 1 条大的。
223
- 3. **超过两三轮还没登记 = 已在失控路上** —— 立刻补 `start`。
69
+ 句子里出现 todo / 沉淀 / load / note 这些词,若是**谈论、提问、定规则**,只回应不执行。
224
70
 
225
- 经验刚冒出来就 `abs_note` 暂存(幂等去重),宁少勿滥。**跨会话任务只用 abs todo**,别用宿主原生 todo(TodoWrite / `/list`),那些不写 `.brain/todo.md`,下会话接不上。
71
+ 唯一例外:用户直接输入 `abs`(单独一个词或 `abs` + 命令,如 `abs 开工`)—— 明确要用 abs,
72
+ 直接执行;无子命令时走开工流程。
226
73
 
227
- ## 主动提炼(不等人说「收尾」)
74
+ ## 文档精简(写 todo / 知识库文档必须遵守)
228
75
 
229
- 提炼是**你的自觉**,不是等用户发指令。两个触发时机,任中一个就主动做:
76
+ 1. 所有内容服务于主题目标,无关的直接去掉。
77
+ 2. 不写没验证过的经验和总结。
78
+ 3. 层次分明,按前因后果组织,不用自造词。
79
+ 4. 禁止反问、猜测。
80
+ 5. 拒绝重复,已有文档写过的优先引用。
81
+ 6. 禁令直接了当,不唠叨。
230
82
 
231
- 1. **sources 积压**:`abs load` 顶部出现「♻ 待消化」或 `abs lint` 报 `SOURCES-PILED-UP`(> 10 条)→ 主动收拢。
232
- 2. **一段活收尾**:任务 `done`、或踩坑后刚 `abs_note` 暂存完 → 顺手看这条值不值得提炼成规律。
233
-
234
- 动作只有一步判断 + 一个落点:
235
-
236
- ```bash
237
- abs review # 列出待确认的 draft 页(concepts + sources)
238
- # 值得留 → 用自己的判断提炼成一句话,落到正确层:
239
- abs capture --layer 3 "某工具怎么用/有什么坑" # 工具经验
240
- abs capture "踩坑的根因与解法" # 认知(默认 L4)
241
- # 不值得留 → 否决掉:
242
- abs review --reject <页名>
243
- ```
244
-
245
- **判断力在你(agent),工具只做落点**——`capture` 不替你判「这条值不值得留、归哪一层」。提炼成规律后删原 source、清指向它的引用(防死链,见 Teardown 第 5 步)。
246
-
247
- ## 收尾循环(用户明确要求收尾时才走)
248
-
249
- 1. **读 todo**:`abs load`,看还有哪些没完成。
250
- 2. **对账**:按「进行中」四个落点补记 —— 漏登记的 `done`、做一半的补 `note` 子项、卡住的转 `滞留中`。
251
- 3. **沉淀经验**(值得才沉淀):坑/可复用技巧 → `abs note` 暂存;值得深提炼的走 Teardown。
252
- 4. **判教训够不够格进 Rules**:是否「违反会丢数据/静默失效/白干活」级?够格就输出一行 `[Rules 提议] <一句话>` 问用户,确认后才 `abs rule add "<一句话>"`;不够格不提。
253
- 5. **更新 index/log/todo**:新页同步进 index;`abs log "完成 X:..."`;`abs lint` 确认自洽。
254
-
255
- **完成标准**:看板反映真实状态(Done 无滞留半成品)、该沉淀已落、够格教训已提议、index/log/todo 与事实一致。
256
-
257
- Stop 时 hook 把「未完成 + 子项」快照进 `~/.abs/log/wrapup.log`,下会话 `abs load` 自动顶到顶部。不往对话里插收尾提醒。
258
-
259
- ## 收尾:Teardown Sync(深提炼)
260
-
261
- 把**真实发生**的写回图谱,只写做过/跑过/测过的事实。按序:
262
-
263
- 1. **暂存线索**:`abs note` 记做了什么、改了哪些文件、验证命令。
264
- 2. **抽规律**:`abs concept <slug> --title "…"` 建页(自动带四段骨架)再填;四段别缺,尤其末尾「验证」段(`abs lint` 报 NO-TAIL)。留不留、新建还是并入由你判断;核实过的 `status` 改 `active`。
265
- 3. **查推翻**:旧页有被推翻的说法 → `abs supersede <旧页> --by <新页>`,别删页。
266
- 4. **沉淀实体 / 综合**:重要未记录的事物 → `entities/<TitleCase>.md`;选型取舍 → `syntheses/`。
267
- 5. **收拢 sources**:提炼成规律的删 source,**同步清指向它的引用**(防死链)。
268
- 6. **修 index + 记 log**:新页同步 index;过门槛的规律加进 `## Rules`。
269
- 7. **留接力棒**:`sessions/log-YYYY-MM-DD.md` 写 `## 🪝 Next Session Hook`。
270
-
271
- ## 知识页格式
272
-
273
- 统一 frontmatter:`tags / author / updated / status`。`tags` 首标签 ∈ `entity|concept|source|synthesis|session-log`;`author` 与 `entities/<name>.md` 同名。
274
-
275
- **`status` 只有三个值**:`active` 当前有效(缺字段默认);`draft` 待核实(`abs note` 默认,展示标 `[draft 未核实]`);`superseded` 已被推翻,别再依据(`query` 默认隐藏)。推翻用 `abs supersede <页名> --by <新页>`(写 `superseded-by`;不写 `--by` = 单纯弃用;指向不存在的页会被拒)。历史必须留,核实后仍有效就改回 `active`。
276
-
277
- - **每页必须有 `## 关联连接`**,用 `[[页面名]]` 链相关页,解释写在 `—` 后(`[[x]] — 节流判据要对齐真收尾`),只写链点等于没链。
278
- - **命名即链接**:`[[Docker]]` → `entities/Docker.md`,`[[docker-prisma-429]]` → `concepts/`。不建别名层。
279
- - **知识冲突**:不静默覆盖,加 `## 知识冲突`,两版都留、标来源时间,交人工裁决。
280
- - 概念页骨架:`触发场景 / ❌表现(贴报错) / 🛠解法(根因+修复+验证命令) / 关联连接`。
83
+ ## ⛔ 禁止做
281
84
 
282
- ## 维护:query / lint
85
+ 1. 禁止手工建骨架 / 手工登记任务 —— 用 `abs init` / `abs todo add`。
86
+ 2. 禁止通读 `.brain/` —— 要状态用 `abs load`,要主题用检索,要单页用 `abs resolve`。
87
+ 3. 禁止删知识页表达"已失效" —— 用 `abs supersede <页> --by <新页>`。
88
+ 4. 禁止直写 Rules —— 先提 `[Rules 提议]` 问用户,确认后 `abs rule add`。
89
+ 5. 禁止用宿主原生 todo 承载跨会话任务 —— 用 `abs todo`。
90
+ 6. 禁止编造没跑过的验证结论。
283
91
 
284
- - `abs query <词>` → 读命中页 → 答用 `[[页面名]]` 标来源。代码问题(符号在哪/谁调用)不在 `.brain`,直接读源码;已推翻经验默认不返回(`--all` 可看)。
285
- - `abs lint` 报错码:`NO-INBOUND` / `SOURCE-UNDISTILLED` / `SUPERSEDED-DANGLING` / `DRAFT-STALE` / `NO-TAIL`。
92
+ ## 需要时再查的细节
286
93
 
287
- ## ⛔ 禁止做
94
+ 以下内容已移到图谱页,**不要凭记忆猜**,用到时读它:
288
95
 
289
- 1. 禁止手工建骨架 / 手工登记任务 —— 用 `abs init` / `abs todo add`。
290
- 2. 禁止由关键词直接触发动作 —— 拿不准先问。
291
- 3. 禁止通读 `.brain/` —— 要状态用 `abs load`,要主题用 `abs query`,要单页用 `abs resolve` 后只读那页。
292
- 4. 禁止删知识页表达"已失效" —— 用 `abs supersede`。
293
- 5. 禁止归档单独建文件 / 一天拆多个快照 / 手工搬大文件 —— 用 `abs todo archive`;一天只有一个 `log-<日期>.md`;大文件进 `sources/` 或摘规律进 `concepts/`。
294
- 6. 禁止编造没跑过的验证结论 —— 只写做过/跑过/测过的事实。
295
- 7. 禁止直写 Rules —— 先 `[Rules 提议]` 问用户,确认后才 `abs rule add`。
296
- 8. 禁止用宿主原生 todo 承载跨会话任务 —— 用 `abs_task`。
96
+ | 要做什么 | 读哪页 |
97
+ |---|---|
98
+ | 七层怎么判、`--kind` 怎么选、收尾深提炼全流程 | `abs resolve abs-skill-details` |
99
+ | 会话页怎么落、三种骨架、与会话的挂钩 | `abs resolve session-digest-design` |
100
+ | 新需求受理协议(先方案→登记→问开工) | `abs resolve abs-skill-details` |
101
+ | `.brain/` 目录结构、知识页 frontmatter 格式 | `abs resolve abs-skill-details` |
102
+ | 体检报错码含义(NO-INBOUND / NO-TAIL / …) | `abs resolve abs-skill-details` |
297
103
 
298
104
  ## 自我约束
299
105
 
300
- 只读写 `.brain/` 与目标代码,不动全局配置(一次性接入除外);双链、frontmatter、index 必须自洽,坏链等于掰断接力棒。
106
+ 只读写 `.brain/` 与目标代码,不动全局配置(一次性接入除外);
107
+ 双链、frontmatter、index 必须自洽 —— 坏链等于掰断接力棒。
@@ -190,7 +190,7 @@ export async function cmdDbRebuild({ dir } = {}) {
190
190
  }
191
191
 
192
192
  /** `abs db search <词>` —— 走库搜索:FTS 种子 → 亮度扩散。 */
193
- export async function cmdDbSearch({ query, limit = 8, full = false, noRules = false } = {}) {
193
+ export async function cmdDbSearch({ query, limit = 8, full = false, noRules = false, cmdName = 'db search' } = {}) {
194
194
  const q = String(query || '').trim();
195
195
  if (!q) return '用法: abs db search <词>';
196
196
 
@@ -207,7 +207,9 @@ export async function cmdDbSearch({ query, limit = 8, full = false, noRules = fa
207
207
  const seeds = search(h, q, { limit: 12 });
208
208
  const lit = illuminate(h, seeds, { limit });
209
209
 
210
- const out = [`db search [${q}] → 种子 ${seeds.length} 条,亮起 ${lit.length} 页`];
210
+ // 命令名随调用方式变(2026-11-06):顶层叫 search,别名仍走 db search。
211
+ // 直接印死 'db search' 会让新命令的输出自相矛盾。
212
+ const out = [`${cmdName} [${q}] → 种子 ${seeds.length} 条,亮起 ${lit.length} 页`];
211
213
  // --no-rules:不输出 L1 铁律(2026-11-05)。
212
214
  // 为何要它:铁律 18 条,占输出近一半。开工时(abs load)确实该先看,
213
215
  // 但「查一个主题」时它们是噪音 —— 实测同一查询 43 行里有 4 行是铁律区,
@@ -265,7 +267,7 @@ export async function cmdDbSearch({ query, limit = 8, full = false, noRules = fa
265
267
  } else {
266
268
  out.push('', '(L1 铁律恒在最前;↝ 表示由邻居扩散点亮,非直接命中)');
267
269
  }
268
- out.push('(只给摘要与成本;要看全文: abs db search <词> --full 或 abs resolve <页名>)');
270
+ out.push(`(只给摘要与成本;要看全文: abs ${cmdName} <词> --full 或 abs resolve <页名>)`);
269
271
  if (project && !noRules) {
270
272
  out.push(`(铁律只显示本项目 "${project}" 的 —— 别的项目的铁律不外借)`);
271
273
  }
@@ -137,6 +137,45 @@ export async function cmdTask({ dir, action, id, section, note, as, session, n }
137
137
  });
138
138
  return cc.length ? `✓ ${id} 状态 → [${note}]` : `[NO_MATCH] 未找到含 "${id}" 的未完成任务行,或状态未变`;
139
139
  }
140
+ // 删除任务(2026-11-05 用户要求「每次删除任务可烦人了」)。
141
+ // 与 state=搁置 的区别(别混):
142
+ // 搁置 = 先不做,任务**留在看板上**,下个会话还会看见它并问你要不要接着干
143
+ // 删除 = 从看板移除,当作从未登记过(记错了/重复了/与事实不符)
144
+ // 为何必须连子项一起删:只删任务行会留下无主的缩进子项,
145
+ // normalizeTodo 重建分区时它们会被当孤儿清掉 —— 那种「清掉」是静默的,
146
+ // 而这里要让整块消失是**显式**的,且报告删了几条。
147
+ if (action === 'remove') {
148
+ const f = brainPath(root, 'todo.md');
149
+ let removed = null;
150
+ await editFile(f, (cur) => {
151
+ if (cur === null) return SKIP;
152
+ const lines = cur.split('\n');
153
+ const wantId = String(id).replace(/[\u200b\u200c\u200d\ufeff]/g, '');
154
+ for (let i = 0; i < lines.length; i++) {
155
+ if (idOfTaskLine(lines[i]) !== wantId) continue;
156
+ // 收集这一行 + 紧跟的所有子项行(缩进列表项 / 旧 ↳ 写法)
157
+ const block = [lines[i]];
158
+ let j = i + 1;
159
+ while (j < lines.length) {
160
+ const nx = lines[j];
161
+ if (!nx.trim()) break;
162
+ const kid = parseChild(nx);
163
+ const legacy = /^\s+↳\s/.test(nx);
164
+ if ((kid && kid.indent > 0) || legacy) { block.push(nx); j++; continue; }
165
+ break;
166
+ }
167
+ removed = { body: lines[i], kids: block.length - 1 };
168
+ lines.splice(i, block.length);
169
+ return { text: lines.join('\n') };
170
+ }
171
+ return SKIP;
172
+ });
173
+ if (!removed) return `[NO_MATCH] 未找到含 "${id}" 的未完成任务行`;
174
+ // 只删未完成区:Done 区的条目是历史,删了等于篡改记录。
175
+ // idOfTaskLine 只认 `- [ ]`,所以到这里的一定是未完成的。
176
+ const kidNote = removed.kids ? `(连同 ${removed.kids} 条子项)` : '';
177
+ return `✓ 已删除任务 ${id}${kidNote}\n 原行: ${removed.body.trim().slice(0, 90)}\n 说明: 删除是不可恢复的移除;只是「先不做」请用 abs todo state ${id} --note 搁置`;
178
+ }
140
179
  if (action === 'note') {
141
180
  if (!note) return '用法: abs todo note <id> --note "进度"\n 建议前缀(load 会把它们单独抽出来,让人一眼看到):\n 验证: <跑过的命令/结果>\n 边界: <这方案治不了什么>\n 阻塞: <在等什么,卡在哪>';
142
181
  const r = await setBreakpoint(root, { id, text: note });