跳转到内容

flow 是什么

flow 是一个带 gate 的构建 harness。它带着产品从想法走到真实的完成证据——已部署的 URL、装得上跑得起来的 CLI、可导入的库 API,或达到自定完成定义的 skill——沿途每个 gate 都必须被诚实满足才能前进。

它是装进 coding agent 的 skill,不是让你注册的服务,也不是你的代码要依赖的框架。flow 掌管 gate 与证据,从不碰 runtime。 它独立存在:不需要 AgentKit 也不需要 claudekit,虽然装了这些引擎可以解锁可选的多模型评审。

coding agent 很乐意产出一份像样的计划、一份像样的调研文档、一句像样的“做完了”。每份产物单看都挺好。失败是系统性的,不是局部的:整个循环里没有一个环节负责说不。

两类具体失败模式造成了大部分损失。

看起来像进展的文书工作。 一份引用了编造竞品言论的调研文档,能通过任何结构检查。一份把 C 级功能写成 B 级的 scope 文档,也能通过。单看都没毛病,一碰现实全碎。

“完成”其实没完成。 agent 报 card 完成,因为测试绿了、分支合了。没人打开过页面,没人跑过命令。“Tests pass” 是个中途状态,被悄悄提拔成了终点。

三个承诺,其余都是推论。

完成意味着世间的证据。 每张 card 开头就写好证据,长什么样 gate 就要看到什么贴进来,贴不进来 card 就标不了完成。web 项目要上线 URL 加真实 curl 输出;CLI 要一次真实调用加 exit code。合了代码、CI 绿了,明确不算。见完成意味着世间的证据。

两层都得点头。 确定性脚本抓住可作弊的机械项——没打勾的框、残留的 [FILL] 占位符、空证据——exit 0 或 1。读 skill 的模型抓住脚本抓不住的:编造的调研、注水的 scope、没 auth 列的接口。只有两层都同意,gate 才算过。见双层 harness。

在 gate 毙掉是有效产出。 只会说“通过”的 harness 是传送带。在 Scope 毙掉一个弱想法又便宜又明智,flow 把它当一等结果,而不是需要绕开的失败。

它不是项目管理工具:没有看板,没有燃尽图,没有估算。它不是代码生成器——它给写代码的 agent 或人设 gate。它不是 CI 系统,虽然它的证据规则比大多数 CI gate 更严。它也不是让 agent 变聪明的包装;它让 agent 可问责,这是另一件、更有用的事。

Idea -> Research -> Scope -> PRD -> ADR -> Contract -> Cards -> Build -> Review -> Deploy -> Verify-live -> Retro
|------------------ 规划(flow/ 下的文件) ------------------| |------- 交付(cards/ 里) -------|

规划是六个带 gate 的 stage,落在 flow/ 下的文件里。交付是一串 card,在 cards/ 下,每张 card 是对着 stage 05 的 contract 做的一次构建会话。session 之间,持久存储留着 debt、retro、trace、playbook,下一个 session 开局就能看到上一个的痛。

对话是默认入口——说出你要什么,concierge 给一个下一步动作。手打的 /flow next 这类动词永远优先于对话路由。

这是 flow 的核心想法,其余都是推论。

一个 gate 要抓住两种完全不同的失败,没有单个组件两样都擅长。所以 flow 跑两层,只有两层都同意,gate 才算过。两层都点头,才算过。

runner/flow.sh 是 bash 引擎,确定性,exit 0 或 1。它掌管 stage 和 card 的生命周期,检查那些好作弊又好发现的东西:

  • 没打勾的 gate 框,包括 ## Open decisions 下残留的 - [ ]——同一个扫描器一起管
  • 残留的 [FILL] 占位符
  • card 状态合法性
  • 号称完成的 card 上空的 ## Evidence 节

它的 exit code 就是 ground truth。给模型的规则很 blunt:永远先跑脚本,读 exit code,原样转达。永远别拿自己的判断代替它。

