LifeOS LocalIntelligence 立法追踪工作流:从家乡立法动态到可落地的数据管道
【免费下载链接】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 中 LocalIntelligence 技能的Legislation(立法追踪)工作流,讲解如何自动采集家乡城市与州层面的待审议与已生效法律信息,并将其纳入每日本地情报摘要。读完本文,你将掌握该工作流的触发方式、底层数据源与返回结构,并能结合源码理解其容错设计、身份解析与 Pulse 仪表盘集成原理。
一、Legislation 工作流是什么
Legislation 工作流是 LifeOS LocalIntelligence 技能(SKILL.md)中九个并行工作流之一,负责追踪影响使用者家乡(hometown)的待审议(pending)与已生效(enacted)法律,覆盖两类层级:
- 城市条例(city ordinances):市议会议程项、条例表决;
- 州级立法(state-level legislation):州议会待审议法案与近期生效法案,只要对本地有影响即纳入。
其工作流定义文件位于 Workflows/Legislation.md。从技能入口的 Workflow Routing 表可以看到,它的触发意图包括:"pending laws"、"council agenda"、"ordinance vote"、"new laws in effect" 等自然语言表达。
二、执行流程:三步走
Legislation 工作流的核心过程非常精简,只有三个步骤:
- 解析家乡:通过
Tools/Hometown.ts解析出{ city, state }; - 拉取立法数据:运行
bun run Tools/FetchLegislation.ts,通过 OpenStates API 获取州级待审议与近期生效法案,通过 Granicus/Legistar 知名 URL 发现(well-known URL discovery)获取市议会议程项; - 返回结构化结果:返回被划分为
pending与enacted两个数组的FetchResult,每条数据通过metadata.status标记状态。
2.1 家乡解析:Hometown.ts
Hometown.ts 是整个技能的"单一事实来源"(sole resolver)。它从主身份文件~/.claude/LIFEOS/USER/PRINCIPAL/PRINCIPAL_IDENTITY.md中读取**Hometown:**行,返回结构化的Hometown对象:
export interface Hometown { city: string state: string // 两字母 USPS 州代码(可推导时) stateName?: string // 已知时的全名 zip?: string county?: string citySlug: string // kebab-case slug,用于模板化 URL(如 Patch RSS) stateSlug: string }支持的身份行格式为:
- **Hometown:** Austin, TX (ZIP 78701, Travis County)其中<ST>可以是两字母 USPS 州代码或完整州名;(ZIP <zip>, <County> County)可选但推荐。解析逻辑细节:
HOMETOWN_RE正则严格匹配该 bullet 行;STATE_NAME_TO_CODE内置了 50 州 + 哥伦比亚特区的全名→代码映射(Hometown.ts);- 若州名为全称,会被转换为两字母代码;无法识别时保留原样大写;
parseParenContent从括号中提取 ZIP(支持 5 位与 9 位格式)与县名。
关键设计:技能内部没有任何硬编码的城市字符串,所有 fetcher 和工作流运行时都通过readHometown()动态解析。若身份文件中缺少**Hometown:**行,会抛出NoHometownError,工作流返回明确的设置帮助信息并退出(退出码 2),不存在兜底城市。这也体现在 Release Readiness 检查中——发布前需运行rg -i "<your-city>|<your-zip>|<your-county>"确认零匹配。
2.2 拉取立法数据:FetchLegislation.ts
FetchLegislation.ts 是立法数据的抓取器,遵循整个技能的 Fetcher Contract:
export async function fetchLegislation(home: Hometown): Promise<FetchResult>它同样支持 CLI 直接运行(bun run Tools/FetchLegislation.ts),会先解析家乡再输出 JSON。值得注意的是,当前仓库中的实现体是一个stub——它调用Types.ts中的unavailable()辅助函数,返回:
{ items: [], source_status: "unavailable", errors: ["legislation fetcher not yet implemented — TODO: OpenStates + Granicus discovery for ${home.city}, ${home.state}"] }这是 LocalIntelligence 技能"优雅降级"哲学的直接体现:当一个源对当前城市不可用或尚未实现时,返回unavailable而不是抛异常,从而保证每日摘要的其余七个分类不受影响。
2.3 数据契约:Types.ts
Types.ts 定义了共享类型。每条立法条目符合Item结构:
export interface Item { title: string source: string url: string date: string // 已知则为 ISO 8601,否则为自由格式日期字符串 summary?: string metadata?: Record<string, unknown> }metadata.status用于区分"pending"与"enacted"。整体的FetchResult为:
export interface FetchResult { items: Item[] source_status: SourceStatus // "ok" | "unavailable" | "empty" errors?: string[] }三种状态语义不同(SKILL.md Gotchas 有明确说明):empty表示源返回 200 但零匹配(小城镇常见);unavailable表示 4xx/5xx 或 DNS 失败。Pulse 仪表盘对两者渲染不同的空状态。
三、数据源:三级发现策略
Legislation 工作流的数据源定义在原文档的 Sources 小节,并可在 DataSources.md 的 Legislation 表中找到完整映射:
| 数据源 | 覆盖范围 |
|---|---|
OpenStates API(https://v3.openstates.org/) | 州级待审议 + 已生效法案 |
| Granicus / Legistar | 通过知名 URL 模式发现的市议会议程项 |
| 市议会会议日历 | 暴露为 iCal 或 RSS 时 |
设计要点:
- OpenStates 覆盖州议会,不覆盖市议会(SKILL.md Gotchas 明确警告)。对于市议会的待审议/已生效法律,抓取器通过知名 URL 模式(如
https://<city>.granicus.com/...)尽力尝试 Granicus/Legistar 发现,属 best-effort; - 无城市级配置:所有源均以
{city, state}(偶尔含 county)为键,城市特异性 URL 通过sources.json用户配置层提供,技能本体永不硬编码; - 公开数据边界:整个技能只使用公开数据,禁止付费的人肉搜索聚合器、禁止绕过 CAPTCHA(见 DataSources.md 中 Arrests 一节的声明)。
3.1 可选的用户定制层
在~/.claude/LIFEOS/USER/CUSTOMIZATIONS/SKILLS/LocalIntelligence/PREFERENCES.md中可放置 per-source 覆盖,例如OpenStates API key(获得更高限速)、Google News topic ID、额外的区域报纸 RSS。sources.json则提供确定性的城市级源列表(RSS/JSON 端点),由Tools/UserSources.ts在每次刷新时消费,schema 见 UserSources.help.md。
四、如何运行与验证
4.1 前提条件
- 身份文件中已配置
**Hometown:**行; - 已安装 bun 运行时(脚本均以
#!/usr/bin/env bun开头); - 可选:
LIFEOS_PRINCIPAL_IDENTITY环境变量覆盖身份文件路径,默认路径为~/.claude/LIFEOS/USER/PRINCIPAL/PRINCIPAL_IDENTITY.md。
4.2 验证家乡解析
bun run ~/.claude/skills/LocalIntelligence/Tools/Hometown.ts成功输出 JSON:
{ "city": "Austin", "state": "TX", "stateName": "TX", "zip": "78701", "county": "Travis", "citySlug": "austin", "stateSlug": "tx" }未配置家乡时输出错误信息并exit 2。
4.3 运行 Legislation 抓取器
bun run ~/.claude/skills/LocalIntelligence/Tools/FetchLegislation.ts在完整实现下,返回被划分为pending与enacted的items数组;在当前仓库快照中返回source_status: "unavailable"(stub 实现)。
4.4 发送语音通知
原文档中的 Voice Notification 步骤通过 LifeOS 本地通知服务广播执行状态:
curl -s -X POST http://localhost:31337/notify \ -H "Content-Type: application/json" \ -d '{"message": "Running Legislation in LocalIntelligence"}' \ > /dev/null 2>&1 &同时在对话中输出文本通知Running **Legislation** in **LocalIntelligence**...。
五、与更大系统的集成
Legislation 只是 LocalIntelligence 八个分类之一,理解它需要了解整体编排:
5.1 刷新编排器 Refresh.ts
Refresh.ts 通过Promise.allSettled并行运行八个 fetcher(construction、crime、business、officials、legislation、elections、arrests、news),单个死源不会清空整个摘要。抓取顺序为:内置 fetchers →UserSources.ts(确定性用户配置)→ClaudeFill.ts(仅对仍为空的分类做 AI 补全,且输出必须通过validateSection()校验)。--fill模式供每日 cron 与仪表盘刷新按钮使用。
每个 fetcher 外层包有runOne的 try/catch——即使 fetcher 抛异常也会降级为unavailable结果而非让整次刷新失败。
5.2 输出与 Pulse 集成
刷新输出写到两处(SKILL.md 明确指出两处都必须写,历史上曾因只写旧路径导致仪表盘静默服务过期数据):
- 历史文件:
~/.claude/LIFEOS/MEMORY/DATA/LocalIntelligence/<YYYY-MM-DD>_<city>_<state>_digest.json - 两份
latest.json:USER/CUSTOMIZATIONS/SKILLS/LocalIntelligence/(Pulse 模块主读取路径)与MEMORY/DATA/LocalIntelligence/(兼容回退路径)
Pulse 侧的读取模块位于 PULSE/modules/local-intelligence.ts,提供GET /api/local-intelligence与POST /api/local-intelligence/refresh两个端点;每日刷新由PULSE.toml中的[[job]]在0 6 * * *触发。
此外还有一个no-clobber 守卫:如果某次运行所有分类均为空(fetcher 全挂且补全失败),仍会写入带日期的历史文件,但不会覆盖已有内容的latest.json,避免一次失败的清晨任务把仪表盘清空。
六、实战要点与注意事项
结合 SKILL.md 的 Gotchas,使用 Legislation 工作流时需注意:
- 无家乡行 = 不抓取:不要替用户编造城市,工作流会返回设置帮助信息并以零码退出;
- 数据覆盖因城市而异:有的城市 Granicus/OpenStates 覆盖丰富,有的只发布 PDF,抓取器必须返回
unavailable而非失败; - OpenStates ≠ 市议会:州级立法走 OpenStates,市议会议程靠 Granicus/Legistar 发现,均为 best-effort;
- 每日 JSON 会累积:历史摘要保留在
MEMORY/DATA/LocalIntelligence/供趋势查询,Pulse 只读latest.json,定期清理由用户决定; - 付费墙边界:本地报纸的优质报道常被付费墙挡住,RSS 通常只暴露标题+摘要,技能从不绕过付费墙;
- 执行日志:工作流完成后,向
~/.claude/LIFEOS/MEMORY/SKILLS/execution.jsonl追加一行 JSONL 记录(含时间戳、工作流名、8 词输入摘要、状态与耗时),形成可审计的执行历史。
七、小结
Legislation 工作流是 LocalIntelligence 技能"全美任意城市通用"设计哲学的缩影:运行时解析家乡、按知名 URL 模式做通用源发现、无法获取时优雅降级、确定性数据优先于模型补全。虽然当前仓库快照中 FetchLegislation.ts 还是 stub,但围绕它的数据契约(metadata.status区分 pending/enacted)、三级源发现策略、容错编排与 Pulse 集成链路均已完整落地,任何贡献者都可以在既有契约下补全 OpenStates 与 Granicus/Legistar 的具体抓取实现。
【免费下载链接】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),仅供参考