docs(design): 落成 0006 与 0007,公共 API 的名字、签名与接缝行为
0006 定「叫什么、什么形状」:五个接缝的 Protocol 名与签名、公共类型的英文名与 字段清单、类型分到 types / ports / tools 三个模块的判据。 0007 定「同一个签名下什么算对」:三个动作状态的触发条件、动作被拒绝时观察由库 合成而不取执行器那段、解释器不许抛异常、read_log 读不存在的运行返回空日志。 两份拆开是因为后者的权威处按 §0 是 tests/contract/,design doc 只记当初为什么这么定。 这两份改动了 0003 四处,全部在文首登记:记录集合是六种东西不是五类; 参数视图是方法不是字段;预算是四项不是两个计数;ports 装「Protocol 与它们的 入参/返回结构体」那半句写不出来——照它写 types 会反向依赖 ports。 四处全是「把字段类型逐个写出来」这个动作本身逼出来的,纯读文档看不见。 四轮评审:两轮硕士生冷读报了约 45 条,两轮 Codex 对抗审查报了 13 条, 逐条核实后基本全部成立并修完。最后一轮是唯一一次契约测试与文档互相抓到对方的错—— 文档改了方法名测试没跟,测试把 dissect 的动作语言写死成输入会误杀 GovDoc 的实现。 结论回写 architecture.md:第七节补类型归属判据,第八节改 ports 那一行, 第九节补五个 Protocol 的英文名,第十四节把「英文名还没定」那条缺口换成指向; 决策索引加两行。字段表刻意不回写——按 §0 那是代码的权威。 CLAUDE.md 与 README.md 开头的「一次 Agent Session」是术语漂移,改成「一次运行」。 CLAUDE.md §7 加两条工作方式:能压成一段结论的活尽量交给 subagent、 委托出去的活交证据不交判断;以及持续往下做,只在人类门和真判断不了的岔路停。 §8 那句「讲完停下来等回应」与后者打架,收窄到只管说话方式。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -238,6 +238,11 @@ PolyLoop 把这个循环收成一份。它治理的单位是**一次运行**:
|
||||
|
||||
### 分层
|
||||
|
||||
**类型分到 `types` 还是 `ports`,判据是「它是不是一个值」**:值类型与持久化记录住 `types`,
|
||||
只为一次调用打包入参或返回的壳住 `ports`。判据不能写成「会不会被写进日志」——消息不出现在
|
||||
任何一条日志记录里,照那条会判进 `ports`,而上下文住 `types` 且字段就是消息序列,于是
|
||||
`types` 反向依赖 `ports`。理由见 `../design/0006-public-names-and-signatures.md` 决策四。
|
||||
|
||||
**这张图讲的是谁 import 谁,不是运行顺序,也不是数据流向。**
|
||||
`A ──▶ B` 读作「A 的代码里写了 `from polyloop.B import ...`」,也就是 A 依赖 B。
|
||||
|
||||
@@ -334,8 +339,8 @@ provider 目录一起拉起来。
|
||||
|
||||
| 位置 | 公开 | 装什么 |
|
||||
|---|---|---|
|
||||
| `polyloop/types/` | 是 | 公共值类型、枚举、持久化记录 |
|
||||
| `polyloop/ports/` | 是 | 全部 Protocol 与它们的入参/返回结构体 |
|
||||
| `polyloop/types/` | 是 | 公共值类型、枚举、持久化记录。**凡是被这里引用的都必须也在这里** |
|
||||
| `polyloop/ports/` | 是 | 五个 Protocol,以及只在一次调用往返之间存在的入参 / 返回壳 |
|
||||
| `polyloop/tools/` | 是 | 工具规格与注册表,以及由注册表派生的动作执行器 |
|
||||
| `polyloop/serialization/` | 是 | 记录的编解码与 schema major 校验 |
|
||||
| `polyloop/session/` | 是 | 定义、请求、`run`、`resume` |
|
||||
@@ -374,7 +379,7 @@ GovDoc 的编排层读停止原因决定这个阶段算不算可挽救,写任
|
||||
|
||||
### 五个接缝
|
||||
|
||||
**模型调用**(挂定义)。把已装配好的消息序列送出去,拿回可见回复与推理段。签名里不出现
|
||||
**模型调用** `ModelClient`(挂定义)。把已装配好的消息序列送出去,拿回可见回复与推理段。签名里不出现
|
||||
重试次数、退避时长、限流配额——出现即意味着库在治理一次模型调用,而那归 PolyGateway。
|
||||
两个形态:一种要在调用点按多本账各记一条并自己按价格表算成本,一种要在调用外面套退避并
|
||||
累加本次运行的用量。
|
||||
@@ -382,11 +387,11 @@ GovDoc 的编排层读停止原因决定这个阶段算不算可挽救,写任
|
||||
返回类型是库自己的,不是 re-export PolyGateway 的响应类型。理由是接缝定义模块不许有第三方
|
||||
依赖(第七节规则五),而且 PolyGateway 加一个字段就等于本库的公共类型变了一次却没发过版。
|
||||
|
||||
**决策解释**(挂定义)。把一次模型回复解释成三分支之一:动作、最终回答、无效决策。
|
||||
**决策解释** `DecisionParser`(挂定义)。把一次模型回复解释成三分支之一:动作、最终回答、无效决策。
|
||||
库不带默认实现——带了就等于替某一家定了动作语言。两个形态:一种从代码围栏里抽 Python
|
||||
源码,一种从 JSON 里抽工具名与参数。
|
||||
|
||||
**动作执行**(挂请求)。结算一个动作,返回状态(已执行 / 未执行 / 环境故障)、观察、
|
||||
**动作执行** `ActionExecutor`(挂请求)。结算一个动作,返回状态(已执行 / 未执行 / 环境故障)、观察、
|
||||
观察是不是库合成的、完成信号、被截断的字符数。两个形态:一种把一段代码交给已开好的容器
|
||||
会话、状态恒为已执行,一种查工具注册表分发、工具不存在或参数不合法时返回未执行。
|
||||
|
||||
@@ -410,7 +415,7 @@ GovDoc 的编排层读停止原因决定这个阶段算不算可挽救,写任
|
||||
字符数」单独记。存原文的话,恢复时得拿原文重跑一遍截断逻辑才能得到历史,而截断逻辑会随
|
||||
版本变——那正是记录逐步结果要消掉的那类重算。
|
||||
|
||||
**存储**(挂定义)。六个方法:写运行开始、写一条意图、写模型调用结果、写动作结果与步记录、
|
||||
**存储** `RunStore`(挂定义)。六个方法:写运行开始、写一条意图、写模型调用结果、写动作结果与步记录、
|
||||
读回整份日志、写运行结束。全部带运行标识,端口不持有「当前运行」的隐式状态——一个有隐式
|
||||
当前运行的端口在并发下会把 A 的意图写进 B 的日志。两个形态:一种逐行写本地 jsonl 文件,
|
||||
一种写关系数据库。
|
||||
@@ -428,7 +433,7 @@ GovDoc 的编排层读停止原因决定这个阶段算不算可挽救,写任
|
||||
上顺序提交的事务,先提交的先持久。代价是排除了「不同记录类型写进彼此无序的多个后端」这种
|
||||
形态,现在没有消费者要它。
|
||||
|
||||
**事件出口**(挂定义)。投递失败由库捕获、记日志、把失败计数加一,然后继续跑。失败不再
|
||||
**事件出口** `EventSink`(挂定义)。投递失败由库捕获、记日志、把失败计数加一,然后继续跑。失败不再
|
||||
转成一条事件从同一个出口发出去——那会自我喂食,一个持续失败的出口会让失败处理路径变成
|
||||
递归。两个形态:一种把进度回写业务数据库,一种把审计事件送进日志管道。
|
||||
|
||||
@@ -449,12 +454,14 @@ GovDoc 的编排层读停止原因决定这个阶段算不算可挽救,写任
|
||||
本库不部署,也不跑模型推理,没有常驻进程。它被 `pip install` 进下游项目,在下游的进程里
|
||||
被装配和调用。
|
||||
|
||||
装配分两步。**定义**在进程或 worker 启动时装配一次,持有跨运行不变的能力:模型调用接缝、
|
||||
决策解释接缝、存储接缝、事件出口。它是不可变的,可以被并发复用。
|
||||
装配分两步。**定义**在进程或 worker 启动时装配一次,持有跨运行不变的五样东西:模型调用
|
||||
接缝、决策解释接缝、存储接缝、事件出口,以及库在动作被拒绝或环境故障时合成的那几段观察
|
||||
文本。它是不可变的,可以被并发复用。它还有一个只读方法,把四个接缝各自上报的参数聚合成
|
||||
一份快照——那是方法不是字段,因为聚合要向接缝逐个发问,而构造定义之前定义还不存在。
|
||||
|
||||
**请求**每次运行构造一个,持有这次运行独有的数据:运行标识、预算、动作执行器、本次可见的
|
||||
工具集、上下文各段、注入内容、模型绑定、模型调用的重放策略、取消收尾时限。它构造廉价——
|
||||
无 I/O、无网络校验、无哈希计算。
|
||||
**请求**每次运行构造一个,持有这次运行独有的十一样数据:运行标识、预算、动作执行器、本次
|
||||
可见的工具集、上下文各段、注入内容、模型绑定、模型调用的重放策略、观察包装模板、工具段
|
||||
渲染样式、取消收尾时限。它构造廉价——无 I/O、无网络校验、无哈希计算。
|
||||
|
||||
切点是「跨运行变不变」。预算只在请求这一处,不设「定义给默认值、请求可覆盖」——两处取值
|
||||
意味着「这次到底跑的什么设置」要对照两个地方才答得出来。
|
||||
@@ -521,9 +528,10 @@ dissect 的每一次运行都是论文数据点,这个性质对结构提了几
|
||||
|
||||
## 十四、已知缺口与尚未决定的部分
|
||||
|
||||
**公共类型的英文名与接缝的具体签名还没定。** 按 `../../CLAUDE.md` §2 它们要过人类门。
|
||||
本文件通篇用中文概念名指代它们,这是刻意的留白不是遗漏。它们和实现一起落地,落地时本文件
|
||||
第八、九、十一节要补上英文名。
|
||||
**公共类型的字段与枚举取值不在本文件里。** 英文名与签名定在
|
||||
`../design/0006-public-names-and-signatures.md`,行为契约定在 `../design/0007-seam-behaviour.md`;
|
||||
落地之后权威转移到 `src/polyloop/` 的代码与 `tests/contract/`。本文件只给五个接缝的
|
||||
Protocol 名与模块归属,不复述字段表——按 `../../CLAUDE.md` §0,那种复述腐烂的速度和代码一样快。
|
||||
|
||||
**停止判定的顺序、停止原因的取值、两个预算计数的语义、步记录的字段清单不在本文件里。**
|
||||
这四样已经定了,在 `../design/0004-stopping-and-step-record.md`,字段表经
|
||||
@@ -552,6 +560,8 @@ dissect 的每一次运行都是论文数据点,这个性质对结构提了几
|
||||
| 公共 API 分几层、五个接缝为什么是这五个、依赖规则为什么这么定 | `../design/0003-public-api-shape.md` |
|
||||
| 停止原因为什么是这十个、判定为什么按这个顺序、步记录为什么是这些字段 | `../design/0004-stopping-and-step-record.md` |
|
||||
| 存储的方法为什么这么切、为什么要前缀持久性、步记录那三处为什么改 | `../design/0005-storage-atomicity-and-record-fields.md` |
|
||||
| 公共类型与接缝叫什么、字段是什么形状、类型分到哪个模块 | `../design/0006-public-names-and-signatures.md` |
|
||||
| 三个动作状态什么时候赋上、动作被拒绝时观察从哪来、解释器能不能抛异常 | `../design/0007-seam-behaviour.md` |
|
||||
|
||||
边界的当前裁决清单(哪些在界内、哪些在界外)在 `scope.md`,那份是常青的,会随新消费者
|
||||
接入而更新。每个下游要迁什么、迁完算不算数在 `../migrations/` 下对应那份。
|
||||
|
||||
Reference in New Issue
Block a user