@@ -22,12 +22,25 @@ Codex session jsonl
2222## 已确认决策
2323
2424- 使用全局 SQLite 数据库,不按项目拆多个数据库。
25+ - SQLite 是本机 durable recall archive,不只是镜像缓存或临时索引。
26+ - SQLite 要保存原始 session 消息和 raw json,避免 ` ~/.codex/sessions ` 本地日志丢失后 recall 失效。
27+ - 原始 Codex jsonl 文件被删除时,SQLite 中已归档 session 不自动删除。
2528- ` csep recall ` 默认只查同仓库范围。
2629- 跨仓库 recall 必须显式使用 ` --global ` 。
2730- 同一个 git repository 的多个 worktree 算作同一个 repo;worktree 路径只作为更细粒度 metadata 和排序信号。
31+ - 第一版提供 ` [session_recall] ` 总开关,默认启用。
32+ - Stop hook 第一版自动归档当前 session;归档通过独立后台子进程执行,不是 scheduler、队列或定时任务。
33+ - 第一版不做 ingest 失败重试队列,失败只记录日志、status 和 ingest error,后续靠手动 backfill 补。
34+ - 第一版不做 purge / 显式删除能力;已归档数据不会自动删除,删除能力留到后续版本。
35+ - user、assistant、tool call、tool output 都要入库;recall 默认搜索 tool output,但 tool 命中降权,输出时强截断。
36+ - FTS 只索引提取出的可读文本;raw json 保存到库里,但不进 FTS,也不在默认 recall 输出里展示。
37+ - 第一版支持 Hermes 风格 FTS5 高级语法,默认保留 FTS5 多词 AND 语义;广搜由用户或模型显式写 ` OR ` 。
38+ - 默认按 session 聚合结果,` --limit ` 表示最多返回几个 session;同一 session 默认只返回一个最佳命中窗口。
39+ - ` --recent ` 支持最近 session 浏览,默认同仓库,` --recent --global ` 才看全局。
40+ - 能识别当前 session 时,recall 默认排除当前 session;手动命令识别不了时不强行猜。
2841- 第一版返回原始消息窗口,不做 LLM focused summary。
2942- 第一版保持当前触发方式,不接 ` UserPromptSubmit ` 自动 recall。
30- - 第一版支持增量 ingest 和手动历史 backfill。
43+ - 第一版支持 Stop hook 单 session archive 和手动历史 backfill;不做无参数 ` csep session-ingest ` 增量扫描 。
3144- recall 输出必须有总长度预算和单条消息预算。
3245- 现有 ` recall/index.json ` 行为保留为 fallback,SQLite 不可用或无结果时不打断旧能力。
3346
@@ -39,7 +52,7 @@ CSEP 新增一个全局 session recall store:
3952~/.codex-self-evolution/session_recall/state.db
4053```
4154
42- 这个 store 负责可查询的 recall 索引。Codex session jsonl 仍然是原始事实来源;CSEP 只把这些文件导入到自己的 SQLite 表和 FTS 索引里 。
55+ 这个 store 负责可查询的 recall 索引,也负责本机长期归档 。Codex session jsonl 是初始事实来源;一旦导入成功, SQLite 中的消息内容不依赖原始 jsonl 文件继续存在 。
4356
4457第一版最小表集合:
4558
@@ -49,6 +62,12 @@ CSEP 新增一个全局 session recall store:
4962- ` ingest_checkpoints `
5063- ` ingest_errors `
5164
65+ 需要保留最小 schema version:
66+
67+ - ` schema_version `
68+
69+ 第一版只实现轻量版本升级,不引入 Alembic 或复杂迁移框架。
70+
5271` csep recall ` 优先查询这个 store。默认情况下,它根据当前 ` --cwd ` 或进程 cwd 解析 repo fingerprint,只返回同仓库命中,并围绕命中消息返回有预算控制的上下文窗口。` --global ` 会移除 repo 过滤,允许跨仓库检索。
5372
5473repo identity 和 worktree identity 分开处理:
@@ -60,23 +79,68 @@ repo identity 和 worktree identity 分开处理:
6079
6180repo fingerprint 的实现要优先选择稳定信号,例如 git common dir、origin URL 或归一化后的 repository root。不能只用当前 worktree 路径直接做唯一身份,否则同一仓库的多个 worktree 会被错误拆开。
6281
82+ ## 配置开关
83+
84+ 第一版新增最小配置:
85+
86+ ``` toml
87+ [session_recall ]
88+ enabled = true
89+ stop_hook_archive = true
90+ ```
91+
92+ 默认开启,避免用户忘记归档导致日志丢失。
93+
94+ - ` enabled = false ` :SQLite session recall 整体关闭,` csep recall ` fallback 到现有 ` recall/index.json ` 。
95+ - ` stop_hook_archive = false ` :手动 backfill / recall 仍可用,但 Stop hook 不自动归档当前 session。
96+
6397## Ingest 与 Backfill
6498
6599新增 CLI:
66100
67101``` bash
68- csep session-ingest
102+ csep session-archive --from-hook-payload < payload.json>
103+ csep session-archive --transcript-path < path> --cwd < cwd> --session-id < id>
69104csep session-ingest --backfill
105+ csep session-ingest --backfill --since-days 30
106+ csep session-ingest --backfill --limit-files 500
70107```
71108
72- ` session-ingest ` 从 Codex session jsonl 做增量导入。它使用 checkpoint,只处理上次导入后新增或变更过的文件。
109+ ` session-archive ` 归档一个明确的 session / transcript,主要给 Stop hook 使用,也支持手动补录单个 transcript。
110+
111+ ` session-ingest --backfill ` 扫描历史目录,批量导入旧 session。第一版不提供无参数 ` csep session-ingest ` 增量扫描,避免把第一版做成半个同步器或 scheduler。
112+
113+ Stop hook 会单独 spawn 一个独立后台子进程,执行 ` csep session-archive --from-hook-payload <payload.json> ` ,归档当前 hook payload 指向的 transcript。这个子进程不与 stop-review 共用;任意一边失败都不影响另一边。前台 Stop hook 仍然快速返回。
114+
115+ 这里的“后台”只表示 detached process,不是定时任务、队列或重试系统。
73116
74- ` --backfill ` 扫描已有的 ` ~/.codex/sessions ` 历史,并导入同一个全局数据库。第一版 backfill 是手动命令,不自动跑。它必须支持中断后重跑。
117+ 第一版不做 ingest 失败重试队列。Stop hook archive 失败时只记录日志、` ingest_errors ` 和 status 可见状态;后续通过手动 ` session-ingest --backfill ` 补。
118+
119+ ` --backfill ` 默认扫描已有的 ` ~/.codex/sessions ` 全量历史,并导入同一个全局数据库。第一版 backfill 是手动命令,不自动跑。它必须支持中断后重跑,也支持 ` --since-days ` 和 ` --limit-files ` 控制范围。
75120
76121ingest 必须幂等。重复处理同一个文件或同一条消息,不应该生成重复行。
77122
123+ 同一 session 多次 ingest 时,不删除后重建,而是做幂等增量 upsert。唯一键使用 ` (session_id, message_uid) ` ;` message_index ` 只作为排序、窗口提取和 fallback 信息。
124+
125+ ` message_uid ` 解析顺序:
126+
127+ 1 . 优先使用 Codex event 中稳定 id 字段。
128+ 2 . 其次使用 item id、turn id、tool call id 等稳定字段组合。
129+ 3 . 没有稳定字段时,用 ` sha256(session_id + raw_line) ` 。
130+
78131解析失败不能阻塞整批任务。坏文件或暂不支持的 event shape 应记录 ingest error,然后继续处理其他文件。
79132
133+ 如果原始 Codex jsonl 后续被删除,SQLite 中已归档数据不自动删除。ingest 或 backfill 发现源文件缺失时,只更新类似 ` source_missing ` / ` last_seen_at ` 的 metadata,不删除消息。
134+
135+ ` session-archive ` 成功标准:
136+
137+ - 成功写入或更新 session row。
138+ - 至少写入 1 条可读 message row。
139+ - 写入的可读 message 能通过 FTS 搜到。
140+ - repo metadata 尽量完整;无法解析 git repo 时可用 ` cwd ` fallback。
141+ - tool metadata 解析失败但 tool output 文本已入库时,只记 warning,不算整体失败。
142+ - 0 条可读 message 算 archive failed。
143+
80144session metadata 至少包括:
81145
82146- ` session_id `
@@ -87,58 +151,98 @@ session metadata 至少包括:
87151- ` repo_fingerprint `
88152- ` worktree_root `
89153- ` git_branch `
154+ - ` source_missing `
90155- ` started_at `
91156- ` updated_at `
92157- ` message_count `
93158
94159message metadata 至少包括:
95160
96161- ` session_id `
162+ - ` message_uid `
97163- ` message_index `
98164- ` role `
99165- ` content `
166+ - ` raw_json `
167+ - ` metadata_json `
100168- ` timestamp `
101169- ` tool_name `
102170- ` raw_event_type `
103171
172+ 入 ` messages.content ` 并进入 FTS 的只应是可读文本:
173+
174+ - user 文本
175+ - assistant 文本
176+ - tool call 名称和参数摘要
177+ - tool output / tool result
178+ - 必要的 system / developer / context 片段
179+
180+ 不直接进入 FTS 的内容:
181+
182+ - 纯 telemetry
183+ - token accounting
184+ - 空 content
185+ - 未提取文本的大段结构对象
186+ - ` raw_json `
187+
104188## Recall 查询
105189
106190默认命令:
107191
108192``` bash
109193csep recall " query"
194+ csep recall --recent
110195```
111196
112197默认查询流程:
113198
1141991 . 从 ` --cwd ` 或 ` PWD ` 解析当前 repo。
115- 2 . 搜索 ` messages_fts ` 。
200+ 2 . 使用 FTS5 搜索 ` messages_fts ` 。
1162013 . 默认过滤到相同 ` repo_fingerprint ` 。
117- 4 . 按 FTS score、时间、轻量 role 权重排序 ,并给相同 worktree / cwd prefix / branch 额外加权。
118- 5 . 按 session 和 message 聚合命中。
119- 6 . 提取每个命中周围的原始消息窗口 。
202+ 4 . 按 FTS score、role 权重、时间排序 ,并给相同 worktree / cwd prefix / branch 额外加权。
203+ 5 . 默认按 session 聚合命中。
204+ 6 . 每个 session 只选择一个最佳命中窗口 。
1202057 . 默认渲染 Markdown,请求 JSON 时输出机器可读结果。
121206
207+ FTS 查询语法尽量接近 Hermes:
208+
209+ - 支持普通关键词。
210+ - 支持 ` "exact phrase" ` 。
211+ - 支持 ` OR ` / ` NOT ` 。
212+ - 支持 prefix,例如 ` deploy* ` 。
213+ - 对破坏 FTS5 语法的字符做 sanitize。
214+ - 查询语法异常不能 crash;应返回空结果或 fallback,并在 debug metadata 中标记。
215+
216+ 多词普通 query 默认保留 FTS5 原生 AND 语义。需要 broad recall 时,由用户或模型显式写 ` OR ` 。
217+
122218跨仓库命令:
123219
124220``` bash
125221csep recall " query" --global
222+ csep recall --recent --global
126223```
127224
128225` --global ` 可以跨仓库搜索,但输出里仍必须带 repo / cwd / source metadata,方便模型判断相关性。
129226
227+ ` --recent ` 返回最近 session metadata 和 preview,不回读完整消息窗口。默认同仓库过滤;配合 ` --global ` 才展示全局最近 session。
228+
130229第一版支持这些 CLI flags:
131230
132231``` bash
133232--global
233+ --recent
134234--limit 3
135235--before 3
136236--after 5
137237--budget-chars 12000
138238--message-chars 1200
239+ --tool-message-chars 600
139240--format markdown| json
241+ --current-session-id < id>
140242```
141243
244+ 能识别当前 session 时,默认排除当前 session。普通手动命令没有 current session id 时,不做复杂运行时推断。
245+
142246## 输出形态
143247
144248Markdown 输出要短、清晰,适合模型直接阅读:
@@ -191,8 +295,11 @@ JSON 输出要包含便于调试的结构化 metadata:
191295- ` after = 5 `
192296- ` limit = 3 `
193297- ` message_chars = 1200 `
298+ - ` tool_message_chars = 600 `
194299- ` budget_chars = 12000 `
195300
301+ ` limit ` 表示最多返回几个 session。每个 session 默认只返回一个最佳命中窗口;如果同一 session 内还有其他命中,JSON 记录 ` hit_count ` 和其他 hit 的 snippet / index,Markdown 只做短提示。
302+
196303内容超过预算时,按以下优先级裁剪:
197304
1983051 . 保留命中消息。
@@ -223,6 +330,8 @@ Markdown 或 JSON 渲染前,必须复用现有脱敏规则或等价检查,
223330
224331第一版只要求输出时脱敏,不要求修改数据库中已存储的 row。
225332
333+ SQLite 中保存原始消息和 ` raw_json ` 是有意设计:它是本机归档库,不是只读镜像缓存。第一版不提供 purge / 显式删除能力;后续若引入删除能力,必须是显式操作;不会因为源 jsonl 消失而自动删除。
334+
226335## 兼容性
227336
228337第一版不删除、不迁移现有 ` recall/index.json ` records。
@@ -245,6 +354,9 @@ fallback 行为:
245354- graph retrieval。
246355- 整段 session transcript 输出。
247356- scheduler 自动 backfill。
357+ - ingest 失败重试队列。
358+ - purge / 显式删除能力。
359+ - 无参数 ` csep session-ingest ` 增量扫描。
248360- 远程同步或共享 recall 存储。
249361
250362## 风险与兜底
@@ -278,19 +390,29 @@ recall 输出受总预算、单消息预算、命中数量和窗口大小共同
278390使用小型 fake Codex jsonl fixture,覆盖:
279391
280392- user、assistant、tool message
393+ - tool call 参数摘要和 tool output
394+ - raw json 保存但不进 FTS
281395- 缺字段事件
282396- 缺 cwd / repo metadata
283397- 重复 ingest 幂等
398+ - 同一 session 多次 Stop hook ingest 不重复
399+ - 原始 jsonl 删除后不自动删除 SQLite 消息
284400- parser error 写入 receipt 且不中断整批
401+ - ` session-archive ` 0 条可读 message 时失败
402+ - ` session-archive ` tool metadata 解析失败但文本入库时只 warning
285403
286404### SQLite / FTS 测试
287405
288406使用临时 state dir,验证:
289407
290408- 导入内容能通过 FTS 搜到
409+ - FTS5 phrase / OR / NOT / prefix 查询可用
410+ - FTS5 语法异常被 sanitize 或软失败
291411- same-repo 默认过滤生效
292412- ` --global ` 能返回跨 repo 结果
293413- 当前 repo 无命中时,不加 ` --global ` 不返回其他 repo
414+ - tool output 默认可搜,但排序低于 user / assistant 命中
415+ - ` --recent ` 默认同仓库,` --recent --global ` 跨仓库
294416
295417### 消息窗口测试
296418
@@ -299,6 +421,7 @@ recall 输出受总预算、单消息预算、命中数量和窗口大小共同
299421- ` before ` / ` after ` 行为
300422- session 开头和结尾边界
301423- 同一 session 多个命中
424+ - 同一 session 多个分散命中只返回最佳窗口
302425- 重叠窗口去重
303426- tool output 截断
304427
@@ -316,10 +439,15 @@ recall 输出受总预算、单消息预算、命中数量和窗口大小共同
316439
317440覆盖:
318441
319- - ` csep session-ingest `
442+ - ` csep session-archive --from-hook-payload <payload.json> `
443+ - ` csep session-archive --transcript-path <path> --cwd <cwd> --session-id <id> `
320444- ` csep session-ingest --backfill `
445+ - ` csep session-ingest --backfill --since-days 30 `
446+ - ` csep recall --recent `
321447- ` csep recall "query" `
322448- ` csep recall "query" --global `
449+ - ` session_recall.enabled = false ` 时 fallback 到现有 recall search
450+ - ` session_recall.stop_hook_archive = false ` 时 Stop hook 不归档
323451- SQLite 不可用时 fallback 到现有 recall search
324452
325453主要验证命令:
0 commit comments