
LifeOS Pulse collection 适配器完全指南把 Markdown 清单解析为结构化 JSON 的抽取规则与运行链路【免费下载链接】LifeOS⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work.项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS导读本指南围绕 LifeOS 中 Pulse 子系统的collection页面适配器展开——它负责把用户USER/目录下用「LifeOs collection 格式」书写的清单型 Markdown书籍、电影、工具、灵感等收藏条目抽取为符合CollectionPageSchema的 JSON 对象供 Pulse 记忆层做结构化存储与后续检索。读完本文你将掌握 collection 输入格式的宽容解析规则、CollectionPageSchema每个字段的取值约束、星级到 1–10 整数的换算逻辑以及从 manifest 加载、源码打包、模型推理到 Zod 校验、数据落盘的完整运行链路。collection 页面在 Pulse 数据模型中的定位LifeOS 的 Pulse 子系统把「用户记忆」按四种kind建模见 PulseSchema.tsexport const KindSchema z.enum([collection, narrative, reference, index]);collection清单型页面一条一条的条目本书、这部电影、这家餐厅……narrative叙事型页面由带层级的 sections 组成如 Identity 页reference键值对型页面形如key → value的速查表index索引型页面汇总某个领域目录下的子页面清单。本指南聚焦的kind: collection是其中结构化程度最高的一种输入是用户随手写的列表输出是严格的 JSON 数组。与之配套的适配器提示词统一存放在 adapters/prompts 目录下collection.md正是 collection 页面专用的 system prompt。输入侧LifeOs collection 格式与宽容解析规范格式适配器接收的是用户USER/文件中拼接后的 Markdown 源码。用户在 LifeOS 中书写收藏条目的推荐格式为- **{name}** — {creator} · ★{rating} · {notes}字段拆解位置含义说明name条目名称加粗文本必填creator创作者/来源位于—之后可选rating评分★标记后的数值可选notes备注评分之后的所有内容可选例如一个真实可解析的列表- **沙丘** — 弗兰克·赫伯特 · ★9 · 史诗科幻世界观设定极其完整 - **The Pragmatic Programmer** — Hunt Thomas · ★8 · 工程师必读建议每两年重读一次 - **星际穿越** — Christopher Nolan · ★7 · 硬科幻与亲情的结合宽容变体permissive parsing适配器提示词明确要求对输入形状保持宽容Be permissive on input shape用户实际写出的可能包括无加粗、无 creator 分隔符的普通项目符号列表纯编号列表1. ...、2. ...混排格式部分条目规范、部分随意隐式提及条目的叙事性散文没有列表符号仅靠语义识别条目。对应规则是尽量识别出每一个条目而不是因为格式不整齐就丢弃。这与 goals 适配器goals.md中「从长文档里抽取活跃目标」的容忍度策略一致——提示词层级已经承担了格式归一化的职责上层只负责校验结果是否符合 Schema。输出侧CollectionPageSchema 完整字段解析适配器输出必须匹配CollectionPageSchema定义于 PulseSchema.tsexport const CollectionPageSchema z.object({ kind: z.literal(collection), title: z.string().min(1), category: CategorySchema, description: z.string().optional(), items: z.array(CollectionItemSchema), meta: PageMetaSchema, });顶层字段字段类型来源约束kind字面量collection固定Zod 判别联合的判别字段必须是collectiontitlestringmanifest 的 title 或源码首个 H1非空由适配器从页面标题推断categoryCategory适配器推断见下方枚举descriptionstring?导语段lede paragraph可选一行概括itemsCollectionItem[]逐条抽取数组可为空metaPageMeta由 AdapterRunner 填充提示词要求模型输出占位对象{}category 枚举CategorySchemaPulseSchema.ts是枚举与自定义字符串的联合类型export const CategorySchema z.union([ z.enum([identity, voice, mind, taste, shape, ops, domain]), z.string().min(1), ]);内置类别为identity | voice | mind | taste | shape | ops | domain同时允许任何非空自定义字符串。以收藏清单为例美食清单可以归为taste工具收藏可归为ops领域知识清单可归为domain——既给了语义锚点又保留了用户自定义空间。items 条目结构CollectionItemSchemaPulseSchema.tsexport const CollectionItemSchema z.object({ name: z.string().min(1), creator: z.string().optional(), rating: z.number().int().min(1).max(10).optional(), notes: z.string().optional(), private: z.boolean().default(false), });字段类型约束说明namestring必填非空条目名称creatorstring?可选创作者/来源ratingnumber?整数1–10评分见下方换算规则notesstring?可选备注privateboolean默认false隐私标记一个完整输出示例假设源码为上文「沙丘」列表适配器应产出如下 JSONmeta 为占位{ kind: collection, title: 爱读的书, category: taste, description: 过去一年反复翻阅的科幻与工程类书籍, items: [ { name: 沙丘, creator: 弗兰克·赫伯特, rating: 9, notes: 史诗科幻世界观设定极其完整, private: false }, { name: The Pragmatic Programmer, creator: Hunt Thomas, rating: 8, notes: 工程师必读建议每两年重读一次, private: false }, { name: 星际穿越, creator: Christopher Nolan, rating: 7, notes: 硬科幻与亲情的结合, private: false } ], meta: {} }抽取规则逐条详解原规范 源码佐证collection.md 定义了八条核心规则逐条展开如下。1. 识别所有条目宽容输入形状见上文「宽容变体」一节。这一条对应 Schema 中items: z.array(...)的「尽量多条目」倾向——宁可部分字段缺失也不要漏条目。2. rating 必须是 1–10 整数五星制自动缩放ratingis 1–10 integer. If user uses 1–5 stars, scale to 1–10 (3.5 stars → 7).换算规则为线性乘 2用户五星制映射到 1–10★24★3.57★48★510该约束在 Schema 层由z.number().int().min(1).max(10)强制兜底PulseSchema.ts——即使模型换算出错输出11Zod 校验阶段也会判定为validation-failed而不会把脏数据写入数据平面。3. private 标记满足以下任一条件即视为私有条目条目行以(private)前缀开头条目携带private:标志对应 goals 适配器中 frontmatterpublish: false的同类语义。Schema 侧private: z.boolean().default(false)保证缺失时默认为公开不会因遗漏字段而报错。4. 跳过「不再相关」的条目用户通过删除线标记strikethrough或(removed)前缀表示条目已失效适配器必须跳过它们而不是原样抽取。5. notes 捕获 rating 之后的所有内容notescaptures everything after the rating that isnt part ofcreator.即notes 行内 rating 之后剩余的叙述性文本。若用户只写了**书名** — 作者 · ★8 · 短评则notes为「短评」若无 rating 但有附加文字从可解析的最靠后位置截取。6. 部分填充是允许的If you cannot infer creator/rating/notes from a line, just emitname— partial fills are fine.某一行实在无法推断出 creator/rating/notes就只输出name。例如用户写了一条裸文本- 禅与摩托车维修艺术合法输出是{ name: 禅与摩托车维修艺术, private: false }这保证了「宁缺毋滥」与「不漏条目」之间的平衡——Schema 中 creator/rating/notes 全部 optional正是为部分填充设计的。7. 空 sources输出空数组 meta 警告If sources have NO items at all, emititems: []and add a meta warning no items found in sources.当源码中完全没有可识别条目时不要臆造条目而是{ kind: collection, title: 空清单, category: taste, items: [], meta: { warnings: [no items found in sources] } }这条警告会随 meta 一起被 AdapterRunner 读取并写入页面元数据AdapterRunner.ts成为后续诊断「为什么页面是空的」的直接线索。8. 输出纪律只输出 JSONOutput ONLY the JSON object. No prose, no markdown fence.这是所有 adapter prompt 的公共纪律index.md、identity.md均以 Output ONLY the JSON object. 结尾。原因是下游callInference以expectJson: true调用推理层若模型混入散文或 json 围栏会落入parse-failed分支AdapterRunner.ts整页构建失败。meta 字段为什么提示词里是占位符{}collection.md 要求模型输出meta: { /* will be filled by AdapterRunner — leave as a placeholder object {} */ }这是有意设计模型不负责生成可信的运行元数据。真正的 meta 由 AdapterRunner 在运行时覆盖写入AdapterRunner.ts包含const meta: PageMeta { schemaVersion: SCHEMA_VERSION, // 1.0.0 pageId: manifest.id, lastBuildAt: new Date().toISOString(), sourceHashes, // 每个源文件的哈希 adapterVersion: manifest.adapterVersion, model: manifest.model, costUSD: inferenceResult.costUSD, latencyMs: inferenceResult.latencyMs, provenance, // template | customized | mixed warnings: adapterData.meta?.warnings ?? [], };对应PageMetaSchemaPulseSchema.ts。其中provenance由aggregateProvenance汇总各源文件的 frontmatter 印记全部为 template 得template全部 customized/unknown 得customized混合得mixedAdapterRunner.tssourceHashes是缓存键的核心组成与adapterVersion、model、SCHEMA_VERSION一起拼接出cacheKey——命中缓存时跳过推理直接返回status: cachedAdapterRunner.ts。端到端运行链路从 manifest 到数据平面collection 适配器并非独立脚本而是 Pulse「manifest → 推理 → 校验 → 落盘」管线中的一个环节。以 collection 页为例完整链路如下加载 manifestloadAllManifests读取pages/目录下所有*.manifest.tomlmanifest-loader.ts。Manifest 字段manifest-loader.ts包括id、title、dataType即CollectionPageSchema等 Schema 名、sourceGlobs、adapterPromptFile指向collection.md、model、adapterVersion、staleAfterHours等解析 sourcesresolveSources把sourceGlobs展开为实际文件路径支持通配符manifest-loader.ts。注意 collection 的源码来自USER/文件与 goals 页读取LIFEOS/USER/TELOS/TELOS.md的单一来源不同collection 通常是多文件聚合源码打包buildSourceBundle把每个源文件按### SOURCE: {path}头拼接并标注来源路径AdapterRunner.ts推理callInference以collection.md全文作为 system prompt、源码包作为 user prompt调用inference({ expectJson: true, timeout: 120_000 })AdapterRunner.ts。模型名到推理档位的映射由 model-level.ts 从EFFORT_MODEL推导如 haiku→low、sonnet→mediumSchema 校验schema.safeParse(candidate)用 Zod 校验模型输出任何非法字段如 rating11、缺 name都会进入validation-failed状态错误详情写入 error 文件AdapterRunner.ts落盘通过校验后writePage以原子写方式把{ schemaVersion, data, _meta }写入~/.claude/LIFEOS/MEMORY/PULSE_DATA/{pageId}.jsonmeta 单独存为{pageId}.meta.jsondata-plane.ts。六种结果状态由AdapterResult.status表达success | cached | validation-failed | inference-failed | timeout | no-sources每次运行都会追加到adapter-runs.jsonl观察日志供 Observability 层审计成本与延迟AdapterRunner.ts。同类适配器对照Goals 页同样是 collection值得注意kind: collection并不只服务「收藏清单」一类语义——goals.md 中用户 TELOS 文件里的「活跃目标」同样被建模为CollectionPageSchema只是规则差异明显维度collection.md本指南goals.md输入来源USER/ 任意清单型文件LIFEOS/USER/TELOS/TELOS.mdcategory按内容推断taste/ops/domain…固定domaintitlemanifest 或首个 H1固定Goalscreator/rating可选明确不使用保持 undefined抽取边界所有可识别条目仅「今年活跃追求」的目标跳过 aspirational 项对照结论同一个 Schema、同一套宽容抽取哲学通过不同 prompt 实现不同领域语义——这正是 adapter 体系的复用价值所在。若你自己要新增一种清单型页面如「年度愿望清单」只需要复制 collection.md 调整规则并写一个 manifest 指向它数据平面与校验链路完全复用。校验与调试让脏数据在落盘前被拦下validatePageDataPulseSchema.ts暴露了统一的校验入口KIND_TO_SCHEMA与getSchemaByNamePulseSchema.ts允许按 Schema 名动态取用。这意味着你可以在不跑完整管线的情况下单独验证一段候选 JSONrating 超出 1–10 →issues中报告items.2.rating越界kind不是collection→ 判别联合直接失败缺name或title→ 违反z.string().min(1)。一旦校验失败AdapterRunner 会写入{pageId}.error.json含schemaVersion、pageId、occurredAt、错误路径与消息见 contenteditable="false">【免费下载链接】LifeOS⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work.项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考