feat(runtime): 文档摄取①(抽取器 + sidecar + 装配期 resolveDocuments)(design/24 S3-A)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 抽取器零新依赖纯函数:UTF-8 清洗、CSV/TSV 行数列名摘要、64K rune 安全截断;PDF/Office/二进制走哨兵错误诚实拒绝(不引解析库)。

- sidecar:<DataDir>/extracted/<存储名>.txt,首行紧凑 JSON 元数据 + 正文;临时文件 + rename 原子落定;只抽一次(删原文件仍出正文);版本不匹配/坏缓存重抽。

- 装配期 resolveDocuments(resolveImages 同位,每步对模型可见视图注入):清单恒在(解析器缺席/报错也在)、截断带续读游标、失败诚实标记 + status=unreadable、回合继续;文档部件永不抵达编码器(负例钉住)。

- 修 S2 移交的两处静默吞掉:checkpoint 比较键纳入文档引用、compactor token 估算计入文档部件(不是免费的)。

- 主会话独立验收:隔离 worktree(HEAD + 本切片)build/vet 绿、全树 59 包 0 FAIL、linux/amd64 + darwin/arm64 交叉编译绿、documents+loop 两包 167 条 PASS;变异独立复现(resolveDocuments 短路 ⇒ 3 条红,含「文档部件仍抵达下游」)。
This commit is contained in:
AskaEth committed 2026-10-04 17:22:05 +08:00
1 parent 834ef3683e
commit a8851dc0a2
12 files changed
+2008 -7

No files matched your search

+8
View File
@@ -126,6 +126,14 @@ func (l *Loop) driveTurn(ctx context.Context, sessionID string, msgs []model.Mes
if len(steered) > 0 {
view = append(view, steered...)
}
// 装配期解析文档部件(design/24 §2.3-①、§4):每条携带文档部件的消息在
// 这里被**确定性**换成「清单行 + 正文」文本块,因此文档部件绝不抵达编码器
// (S2 的编码器对文档 fail-loud,漏一个就是一次 400)。位置与 Run 开头的
// resolveImages 同族,区别是它作用于**本步的模型可见视图**而不是消息窗口:
// 窗口只留引用(§2.4),正文每次按引用读 sidecar 注入,checkpoint 因此不会
// 被正文撑大;回合中途经 steer 并入的消息(含附件)也在同一处被解析。
view, docRefs := l.resolveDocuments(ctx, view)
res.recordDocuments(docRefs)
rc, roundSpan := l.span(ctx, "loop.step", trace.SpanKindStateTransition)
outcome, err := l.step(rc, sessionID, view)