Files
proxycast/docs/aiprompts/governance.md
T
2026-04-13 02:50:53 +08:00

11 KiB

治理判断手册

这份文档回答什么

本文件定义 Lime 仓库的治理判断标准,主要回答:

  • 什么才算“统一事实源”,而不是“又补了一套更新版本”
  • 哪些路径还能继续演进,哪些路径只能收口、下线或删除
  • 遇到新旧并存时,应该先做什么,而不是先补功能再说
  • 如何用仓库现有守卫阻止 compat / deprecated 路径继续膨胀

它是 仓库治理规则,不是某个 AI 工具、reviewer、sub-agent 或外部流程的说明书。

第一原则

同一种能力,在同一时期只能存在一个继续演进的事实源。

其余实现必须被明确归类。

路线图任务防跑偏

如果用户明确绑定了某份路线图,尤其是要求“按顺序继续”“对齐目标”“先完成主线”,治理动作必须服从路线图主线,而不是反过来主导路线图。

执行时额外遵守:

  1. 先重述当前路线图的 主目标 / 当前阶段 / 下一刀
  2. 只有当 dead / compat / deprecated surface 直接阻碍主线收口 时,才优先做治理减法
  3. 不要把“还能删一点旧代码”误当成“继续推进目标”
  4. 连续两轮主要都在删零引用或补文档时,必须重新打开路线图,改选尚未完成的主链项
  5. 汇报治理结果时,必须补一句“这一步如何服务路线图主线”;如果说不出来,就说明这一步不该先做

分类语言

治理默认使用这四类:

  • current:当前唯一主路径,后续需求只允许继续向这里收敛
  • compat:兼容层,只允许委托、适配、告警,不允许继续长新逻辑
  • deprecated:废弃层,只允许迁移与下线,不允许新增依赖
  • dead:已停用或确认无入口,优先删除

仓库脚本还可能给出一些辅助信号,例如:

  • dead-candidate
  • unused-file
  • unused-export
  • zero-inbound

这些信号 不是正式分类本身。例如 dead-candidate 代表“很可能可以删”,但不是自动等于 dead,仍需要人工确认。

什么时候先读

出现以下任一情况时,先读本文件,再决定是否改代码:

  • 新旧 Hook、新旧组件、新旧命令并存
  • 前端已经切到新入口,Rust / 数据 / 旁路系统还在继续走旧路径
  • 新服务已落地,但旧表、旧 DAO、旧目录兼容仍被依赖
  • 需求迭代后,AI 倾向沿旧实现继续生成
  • 团队想“先补功能,后面再统一”

治理工作流

1. 先盘点,再修改

开始改动前,先盘点这项能力在 4 层中的分布:

  • 入口层:页面、组件、Hook、前端 API
  • 服务层:Tauri 命令、Service、Workflow、事件入口
  • 存储层:表、DAO、Repository、缓存、迁移
  • 旁路层:统计、记忆、搜索、审计、报表、任务系统

如果没有盘点清楚,禁止直接开始“统一”。

2. 先定事实源,再谈迁移

必须先明确一句话:

从现在开始,这个能力以后只允许向哪里收敛?

事实源可以是:

  • 一个 Hook
  • 一个组件入口
  • 一组 Rust 命令
  • 一个 Service / Repository
  • 一组数据表

没有唯一事实源,任何迁移都会继续长出新分支。

3. 先分类,再动刀

盘点完成后,把实际路径标成以下类型之一:

  • current
  • compat
  • deprecated
  • dead

并为 compat / deprecated 写清退出条件:

  • 迁完哪些调用即可删
  • 哪个版本或阶段必须删
  • 删除前要看哪些扫描结果或指标

没有退出条件的 compat,最终都会常驻。

4. 优先做减法

默认优先执行这些动作,而不是再加一层抽象:

  • 把散落逻辑收回单一边界
  • 把 legacy 判断收回 Repository / Database / app_paths
  • 让 compat 层只做委托与适配
  • 删除零引用入口
  • 把运行时 fallback 改成启动期迁移或边界短路

除非用户明确要求保留兼容,否则不要新增新的 compat 层。

5. 先封旧路,再谈“推荐新路”

治理不能靠口头约定,必须靠守卫机制。

当前仓库优先使用:

npm run governance:legacy-report
npm run test:contracts

它们分别用于:

  • governance:legacy-report
    • 扫描已被判定为 deprecated / dead-candidate 的前端入口
    • 检查旧 Tauri 命令是否仍被限制在指定 API 网关
    • 找出已经零引用、可进入删除候选的兼容壳
    • 规则事实源优先看 src/lib/governance/legacySurfaceCatalog.json
  • test:contracts
    • 检查前端 safeInvoke(...) / invoke(...) 的实际调用
    • 检查 Rust tauri::generate_handler! 的实际注册
    • 检查 src/lib/governance/agentCommandCatalog.json 中的命令治理口径
    • 检查 mockPriorityCommands 与 defaultMocks 是否同步

原则只有一句:

不是鼓励走新路,而是先封住老路。

这同样适用于已经删除的旧 UI 壳或旧组件路径:

  • 删除旧文件后,仍应在治理目录册里补 import / 文本守卫,防止后续 AI 或人工把旧路径重新接回主链
  • 如果已经把重复 UI 的扁平 props 收口为共享契约,也应补对应文本 / 正则守卫,防止父层透传和子层接口一起长回旧面
  • 如果共享契约还依赖单独的构造器或归一化 helper,应继续限制只有事实源边界能调用它,不要让运行时代码到处重新拼装
  • 如果多个页面或面板展示的是同一份状态,也要把状态文案收敛到共享 helper,不要让首页、下拉面板、状态徽标各自重新命名

