LifeOS LocalIntelligence 立法追踪工作流:从家乡立法动态到可落地的数据管道
2026/9/15 12:25:28 网站建设 项目流程

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 工作流的核心过程非常精简,只有三个步骤:

  1. 解析家乡:通过Tools/Hometown.ts解析出{ city, state }
  2. 拉取立法数据:运行bun run Tools/FetchLegislation.ts,通过 OpenStates API 获取州级待审议与近期生效法案,通过 Granicus/Legistar 知名 URL 发现(well-known URL discovery)获取市议会议程项;
  3. 返回结构化结果:返回被划分为pendingenacted两个数组的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 前提条件

  1. 身份文件中已配置**Hometown:**行;
  2. 已安装 bun 运行时(脚本均以#!/usr/bin/env bun开头);
  3. 可选: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

在完整实现下,返回被划分为pendingenacteditems数组;在当前仓库快照中返回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.jsonUSER/CUSTOMIZATIONS/SKILLS/LocalIntelligence/(Pulse 模块主读取路径)与MEMORY/DATA/LocalIntelligence/(兼容回退路径)

Pulse 侧的读取模块位于 PULSE/modules/local-intelligence.ts,提供GET /api/local-intelligencePOST /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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询