Lattice:血缘链路(Lineage)与本地 Ticket 驱动的 Agent 工作流
Lattice
血缘链路(Lineage)与本地 Ticket 驱动的 Agent 工作流。
开源了一套团队内部使用的 workflow skill,一句话简介:给 Claude Code / Codex 这类编码 agent 一条从「产品意图」到「合并入库 PR」的有纪律的路径,本地运行,复用你现有的 Git / GitHub 凭证,不连任何后端服务。
我们不想把它做重——没有用一堆细粒度 prompt 去和模型抢控制权;但也不打算放任它裸奔,而是希望把团队的最佳实践沉淀进流程,让模型动手前能拿到全局上下文(这条需求从哪来、拆成哪几张ticket、要满足哪些验收),从而更好地从全局考虑去解决问题。
仓库地址:github.com/percena/lattice
为什么再做一个工作流
此前的一些框架,比如 superpowers、Trellis 都很优秀,是它们把「给 agent 一套结构化交付流程」做了精心设计,很多思路也与我们内部的想法不谋而合。但随着更新越来越频繁,大模型越来越智能,可能很多用户跟我们会有类似的体感:
- 框架越做越重——框架本身在不断加层,技能、子 agent、hook、上下文注入一层套一层,上手和日常维护的心智成本都上去了。
- 细节定得太死——为了把流程焊牢,很多框架把每一步该怎么想、按什么顺序想、输出什么句式都用 prompt 规定死。早期那几代模型确实需要这么管,但这套细粒度的约束,对现在的高智能模型反而是一种束缚——它自己会想事,框太死反而把能力给压住了。
Lattice 就是为缓和这个问题来的。一面给模型减负、留白,不让流程约束去和大模型抢方向盘;一面把团队的最佳实践沉淀进流程,让模型在动手前先有个全局视图——这条需求是从哪个 spec 来的、拆成了哪几张ticket、要满足哪些验收、上一个人 review 留了什么结论。换句话说:该松的地方松开手脚,该托的地方把全局托住。
它要解决什么
经常 Vibe Coding 的开发者大概都有体会:agent 很能写,但跨会话很难「接住」。一次会话里它干得飞起,第二天开新会话,上下文丢了,分支烂了,PR 不知道该对什么验收。要么人肉记笔记,要么靠一堆临时 prompt 拼命把状态喂回去。
Lattice 把这件事工程化:用稳定的 ID 把「这条需求 → 这张ticket → 这个 worktree → 这个 PR」串成一条可续作的血缘链,agent 只认 ID 不认运气。
换个角度说,其实 Claude Code、Codex 这些框架自带 Memory 功能,跨会话续作不是没有现成机制。但问题在于:Memory 怎么创建、怎么索引,对开发者很不透明。 它存了什么、什么时候触发写入、下次怎么被捞起来——大多是框架黑箱里的事,你想检查、想干预、想让团队复用同一套记忆,基本无处下手。Lattice 要优化的就是这个环节:把 Memory 从黑箱里搬出来,变成你看得见、grep 得到、能 review、能随仓库一起 commit 的本地文件。spec、ticket、review 全是模板化的本地活页夹(ADR 在 docs/adr/),谁写的、什么时候写的、关联到哪条需求,一清二楚——Memory 不再是「框架替你记的」,而是「你和团队一起维护的、显式的工程产物」。
核心理念:约束路径,不约束大脑
承接上面——既然不打算用细粒度 prompt 把模型焊死,那 Lattice 到底约束什么?答案是:只约束路径,不约束脑子。
Lattice 不走那条把模型焊死的路。我们的态度是:
- 助力,不完全是驯化——在模型「不规范」的地方(忘了绑ticket、PR 没写 Why、worktree 没对齐 base)把它拽回正轨,但实现思路怎么走、代码怎么组织,全留给模型自己定。
- 只锁路径,不锁细节——约束的是「从 spec 到 PR 这条主干不能跳步、不能丢血缘」,至于每一步内部怎么干,不给剧本、不给模板,让模型发挥。
- 基本轨线 + 留白——该有的护栏(worktree 隔离、alignment 验收、ID 续作)守牢,剩下的空白区域交给模型。护栏是底线,不是天花板。
一句话概括:给现代高智能模型一套最薄的纪律底座,让它既有迹可循、又不被捆住手脚。这套分寸,对越聪明的模型越合适——它需要的是「接得住」的续作链路,不是「按我说的做」的提词器。
改了什么
1. 六技能闭环,不是一坨 prompt
核心是六个可移植 Agent Skills,按顺序走完一条交付环:
1 | |
每个 slash 命令干什么,一句话讲清:
| 技能 | 干什么 | Slash |
|---|---|---|
start-work |
分类 S/M/C、绑 ticket + worktree、按 id 续作 | /start-work |
create-spec |
持久化带验收标准的 Spec(spc-n) |
/create-spec |
create-review |
持久化带显式 outcome 的 Review(rev-时间戳) |
/create-review |
create-tickets |
把锁定范围拆成 GitHub issues + 活页夹 | /create-tickets |
create-pr |
开/更新格式规范的 PR(Why/How + Fixes/Refs + Spec 行号) | /create-pr |
finish-work |
更新 base、对齐检查、合并、清 worktree | /finish-work |
_lattice-lib |
上面六个共用的脚本底座(共装,非 slash 入口) | — |
2. 本地血缘活页夹:.lattice/,优先本地检索
先说「血缘(lineage)」是什么——很多人没听过这个词。简单讲:一条需求从立项到合并,留下一条能回头追溯的链。这条需求(Spec)拆成了哪几张ticket(Ticket),每张ticket落进了哪个 PR,PR 又对齐了哪条验收——这些节点之间互相关联、能顺藤摸瓜,就是「血缘」。
Lattice 把这条链的每个节点都写成一个稳定的本地文件,而不是只存在 GitHub 上。每件事落一个 ID,ID 就是文件名的一部分:
| ID 形态 | 含义 | 落在哪 |
|---|---|---|
spc-N |
Spec(N = GitHub issue 号) | .lattice/specs/spc-N-*.md |
tkt-N |
Ticket / 工作单元 | .lattice/tickets/tkt-N-*/README.md(一张ticket一个活页夹目录) |
pr-N |
交付 PR | GitHub PR 本体(合并在活页夹 ledger 里记一行) |
rev-YYYYMMDD-HHMMSSZ |
Review(UTC 时间戳) | .lattice/reviews/rev-*.md |
adr-NNN |
架构决策记录(带外伴生) | docs/adr/NNN-*.md |
为什么非要写成本地文件?这是 Lattice 的一个核心理念:能本地查的,尽可能不去联网。
想想 agent 干活时最常问的问题:「这张ticket的验收标准是啥?」「上个 review 决定了啥?」「这个 spec 拆成哪几张ticket了?」如果这些都得调 GitHub API、翻 issue/PR 评论,联网往返又慢又脆——网络抖一下、限流一下,agent 就卡在那等。Lattice 的做法是把 Spec、Ticket、Review 这些模板化地预生成本地活页夹(ADR 在 docs/adr/),agent 要查上下文,直接 cat / grep 本地文件,毫秒级拿到,不联网、不限流、不花一分钱。
| 查什么 | 别的方案 | Lattice |
|---|---|---|
| 这张ticket的验收标准 | 翻 GitHub issue 评论 | cat .lattice/tickets/tkt-N/README.md |
| 上次 review 的结论 | 翻 PR 评论 | cat .lattice/reviews/rev-*.md |
| spec 拆成哪几张tickets | 拼 issue 关系图 | .lattice/tickets/*/README.md 里每张ticket都写了 Path: spc-N → tkt-N → (pr-…) |
| 整条血缘链 | 多次 API 调用 | 一个 grep -r spc-N .lattice/ 全出来 |
本地优先,GitHub 只在必要时才查:本地活页夹是主检索源——绝大部分上下文查询(验收标准、review 结论、spec/ticket/PR 的对应关系)在本地一次 cat/grep 就够了,命中毫秒级。真正需要 GitHub 的,是那些只能从远端拿到的事实(issue/PR 的实时状态、评论、CI 结果)——这种才走 gh API 联网查。换句话说,联网是补充,不是默认;本地能覆盖的绝不去敲 GitHub 的门,效率自然高。
而消费仓里只留 .lattice/ 活页夹(specs / tickets / reviews / config),GitHub Issues 和 PR 本身就是交付记录——不把工作流逻辑塞进你的业务代码仓。这是 Lattice 的「引擎 vs 消费仓」分离设计:
引擎仓 percena/lattice |
你的消费仓 | |
|---|---|---|
| 角色 | 工作流逻辑 + 插件 | 干活的地方 |
| 安装 | 技能/插件装在机器上(建议全局) | 不需要拷 skill 正文 |
| 每仓设置 | — | 对人零设置,技能自动 ensure .lattice/ |
| 日常 | 维护/发版本 | /start-work … /finish-work |
3. 两种 profile:strict(默认)/ light
Lattice 是 discipline-first(纪律优先),不是装个主题就完事。默认 strict:可发布分支默认走 sibling worktree,合并前 alignment-check 对 Acceptance 是 HARD(不过就 exit 1)。嫌重可以 opt-in light:
| strict(默认) | light(opt-in) | |
|---|---|---|
| 可发布隔离 | sibling worktree 默认 | 允许 --mode branch |
绑 tkt- / spc- |
默认 | 默认;允许语义未绑 + 理由 |
alignment-check 开放 Acceptance on Fixes |
HARD(exit 1) | WARN(exit 0,能修就修) |
文件 .lattice/config.yaml:
1 | |
4. 可移植 Agent Skills,跨 agent
不是只绑 Claude Code。技能以 Agent Skills 标准打包,一条命令装到机器全局,Claude Code、Codex、Cursor 都能用同一套:
1 | |
六个生命周期技能之外,还有三类「非闭环」伴生技能(都不产生血缘节点):
| 类别 | 技能 | 说明 |
|---|---|---|
| PR 范围质量旁路 | review-code · review-production |
可选,/create-pr 前后跑 |
| 独立文档工具 | generate-wiki |
生成 wiki/ + llms.txt,随时跑 |
| 带外伴生 | create-adr |
写 docs/adr/NNN,与 /create-spec 同 pass 调用,非血缘节点 |
5. Claude Code 插件 + 可选 hooks(给裸 gh pr 上保险)
Claude Code 用户可以装成插件,技能之外多一层可选 advisory hooks:agent 跑裸 gh pr create / gh pr merge 时给提醒,把交付动作收回到 /create-pr / /finish-work 这条受控路径上。
1 | |
6. 自举 dogfood:Lattice 自己用 Lattice 发版
我们内部已经用了很长一段时间,也修了不少问题,目前刚发的公开 v0.1.0 版本就是靠 Lattice 流程跑出来的一个示例 ——spc-4(GH Actions v7 升级 + Dependabot 分组 + ADR-001 策略)拆成 tkt-5/6/7/8,最后 /finish-work pr 9 合并入库。血缘链也是真实跑出来的,issue 和 PR 上一眼能看到 spc / tkt / pr 的对应关系。
安装和使用
每台机器装一次,然后在任意仓库里 /start-work 开张。
1 | |
环境要求:git、gh、jq、python3(≥3.8)、curl,再加一个能跑 Agent Skills 或 Claude Code 插件的 agent。Hook 测试需要 bats。
日常三十秒路径:
1 | |
欢迎各位试用并反馈问题,留言或者 issue 直接开到仓库就行。