Observation Schema
定义
Observation Schema 是该架构演进中为 observations 表定义的一条 observation 记录的数据结构。它不是泛指任意“观察数据格式”,而是明确指向数据库表 observations 中的单条记录如何被拆分、存储与约束。
这个 schema 的核心对象,就是 observations 表里的单条 observation 记录。该记录被组织为几类信息:记录标识与归属、渐进披露用的摘要层字段、核心叙述正文、事实与概念数组、文件读写轨迹,以及时间戳字段。
在本文档中的语境
在 Architecture Evolution 摘要 所描述的演进片段里,Observation Schema 属于“rich, structured schema”的一部分。其目标不是只保存一大段不可分解文本,而是把一条 observation 拆成多个可单独利用的字段,以同时满足结构化存储、后续检索、全文搜索和进一步分析的需要。
这也解释了它为何既保留 narrative 这样的完整正文字段,又额外引入 facts、concepts、files_read、files_modified 等数组字段:同一条记录既能被完整阅读,也能被程序按事实、标签和文件轨迹进行筛选、聚合与索引。这一设计与 FTS-backed Observation Search 直接相关,因为后者会把其中部分字段送入全文索引。
关键组成
主键与关联
id INTEGER PRIMARY KEY AUTOINCREMENT:id是主键,类型为整数,并且自增。session_id TEXT NOT NULL:session_id是必填字段。FOREIGN KEY(session_id) REFERENCES sdk_sessions(id):session_id通过外键关联到sdk_sessions(id),用于把 observation 归属到某个 session。project TEXT NOT NULL:project用于标识这条 observation 所属的项目,而且不能为空。
这里的结构说明,一条 observation 不是孤立存在的。它至少同时绑定到一个 session 和一个 project:前者表示它来自哪次会话,后者表示它属于哪个项目上下文。
渐进披露元数据
该 schema 明确把 title、subtitle、type 归为“Progressive disclosure metadata”,也就是渐进披露所需的摘要层信息:
title TEXT NOT NULL:标题,必填。subtitle TEXT:副标题,可为空。type TEXT NOT NULL:类型,必填,注释中给出的例子包括decision、bugfix、feature等。
project 与 title / subtitle / type 共同构成记录在上层界面、列表视图或摘要视图中的可读外壳。其中 project 负责标识归属项目,而 title、subtitle、type 负责让同一条 observation 在不展开正文时也能被快速理解、分类和浏览。
核心正文
narrative TEXT NOT NULL:narrative是核心正文内容,而且被明确标记为NOT NULL。
这意味着无论一条 observation 是否补充了事实数组、概念标签或文件轨迹,它都必须至少有一段叙述性正文。换言之,Observation Schema 不是只有元数据和标签的空壳;narrative 才是记录内容的主体。
事实与概念
facts TEXT:用于保存事实列表,注释说明其内容是 JSON array。concepts TEXT:用于保存概念标签,注释说明其内容是 JSON array of tags。
facts 与 concepts 都存储在文本列中,但语义上都要求是 JSON array。前者面向“这条 observation 提炼出的事实项”,后者面向“可用于标注和检索的概念标签”。这说明 schema 采用的是“数据库列为 TEXT、应用层内容为 JSON array”的设计,而不是单独建子表。
文件读写轨迹
files_read TEXT:记录本条 observation 涉及读取过的文件,内容是 JSON array。files_modified TEXT:记录本条 observation 涉及修改过的文件,内容也是 JSON array。
这两个字段把 observation 与文件操作历史连接起来,使一条记录不仅描述“发生了什么”,还描述“读了哪些文件、改了哪些文件”。因此 Observation Schema 不只是叙事或标签模型,也是可追踪文件接触面的活动记录模型。
时间信息
created_at TEXT NOT NULL:文本形式的创建时间,必填。created_at_epoch INTEGER NOT NULL:整数形式的创建时间,必填。
时间信息被同时保存为文本和 epoch 整数,说明该 schema 同时照顾可读展示与数值排序/过滤两类需求。
机制特点
Observation Schema 的一个关键特点,是把单条记录拆成“可阅读正文”和“可机器利用的结构化侧面”两层。
具体来说:
narrative提供完整叙述,保证上下文与可读性;title/subtitle/type提供渐进披露所需的摘要层;facts提供可枚举的事实列表;concepts提供可检索的概念标签;files_read/files_modified提供与文件交互相关的轨迹;session_id、project、created_at、created_at_epoch提供归属与时间上下文。
这种设计让同一条 observation 能够支持多种使用方式:可以像日志一样阅读全文,可以像结构化事件一样筛选类型和项目,也可以像知识条目一样按概念和事实进行搜索与聚合。
与全文搜索的关系
虽然 Observation Schema 本身定义的是 observations 表中的记录结构,但它与全文搜索机制是连在一起设计的。
在同一段架构中,FTS5 虚拟表 observations_fts 会索引以下字段:
titlesubtitlenarrativefactsconcepts
这说明 Observation Schema 中并不是所有字段都会进入全文搜索。像 files_read、files_modified、project、时间戳等字段,在给出的定义里并不属于 FTS5 索引列;而 title、subtitle、narrative、facts、concepts 则被明确纳入全文检索范围。这也是它与 FTS-backed Observation Search 的接口边界。
细节与边界
哪些字段是必填的
从表定义可直接看出,下列字段带有 NOT NULL 约束:
session_idprojecttitletypenarrativecreated_atcreated_at_epoch
而 subtitle、facts、concepts、files_read、files_modified 没有被标记为 NOT NULL,因此在数据库层面允许为空。
JSON array 是语义约束,不是独立表约束
facts、concepts、files_read、files_modified 都是 TEXT 列,但注释明确要求它们承载 JSON array。这表示数组结构主要靠应用层约定与写入逻辑维护,而不是通过关系型子表来强制建模。
它描述的是单条 observation,不是整个搜索索引
Observation Schema 的边界是 observations 表中的一条记录。虽然它与 FTS 表及触发器配套出现,但 FTS 虚拟表 observations_fts、自动同步触发器,以及更广义的检索机制,不属于这个 schema 本体,而属于围绕该 schema 构建的搜索基础设施。