这一层做不到的是读懂意思。它分不清真实的竞品引用和编的,也分不清老实的 B 级功能和注水成 B 的 C 级。

那是模型的工作。脚本通过之后,skill 按 stage 施加一组挑战,操作者才能往前走。编造的调研在这里被质问,注水的 scope 在这里被点名,没 auth 列的接口在这里被标出,贴进证据区的 “tests pass” 在这里被当作中途状态打回。

指令是对称的,两个方向都重要:别悄悄放过空洞的产物,也别悄悄拦下扎实的产物。脚本过了但内容虚,就原话告诉操作者——机械过了,质量虚——让操作者定夺。

为什么拆两层,而不是一个更聪明的检查器

Section titled “为什么拆两层,而不是一个更聪明的检查器”

脚本不懂语义;模型在机械项上不可信。拆开,各管各抓得住的那类失败,可作弊的那一半变成可执行的,而不是可说服的。你说服不了 exit 1 改变主意。你也写不出正则来识别编造的市场引用。

还有第二个更微妙的好处。机械层是独立进程,带着真实 exit code,模型自己关于 gate 的说法就变得可审计。agent 说“gate 过了”,可以用一个它没产出的信号去核验。

两层之下是持久层——Python 加 SQLite,存着 intake 和风险 lane、story 和证据、trace 和 tier、decision、backlog。它优雅降级:没有 python3,gate 照跑,只是这一层关掉。

+---------------------------------------------------------------+
| 语义层 - SKILL.md + references/(模型) |
| 判断:空洞内容、注水、敌对评审、agent 编排、工作模式、auto tier |
+---------------------------------------------------------------+
| 调用(exit code 即 ground truth)
v
+---------------------------------------------------------------+
| 机械层 - runner/flow.sh(bash,exit 0/1) |
| stage/card 生命周期、gate 检查、debt 台账、 |
| design 检查、harness 透传 |
+---------------------------------------------------------------+
| 读写(尽力而为,优雅降级)
v
+---------------------------------------------------------------+
| 持久层 - Python + sqlite3(flow 自有) |
| intake/风险 lane、story+证据、trace+tier、decision、backlog |
+---------------------------------------------------------------+

它是外部记忆。进展和摩擦在 session 和上下文窗口之外活下来,这是对抗长项目只活在对话里慢慢腐烂的解药。

agent 可插拔,gate 是固定的。装了 specialist agent 的 stage 可以把起草交给它,没装就回退到内置行为。gate 在每条路上都一样,所以缺 agent 永远降不了 bar,fancy 的 agent 也永远抬不了它没挣到的通过。agent 起草,gate 照样审判。

可选的跨厂商引擎也一样。一个或两个模型可以评审 card,但 verdict 只影响分诊——永远不自动通过,也永远不自动打回。

每张 card 开头就写好完成证据,gate 要看到证据贴进来,card 才能标完成。“Tests pass” 和 “code merged” 是中途状态,永远不算完成。

agent 辅助构建最常见的翻车不是 bug,是状态。card 被报完成,因为测试绿了、评审过了、分支合了。每句话都对。没人打开过页面。

每个信号量的都是你真正关心的东西的代理。测试量的是你的模型对系统自身的建模。合并量的是对 diff 的共识。哪个都没碰过真实运行的世界。代理会悄悄偏离现实,偏偏在最要命的时候看不见,因为所有仪表盘都是绿的。

解法不是更多代理,是要求一次对真实东西的观察。

项目类型决定证据长什么样,精神每种都一样:有人跟部署好的现实交互过,并把返回贴了回来。

项目类型 完成证据
web 上线的部署 URL 加真实 curl 输出
cli 工具装得上,一次真实调用返回预期输出和 exit code
library 公开 API 导得进来,示例跑得起来,覆盖率达标
skill 装进 skill 家目录,一次真实运行达到自定完成定义

用 /flow project-type <type> 设类型,默认 web。contract 接缝和类型矩阵的其余部分在项目类型。

