2026-09-23·by Sijie Wang#software

facade-parity

门面对等

上级:structure · 邻居:facade-directions · owner-facade-from-registry · ui-mcp-parity

一份注册表;每一个门面要么由它生成、要么对着它校验。 绝不允许同一个能力有第二份手写的描述。

它回答的问题

同一个底层能力,产品要从好几个面暴露出去:admin UI 的 HTTP 路由、owner 的 MCP 工具、API-key 面、访客 agent 的工具集。各写各的就会漂移 —— 而这里的漂移不是外观差异。一个 op 在 admin 面板上有、在 MCP 上没有,意味着 owner 点鼠标能做的事、没法让他的 AI 去做,而那正是这个产品的前提在无声地失效。

这个缺口是量出来的,不是估的:对等机制第一次跑,找出 56 个 op 只在一个面上有、另一个面上没有。事先的估计是十五个左右。这个比例本身就是论证 —— 一处读代码看不出来的不一致,比写这些代码的人猜的多了将近四倍。

机制

一个域把每个 op 声明成数据,只声明一次:

fp.Op{ ID, Description, InputSchema, Kind, Reach, Invoke }
  • Kind —— Read / Query / Action,各个门面按自己的语汇渲染它(HTTP 的 GET / QUERY / POST)。
  • Reach —— 暴露意图,而且是对着门面的声明的,从不对着门面的名字:OwnerRead()OwnerAction()OutwardRead()OutwardAction(),或者 Only(理由, …) 用于真正只该出现在少数面上的 op —— 理由是必填的,于是一个缺口是一次被明确评审过的决定,而不是一次无声的遗漏。

正因为 reach 是对着类声明的,后加的门面会自动绑上。没有人需要再把 op 清单走一遍。

dispatcher 把所有声明汇成那唯一一份注册表(convergence-inbound-and-outbound);paritymanifest 记录每一类门面可以承载什么;一条棘轮兜着还没迁完的文件,只许变少。

为什么"声明一次"胜过"事后审计"

把对等当成一次审计,就是一件得有人记得去跑、而且必须跑全的任务。把对等当成一次投影,它就是一条你违背不了的性质:描述没有第二个地方可写,于是没有第二份描述可以跟它不一致。

剩下的风险不是漂移,是覆盖:一个从没被声明过的 op,对这套机制是隐形的。corpus_graph 就是这么溜掉的 —— 一条既没有 MCP 孪生、也没被登记进那张手写对照表的路由,棘轮从来看不见它。一份注册表只保证它里面那些东西彼此一致。

它不做什么

它不决定一个 op 应不应该出现在某个面上 —— Reach 是人的判断,而 Only(理由, …) 的存在正是为了让那个判断写在 op 旁边,而不是从它的缺席里去反推。对等保证的是:这个答案只说一次,而且处处照办。

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →