swapit — 家用有毒物品清查与替换引擎 是做什么的?
此技能的作用
swapit 将模糊的担忧(“我家可能有很多塑料和BPA”)转化为一个具体、有优先级、可跟踪的计划。它是有状态的:你的家庭物品库存保存在磁盘上,并在会话之间持续存在。它是本地优先的:零付费服务,除非你明确选择加入(M3)共享知识库,否则没有任何数据离开你的设备。
一次运行即可产生:
- 一份物品清单,记录你拥有的所有物品,每件都带有通用物品类别标签。
- 每件物品的风险评分,反映实际暴露——一个每日高温使用的有划痕的不粘锅,其排名远高于车库里一个未开封的塑料箱。
- 一份分级的**“优先替换”清单**——只需替换5%的物品就能最大程度减少暴露。
- 替换跟踪——选定的替代品、采购状态、检查清单、书签。
- 一份可共享的HTML报告(并且在 M2 中,
swapit serve提供一个实时仪表板)。
三个领域(以及隐私不变性)
| 领域 | 包含内容 | 共享性 |
|---|---|---|
| 1 · 知识 | 危害 → 物品类别 → 替代品(通用的、有引用的事实) | 可共享;已缓存 +(M3)共享知识库同步 |
| 2 · 库存 | 你的物品、房间、数量、品牌、照片、替换计划、书签 | 私有的——永远不会离开设备 |
| 3 · 共享知识库(M3) | 匿名化贡献,用于丰富共享知识图谱 | 选择加入、经过审核、仅限通用事实 |
隐私不变性(约束): 领域-2的库存数据(物品、房间、数量、品牌、照片、购买信息、位置)永远不会跨越同步边界。只有领域-1的通用事实是可共享的,需通过明确的选择加入和可审核的
swapit sync --dry-run。此约束由客户端的允许列表序列化器(scripts/anonymize.py)和共享知识库服务器上的后台保护共同强制执行,并通过模糊测试确保每个真实的库存物品都被网关拒绝。禁止字段列表:anonymize.CONTRIBUTION_FORBIDDEN(state.PRIVATE_FIELDS中关于库存结构的子集)。
数据模型
状态存储在 ~/.config/swapit/(可通过 $SWAPIT_HOME 覆盖;遵循 $XDG_CONFIG_HOME)。
~/.config/swapit/
├── knowledge/ hazards.jsonl · item-classes.jsonl · alternatives.jsonl · products.jsonl · procurement.jsonl
├── inventory/ events.jsonl(仅追加审计) · items.json · swaps.json · rooms.json · bookmarks.json
├── contributions/ queue.jsonl (M3)
├── sync/ config.json · sync-log.jsonl (M3)
└── photos/
节点模式(请参阅 seed/*.jsonl 获取完整、有引用的数据集):
- 危害 —
id · name · aliases · class · mechanism · exposure_routes · regulatory · severity(0-3) · evidence_strength · sources - 物品类别 —
id · name · category · description · hazards[]{hazard_id, presence_likelihood, rationale} · detection_hints · sources - 替代品 —
id · name · replaces[] · material · rationale · tradeoffs · caveats · avoids_hazards · residual_concerns · sources - 采购选项(公开的购买渠道)—
id · alternative · item_class · retailer · region(ISO-3166-1 a2) · area · url · price_min · price_max · currency · as_of · availability · confidence · corroboration_count - 物品(私有)—
id · name · item_class · room · quantity · brand · condition · usage{frequency, food_contact, heat, child_contact} · status · notes · photos - 替换计划(私有)—
id · item_id · chosen_alternative · procurement{status, cost, vendor} · checklist[] · bookmarks[]
风险模型
risk = severity × presence_likelihood × evidence × exposure_relevance × frequency × condition
- exposure_relevance 激活危害的暴露途径,并与物品的使用方式关联(食品接触 + 高温完全激活食物接触/高温危害;皮肤接触对个人护理品至关重要;吸入对清洁/家具至关重要;儿童接触会放大风险)。
- 物品得分 = 每个危害风险的加权和 → 波段 高 / 中 / 低。
- 这是优先级排序智能的核心——类似于采购技能的“主要失效模式”:首先修复导致大部分暴露的那几件物品,而不是列出所有塑料制品作为负罪清单。
模式
| 模式 | 功能 |
|---|---|
init | 创建状态并加载种子知识图谱 |
add | 添加一个家居物品(名称、类别、房间、状况、用途)→ 打印其评估结果 |
assess | 评估一件物品或一个临时物品类别 → 危害 + 风险 + 分级替代品 |
list | 列出库存,可按 --room/--band/--status/--class/--hazard 筛选,按风险排序 |
swap | 创建/更新替换计划:选择替代品,设置状态,检查清单,书签,成本 |
score | 家庭暴露摘要 + 优先替换排名 |
report | 生成自包含的 HTML 报告(Category-C) |
procure | 采购任务摘要 + 已知的购买渠道 用于替换目标(可按 --region 筛选);记录你找到的优惠信息(--retailer/--url/--price-*)到公共共享知识库 |
knowledge | 浏览/搜索知识图谱(list/search/show) |
rooms | 列出/添加房间 |
selfheal | 验证知识边、库存引用和基础引用;出错时返回非零退出码 |
serve | 本地实时仪表板,位于 http://127.0.0.1:8731 — 看板、检查清单、书签、状态;每次点击都写回状态 |
contribute | 加入一个匿名化事实的队列 — product / hazard(物品类别→危害)/ alternative / procurement(公开的购买渠道)/ item-class(新的分类节点);在本地应用并等待共享知识库审核 |
sync | 推送贡献队列并拉取社区知识(选择加入);--dry-run 预览将要发送的;--configure 设置端点 |
典型流程
swapit init
swapit add --name "Old Teflon pan" --class nonstick-cookware --room kitchen \
--condition scratched --frequency daily --food-contact --heat
swapit score # 查看优先替换哪些物品
swapit swap itm_xxxx --to cast-iron-skillet --status sourcing --add-task "buy 10in skillet"
swapit procure itm_xxxx # -> 将任务交给 `procurer` 技能
swapit report --open # 生成可共享的 HTML 报告
与其他技能复合使用
procurer—swapit procure <item>构建需求描述(“更换3个聚碳酸酯水瓶为玻璃/钢瓶”)和准备好的采购提示;procurer 返回有引用的来源和预算范围。bookkeeping(P6) — 一种新的、持久的危害/产品发现(例如,一个新表征的物品类别)会被主动归档到research/entities/,并随后可以流向共享知识库。health— 个人暴露背景。content-creation— 基于图谱生成教育文章。
基础引用纪律
种子知识仅引用权威机构(NIEHS、ATSDR/CDC、美国 EPA、美国 FDA、ECHA/EU REACH、CA OEHHA Prop 65、WHO、EWG)。每条记录至少包含 ≥1 个来源;verified: false 标记这些记录为参考级别(非最新获取)——运行一个源更新(或通过共享知识库)来刷新。如果任何节点失去其引用,selfheal 将失败。这是基于公共卫生科学的消费者指导,并非医疗或法律建议。
资源
scripts/swapit.py— CLI 入口点和命令处理器scripts/state.py— 双领域状态层(PRIVATE_FIELDS定义了同步边界)scripts/ops.py— 单状态修改写入路径(由 CLI 和仪表板共享)scripts/knowledge.py— 知识图谱加载与边解析scripts/risk.py— 暴露风险评分引擎scripts/report.py— 自包含的 HTML 报告生成器(Category-C)scripts/server.py—swapit serve实时仪表板(基于 stdlib http.server,仅本地主机)scripts/anonymize.py— 隐私门:允许列表事实构建器 + 禁止字段扫描scripts/sync.py— 共享知识库同步客户端(队列、--dry-run预览、推/拉、合并)scripts/selfheal.py— 完整性验证器templates/dashboard.html— 实时仪表板(内联 CSS/JS,Category-C)commons/— 网络化共享知识库参考服务器(FastAPI + SQLite;部署受控)seed/{hazards,item-classes,alternatives}.jsonl— 基础引用的初始知识tests/— 风险、知识、自修复、CLI、隐私/匿名化、同步、报告和服务器测试
协作(共享知识库)
贡献内容仅为通用事实 — swapit contribute product|hazard|alternative|procurement|item-class 构建一个匿名化事实(一个公共的产品→物品类别映射、危害边的修正、替代品、购买渠道或新的分类节点),在本地应用并加入队列。swapit sync --dry-run 显示将要发送的内容;swapit sync 推送队列并拉取社区知识(选择加入,需先 --configure)。来自不同用户的相同事实会相互佐证(内容寻址)而不是重复;共享知识库在两个不同的贡献者佐证后才提供该事实(corroboration >= 2)—— 审核基于佐证阈值,而不是置信度阈值,因为 confidence 由调用者提供,单个提交者可能自我批准。隐私不变性在两端都得到强制执行(客户端 anonymize 门 + 服务器后台保护)—— 库存数据永远不会跨过边界。
购买渠道(采购)共享知识库
一个 procurement_option 事实是一个公开的优惠信息:由某个 retailer 在某个 region(ISO-3166-1 alpha-2)销售的更安全的 alternative,带有可选的 url、price_min/price_max + currency + as_of、area 和 availability。它基于 (alternative, retailer, region) 进行内容寻址——同一优惠信息在不同用户间会互相佐证;不同的地区是一个不同的事实(地理尺度轴)。价格/URL/地区是可细化的市场数据:一个具有严格更新 as_of 的佐证会向前刷新价格,绝不会回归较新的数据。隐私边界清晰——公开优惠信息使用 retailer + price_*,绝不使用私有的 vendor/cost(你从哪买的以及花了多少钱会保留在领域 2)。swapit procure <item> --region <CC> 会显示已知的优惠信息并记录你发现的新信息——从而构建一个开放的、详细的、按地理位置划分的数据集,供任何人使用。
路线图
- M1(已发布,0.1.0) — 数据模型、种子知识、CLI、风险引擎、静态 HTML 报告、自修复。
- M2(已发布,0.2.0) —
swapit serve:具有读写回状态功能的本地实时仪表板。 - M3(0.3.0) — 匿名协作 + 网络化共享知识库(
commons/,FastAPI + SQLite)。隐私不变性由客户端和服务器的允许列表序列化 + 模糊测试强制执行。 - M4(本次发布,0.4.0) — 按地理扩展的采购共享知识库 + 分类法增长:
procurement_option(公开的购买渠道,键为(alternative, retailer, region),仅向前刷新价格)和item_class(基于佐证的分类法增长)事实类型;procure显示并记录优惠信息;种子优惠信息覆盖 US/CO/DE/GB;通过固定向量锁定跨语言哈希一致性。部署到 broomva.tech 基础设施需明确授权(凭据/DNS);本技能无需网络即可完全离线运行。