6. 主链路和旁路一起治理

如果只迁:

  • 页面
  • Hook
  • 主命令

但没有迁:

  • 统计查询
  • 记忆系统
  • 搜索召回
  • 报表分析
  • 审计与任务类旁路

那么旧表、旧命令、旧 DAO 最终都删不掉。

治理完成的标准不是“页面能跑”,而是“系统生态已经收口”。

7. 验证后再删

只有当以下条件同时满足时,才允许删除旧路径:

  • 新增依赖已经被封住
  • 调用量或引用已清零
  • 旁路系统已经迁完
  • 边界检查与定向验证通过

Lime 特别关注的三类边界

1. 命令边界

只要改动涉及 Tauri 命令、Bridge、mock、前端 API 网关,至少同时看这几处:

  • 前端 safeInvoke(...) / invoke(...)
  • Rust tauri::generate_handler!
  • src/lib/governance/agentCommandCatalog.json
  • src/lib/dev-bridge/mockPriorityCommands.ts
  • src/lib/tauri-mock/core.ts

命令边界的详细规则,直接看:

  • docs/aiprompts/commands.md

2. 运行时路径边界

涉及用户数据、日志、缓存、凭证、workspace、历史目录兼容时,优先收口到统一路径入口,例如 app_paths 或等价边界。

不要在上层继续手写:

  • ~/Library/...
  • C:/Users/...
  • ~/.lime/...

路径兼容是边界问题,不应该变成业务层到处散落的字符串问题。

3. 数据迁移与语义暴露

一旦历史数据迁移已接入启动流程:

  • 运行时主链路必须优先按“迁移完成标记”短路旧表读取
  • 旧表只允许服务迁移、审计与回放
  • 业务层优先消费 pending_* 等迁移态语义

不要在多个 service 或 command 里重复写:

  • is_migrated
  • legacy_*
  • 手工分叉短路逻辑

过渡期对外暴露的命名,也应该体现“迁移态”语义,例如:

  • pending_*

不要继续让业务层直接依赖:

  • legacy_*
  • general_chat_*
  • 只体现历史实现、不体现迁移语义的模块名

Lime 的典型判断方式

命令与会话主链

遇到 Agent / 聊天 / 会话相关新旧并存时,至少问这几个问题:

  • 前端唯一入口是不是已经收敛到现役 API 网关
  • Rust 唯一入口是不是已经收敛到 agent_runtime_*
  • 旧 chat_*、general_chat_*、历史 helper 是否还在继续长逻辑
  • 命令契约五个事实源之间有没有漂移

只要其中任意一个答案是否定的,就说明治理还没完成。

Harness Engine 主链

遇到 handoff、evidence pack、replay、review、外部诊断交接相关改动时,至少问这几个问题:

  • 运行时事实是不是继续收敛到 agent_runtime_export_evidence_pack
  • replay / analysis / review / GUI 是否只是在消费 evidence pack,而不是重新拼装一套摘要
  • gap 是否只来自“当前线程真实适用但尚未导出”的信号,而不是历史硬编码模板
  • request telemetry 是否已经按 session/thread/turn 真实关联导出;如果当前线程没有匹配请求,是否导出空摘要而不是继续保留 unlinked

只要其中任意一个答案是否定的,就说明 Harness Engine 还在继续长平行事实源。

记忆与旁路

遇到记忆系统治理时,至少同时看:

  • 统一沉淀能力是否继续收敛到 unified_memory_*
  • runtime / 上下文视图是否继续收敛到 memory_runtime_*
  • 统计、搜索、审计等旁路是否还在读旧路径

不要为了补一个功能,再造第三套记忆入口。

自动 reviewer / sub-agent 的角色

如果未来为 Lime 增加 reviewer、hook 或额外 sub-agent,它们只能做 执行器,不能成为新的治理事实源。

它们至少应该检查:

  • 是否新增了与 current 平级的第二套实现
  • 是否让 compat 长了新业务逻辑
  • 是否只迁主链路却漏掉旁路
  • 是否出现新的旧入口引用或旧命令回流
  • 是否补了守卫与验证

它们的输出,也必须回到本文件的分类语言:

  • 哪些是 current
  • 哪些仍是 compat
  • 哪些进入 deprecated
  • 哪些只是 dead-candidate,哪些已经能确认是 dead

明确禁止

出现以下行为,视为违反治理原则:

  • 在旧 Hook / 旧组件 / 旧命令上继续叠加新需求
  • 新增与现役路径平级的第二套实现
  • 前端迁了新入口,但 Rust 仍保留旧主逻辑继续演进
  • 已有统一 Service,却继续让命令层各自写 SQL
  • 主链路改到新表,旁路系统仍直接查旧表
  • 看到“旧代码还能用”,就继续让 AI 沿旧上下文生成

汇报要求

涉及治理类改动时,汇报结果至少应包含:

  1. 本次收掉了哪些 surface
  2. 当前改动分别属于 current / compat / deprecated / dead 中哪一类
  3. 补了哪些守卫和验证
  4. 剩余最值得继续优化的一刀是什么

如果仍保留 dead-candidate、延期白名单或临时例外,必须写明:

  • 具体对象
  • 当前原因
  • 退出条件

相关文档

  • docs/aiprompts/commands.md
  • docs/aiprompts/harness-engine-governance.md
  • docs/aiprompts/quality-workflow.md
  • docs/aiprompts/project-heatmap.md

一句话总结

治理不是继续写一个“更新版本”,而是让系统以后只能向一个版本收敛。