Commit Graph

2 Commits

Author SHA1 Message Date
iomgaa 6abe13abb1 feat(serialization): 落成记录的编解码与 schema 版本校验
一个 encode 对七个 decode_*。编码不需要知道目标类型(对象自己知道),解码需要
(一个字典什么都不知道),不对称是这个原因。

载荷就是记录类的字段,没有任何元信息键——没有类型标签、没有时间戳。哪一行是哪种记录由
存储实现自己解决,库不替它定文件布局;多塞一个键会让步记录的载荷不再和迁移前那份逐行
轨迹同形,而那边的验收标准是逐字段可比。

解码三条:带版本的三种记录(运行开始、步记录、运行结果)版本必须在场且认得,缺了或者
认不得都失败;记录类上的每个字段都必须在载荷里,有默认值的也一样(默认值补齐会把
「这件事没发生过」改写成「发生了但值为空」);多余键忽略(存储常要在同一个字典里塞
自己的东西,把它整个递回来解码是最自然的写法)。

第二条的直接后果写进了模块 docstring:往持久化结构里加字段必须同时抬 schema 版本。
CLAUDE.md §1.3 那条「新增字段必带默认值」管的是 Python 构造器,持久化这一侧由 §1.4 管。

SchemaVersionError 与 DecodeError 分开:一个说去升级库,一个说去查数据。压成一个的话,
一次例行升级漏做会被读成数据损坏,然后有人去修数据。
2026-08-10 00:52:01 -04:00
iomgaa e017160c45 build(repo): 落成工具链、依赖契约与十个模块的空骨架
第 ③ 阶段剩下的那半:架构文档之外,import-linter 契约也落地了。

pyproject.toml 把九条依赖规则里的七条写成五条 import-linter 契约。
分层用一条 layers 契约表达规则 1、2、3、8,`|` 表示同层互不 import;
另外四条 forbidden 分别管下游反向 import、polygateway 的唯一入口、
以及三个纯逻辑模块不碰 asyncio 与 pathlib。
契约不是平凡的绿:故意注入两处违规验证过,都被点名到行号。

先建十个模块的空包,是为了避开 PolyGateway bootstrap 期那段 Makefile 门控——
它当时没有包,lint-imports 报 module not found 而红,只好加一段跳过逻辑。
空包让契约从第一天就真的在跑。

剩下两条规则落不进契约,写成了 tests/unit 下的测试:
规则 6「types 与 ports 不许 import 任何第三方」判据要反过来写(只许标准库和自己),
规则 9「import polyloop 之后 sys.modules 里没有 polygateway」是运行时事实。
另加硬约束 §1.1 零业务假设的黑名单扫描——它第一次跑就抓到 _assembly 的 docstring
里写了 dissect 的业务词,已改。三个扫描类测试都带 fail-closed 守卫,
防止目录搬走之后扫到空列表安静地绿。

工程约定取自实验室已有项目:setuptools + src layout、ruff 十一项 select、
line-length 100 来自 PolyGateway;dev 工具链版本钉死、--strict-markers 与
--import-mode=importlib 来自 CHSAnalyzer 与 dissect 踩过的坑,各自的理由写在配置注释里。
e2e 默认不跑,它打真实网关要花钱。

CLAUDE.md §0 那句「契约还没写,要等 src/ 落地」已过期,改掉;
README 勾掉第 ②③ 阶段,补上本地检查命令与 GovDoc-Editor 那一行。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 21:28:59 -04:00