再漂亮的流程产物也不算:

  • 合并了的 pull request
  • 绿了的 CI 徽章或 workflow
  • 描述发了什么的 release notes
  • 没发现问题的代码评审
  • agent 自己写的“做完了”小结

机械层在这里设了地板:证据区只写流程散文的 card 会被打回,纪律在当场吵不掉。地板之上,语义 gate 问更难的问题——这是世界本身,还是对世界的描述?

agent 的自我评估被明确排除。每个 gate 的 ground-truth 信号都是 agent 没产出的东西:脚本的 exit code、真实 verify 命令的输出、一次上线检查。

为什么 gate 对空证据区下手这么狠

Section titled “为什么 gate 对空证据区下手这么狠”
[x] status is 'done' but ## Evidence is empty (paste world-state proof: URL/curl/DB row)
FAIL: C-001 has gate violations (above).

代码写完写对了也照样触发。因为抓证据最便宜的时机,就是你正盯着运行的东西看的那一刻。拖后补,靠记忆重建,重建的证据和编的证据分不出来。

同一个道理驱动了 CLI 接管的翻转 /flow card done C-NNN:它走和 check 一样的规则,gate 不过就回滚,所以没有任何一条代码路径能产出空洞的完成。

如果 card 眼下真证明不了——部署目标还不存在,外部服务挂了——答案不是放宽证据,是把风险记成 debt,白纸黑字,写清关闭条件。debt 看得见,会在 recall 里冒出来;空洞的完成看不见,会在生产环境冒出来。

怎么开这条 debt,什么时候 skip 会被拒绝,在用 debt 跳过 gate。怎么把证据贴上 card,在创建与检查 card。

机械通过只说明文件结构完整,不说明内容是真的。语义挑战是脚本通过之后模型按 stage 施加的一组问题,每个 stage 特意不同,因为每个 stage 招的谎不一样。

Research 招编造的竞品和没来源的数字。Scope 招注水,把想做的功能写高一级。PRD 招没主人的需求和没功能治的痛。contract 招没 auth 列的接口。card 招描述流程而非世界的证据。通用的“这好不好?“抓不住这些,按 stage 点名的挑战抓得住。

指令双向:永远别悄悄放过空洞的产物,也永远别悄悄拦下扎实的产物。机械过了但读着虚,就原话告诉操作者,让他定夺。还有个行为证据说明这一层真管用——/flow eval 把空洞但机械干净的 fixture 喂给 fresh judge,打分看拦不拦得住,这是下限,不是保证。

Idea (00)。 pitch 真的是三句话吗(谁 / 痛 / 做什么)?点名的人是真实具体的人或群体,不是 “users”?痛是具体的,不是类别?forge-idea 仪式是可选的,永远不变成 gate 检查的条件。

Research (01)。 编造风险最高。三个竞品真打开过吗?web / 市场产品:抱怨是带可用来源链接的真实引用吗,首批十个用户的渠道是具体地方吗?cli / library / skill / 内部工具:一手摩擦具体可观察吗,受益人点名了吗——“没有市场渠道”在这里是预期,不是毙掉的理由。成本必须是真实的,不是猜的。

Scope (02)。 盯注水。C 就是 C(实时、从零做支付、自研 auth、自主 agent 流水线、重并发)。如果实质产品选择还开着(quota、身份 key、租户、响应契约、执行owner),停下,列出来——可配置的默认值不是权威。## Assumptions 下把产品法则写成 bullet 却没有操作者或 ADR 背书的,是 open decision 或停下,不是悄悄默认。

PRD (03)。 成功指标是真数字,不是 “better UX”?每个痛都引用了证据、点名了治它的 v1 功能吗,每个 v1 功能至少治一个痛吗?两边落单的都是 scope drift。陌生人拿着这份 PRD 能不问操作者一句就做出 v1 吗?

ADR (04)。 每个决策都点名了真实被否的备选,不是稻草人吗?存储、auth、部署真定了吗,不是 “TBD”?NOT-doing 清单对推迟的东西老实吗?

Contract (05)。 接口是项目类型的接缝:web 是 endpoint,cli 是命令 + flag + 输出/exit,library 是公开函数 + 参数 + 返回,skill 是命令/文件。每个 PRD 功能至少映射到一个接口,反过来也一样。每个接口输入输出 shape 都有,名字不会漂。access/effects 列每个接口都是实的——web 产品别空着它。先对照 contract 点名的 source of truth 读一遍再放行;这里的矛盾放过去就是 “passed”,每张 card 都继承它。

Card(/flow check C-NNN)。 scope 是一件事吗?## Independent test 是用户可见的证据,不是 “unit tests pass” 吗?diff 没出 ## Allowed files 吗?shape 跟 flow/05-contract.md 严丝合缝吗?## Evidence 是世间的——可点的 URL、真实 curl 输出、DB 行——每项都点名了产出它的产物或命令吗?

Consistency(/flow consistency)。 建议性质,永远不拦构建路。runner 跑完基于 ID 的检查,模型还得抓空洞覆盖(贴在没交付它的 card 上的 FRn)、产物之间矛盾的需求、cut-list 功能借尸还魂 v1、术语漂移(ticket / issue / request)。

模型的完整挑战文本在页脚链接的维护者文件里。security-class skip 和 auto HALT 不在这页,在工作何时必须停下。

flow 是三个协作层加磁盘产物:管可作弊机械项的快而确定的引擎、管判断的 skill、管记录跨 session 的持久存储。操作者看到的公开画面是四块——skill、runner、产物、两个版本通道。

语义层是 SKILL.md 加 skills/flow/references/ 下的 playbook。宿主 agent 读它:分发、守门、编排。runner/flow.sh 返回 0 之后,这一层跑上面的按 stage 挑战。它永远不拿感觉通过代替脚本的 exit code。

机械层是 runner/flow.sh。bash,确定性,exit 0 或 1。它掌管 stage 和 card 生命周期、gate 检查([FILL]、框、空证据)、debt 台账、design 检查、harness 透传。它的 exit code 就是 ground truth。永远先跑它,永远原样转达。

底下,flow 自有的 Python 加 SQLite CLI 存着 intake 和风险 lane、story 和证据、trace 和 tier、decision、backlog。没有 python3,gate 照跑,只是持久层关掉。

产物在被构建的项目里,不在 skill 家目录里:

flow/00-idea.md .. 05-contract.md 规划,带 gate
cards/C-NNN.md 交付单元
MODE, RETRO.md, DEBT.md, AUTO-LOG.md, DESIGN.md
.flow/harness.db 持久记录

flow/ 下的规划文件是带 gate 的 stage。cards/ 下每张 card 是对着 stage-05 contract 的一次 scoped 构建会话。台账文件和 .flow/harness.db 让 debt、retro、trace 活过下一个上下文窗口。

分发是两条平行通道喂同一棵标准树。npm installer(npx @manhquy/flow-skill@latest)是主路:纯 Node,不用 shell。仓库安装脚本是开发和 CI 用的参考实现。两条都写同一个 skill 家目录,项目换通道不用重过 gate。

monorepo skills/flow/ --npm run sync--> npm-wrapper/skills/flow --npm pack--> registry
| |
| install.sh / agent skill homes | npx @manhquy/flow-skill@latest
v v
~/.claude/skills/flow same tree via installer CLI

两个通道版本化的东西不一样。skill 产品版本化 gate、SKILL.md、runner、reference、模板——审判你构建的那个东西。npm 包只版本化 installer CLI:agent 检测、复制路径、flag。它们本来就不该一样。--help 打印两个数字。信你机器上的,别信文档里的。配对故事,包括 pin 哪个数字,在两个版本号。


维护者文件(不在公开页):docs/adr/0001-discipline-layer-identity.md、skills/flow/references/gate-rules.md、docs/system-architecture.md。