docs(scripts): 四条 metadata-protocol 基线条目的处方指向一个不存在的动作 (#4987) - #5624
Merged
Conversation
`scripts/engine-double-contract.baseline.json` 是 shrink-only 手写台账,一条条目的
`closes` 就是给下一个作者的处方。四条 metadata-protocol 条目写的是「add
@objectstack/objectql to devDependencies」—— 这个动作**做不到**:
`@objectstack/objectql` 的 `dependencies` 已含 `@objectstack/metadata-protocol`
(`workspace:*`),反向加边按构造即成环。
不是引用旧测量,而是在本分支重测:把边加进 metadata-protocol 的 devDependencies,
turbo 2.10.7 对 `build` 与 `test` 两个 task graph 都直接拒绝(exit 1),随后回退:
WARNING Circular package dependency detected:
@objectstack/objectql, @objectstack/metadata-protocol
x Cyclic dependency detected:
| @objectstack/objectql#build, @objectstack/metadata-protocol#build
判据本来就在同一个文件里 —— `packages/spec/src/contracts/data-engine.test.ts` 那条
EXEMPT 早就写了「it cannot be pinned even in principle ... the import would invert
the dependency」,只是从没套用到 metadata-protocol 这四条上。
- `why` 改成实测的环,并写明**不能**因此升级成 EXEMPT:不存在的是 devDependency
这条**路线**,条目本身靠下沉谓词仍可关闭,所以按台账自己的规则保持 DEBT。
- `closes` 改成唯一存在的路线:把 `assertEngineDeleteDispatch` 下沉到两边都已依赖
的包。已静态核实其可行:objectql 与 metadata-protocol 都已依赖
`@objectstack/metadata-core`,而后者 `dependencies` 只有 spec + zod、不含
objectql,故不引入新环;生产者 `packages/objectql/src/engine-delete-dispatch.ts`
**没有任何 import**,下沉是一次搬移而非重构。`spec/contracts` 作为另一候选保留,
但注明仅当谓词属于契约层才对,不要默认选它。
- 措辞与 #4867 / #4981 / #5206 三条早先已改好的同族条目对齐,但**不写硬编码的
sibling 计数** —— 那三条写的「four/five sibling」在同族增至 7 条后已经漂移,
本次改用免计数措辞,避免再漂。
未做也未声称做的事:本 PR 文件面只是台账文字,四个文件各自的 fake delete 当前是否被
驱动**没有探测**,`why` 里如实写明。按台账自己的规则这不改变结论 —— 那是关于单个
文件的论证,不是关于契约的论证。
下沉代码本身属 engine-core 域,不在本 PR 文件面,已另开 #5619 承接(三条同族条目
`closes` 里「tracked as #4987」的引用也在那里改指)。
验证:`pnpm check:engine-double-contract` 改动前后输出**逐字节一致** —— 仍是
24 pinned / 34 baseline、仅 1 个 problem(#5604 的 action-execution-calldata-not-found,
cli 座位在修,与本改动无关)。JSON round-trip 字节一致,故 diff 恰好 8 增 8 删;
条目数、`file`/`lines`/`unguarded`/`kind` 与 `$comment` 由脚本断言未变。
Fixes #4987
Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE
Co-authored-by: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
os-zhuang
marked this pull request as ready for review
August 5, 2026 21:00
This was referenced Aug 5, 2026
Closed
This was referenced Aug 5, 2026
Closed
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 6, 2026
…objectstack-ai#5579) (objectstack-ai#5642) 该段给出的唯一理由是「One raw control byte makes grep treat the whole file as binary: zero matches, no signal」——而这条只对 NUL 成立。在容器内独立复现(样本用 printf 生成,未粘贴裸字节;GNU grep 3.11 + ripgrep 14.1.0): U+0000 grep: binary file matches rg: binary file matches (found "\0" ...) U+0001 grep: 2:searchable line rg: 2:searchable line U+007F grep: 2:searchable line rg: 2:searchable line 即门禁扫描面里除 NUL 之外的每个字节(含 objectstack-ai#5460 纳入门禁、objectstack-ai#5577 补进自扫字符类的 DEL)都不会让文件被当成二进制。危害只写这一条的后果不是文字不精确:agent 写出一枚 非 NUL 控制字节、自扫命中后去核对指令,会发现唯一被陈述的判据不成立,从而把门禁的红 判成误报。 `scripts/check-nul-bytes.mjs` 脚本头早就把两侧分开论证好了(objectstack-ai#5157 段),本次把散文 口径搬过去对齐: - binary-file / zero-matches 那条点名 NUL,并标明是实测结论; - 其余扫描面字节引脚本头写清的三条:渲染为空(代码对每个读者说谎)、两种拼写互不 命中(文件里是字节,不是你会去搜的转义文本)、事故源不挑字节值; - 补一句直接堵住上述推理:「不是 NUL、grep 还能搜到」永远不构成把门禁红或自扫命中 读成误报的理由; - 危害论证指向脚本头「引用它,不要重新推导」,不在此处再抄一遍论证细节。 顺带修同段两处陈旧: - 「this repo has paid four times」的硬编码计数改为免计数措辞——该族已多于四例, objectstack-ai#5624 刚因同样的漂移把台账里的 sibling 计数改成不含数字的表达; - 「a `0x01` that `check:nul-bytes` does not scan for (objectstack-ai#5157)」的现在时已错:objectstack-ai#5157 正是把该字节纳入扫描面的那一单,改为过去时的事实句。 未做(留档而非顺手扩面):单源化——让字符类与危害论证不再手抄多处——是 objectstack-ai#5484 正文 留下的方向,本 PR 只修散文口径,不动 `scripts/check-nul-bytes.mjs`、不动 objectstack-ai#5577 刚 补的自扫字符类、不动 objectstack-ai#5630 刚加的 Toolchain traps 条目。 纪律:全程未向任何文件写入裸控制字节,散文沿用该文件与脚本头既有的 `0x01`/`0x7f` 十六进制写法(不含反斜杠转义,不会被编辑工具 materialise)。 `node scripts/check-nul-bytes.mjs` 绿;改动文件自扫 `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` 无命中;`cat -A` / `od -c` 复核新增 行无意外字节。 `.claude/` 文档-only,无用户可见变更,走 skip-changeset 标签路线。 Fixes objectstack-ai#5579 Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 6, 2026
…tstack-ai#5650) * docs(os-dev): PR 收尾清单增补 `skip-changeset` 硬步骤,以回读 PR labels 为闭环 (objectstack-ai#5559) 测试-only / 工作流-only / `.claude/`-only 的 PR 不写 changeset,靠 `skip-changeset` 标签豁免 Check Changeset。此前收尾清单对这一步只字未提,dev 在 PR 正文「声明」了 标签却没有真正挂上,objectstack-ai#5533/objectstack-ai#5538 两例各烧一轮门禁红并由 PM 手工兜底 —— 「声明了 ≠ 执行了」正是 declared ≠ enforced 的 agent 版。 新增条目把它写成与「PR 正文以 Fixes 开头」同级的硬步骤,并按实测校正了三处认知: - 没有任何自动化会替你挂:`.github/labeler.yml` 九条规则里没有 `skip-changeset`, 2026-08-05 六例(objectstack-ai#5533/objectstack-ai#5538/objectstack-ai#5542/objectstack-ai#5624/objectstack-ai#5642/objectstack-ai#5645)的该标签全部来自 agent, `github-actions[bot]` 一次都没挂过 —— 它只负责 `size/*`、`documentation`、 `tests`、`ci/cd`。 - 只「加一个标签」,不要整集写入:整集写入会把 bot 刚挂的 `size/*` / `documentation` / `tests` 抹掉(objectstack-ai#5533/objectstack-ai#5538/objectstack-ai#5642/objectstack-ai#5645 的 agent `unlabeled` 事件即此),反向也成立 —— objectstack-ai#5533 的标签 15:46:44 落、15:46:45 就被 `github-actions[bot]` 的写入抹掉,只活了一秒。 - 闭环是回读而不是 POST:Check Changeset 在 PR 打开后数秒就实时读一次标签 (objectstack-ai#5580),`opened` run 通常早于标签落地 —— objectstack-ai#5542 的 dev 做对了全套,仍留下 一条红 `opened` run,之后每一次 run 才被标签豁免。所以要在 bot 平息后回读 标签、并把读到的列表写进报告。 * docs(os-dev): 首 run 颜色按实测改成双向竞态,不再预设为红 (objectstack-ai#5559) 本 PR(objectstack-ai#5650)自己按新硬步骤执行时,实测结果与原措辞相反:标签 22:03:54 落地, `opened` run(workflow run 31051251795,创建于 22:03:38)的 Check Changeset job 直到 22:04:35 才启动并做实时标签回读 —— 早于回读 41 秒落地的标签被读到,该 run 直接 **success**,并非预设的红。 于是这一句改为如实描述竞态:首 run 的颜色取决于 runner 启动耗时与 POST 落地 的先后,两个方向都有实例(objectstack-ai#5542 红、objectstack-ai#5650 绿)。指导语随之从「预期会红」改为 「尽快落标签,把首 run 的颜色当信息而不是自己的判决」。 预设方向被自己的实测证伪时如实记录,而不是让措辞压着实测走。 --------- Co-authored-by: os-zhuang <hr@objectstack.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4987
scripts/engine-double-contract.baseline.json是 shrink-only 手写台账,一条条目的closes就是给下一个作者的处方。四条 metadata-protocol 条目写的是「add @objectstack/objectql to devDependencies」——这个动作做不到:@objectstack/objectql的dependencies已含@objectstack/metadata-protocol(workspace:*),反向加边按构造即成环。按现在这句去做的人会加 devDependency、跑 turbo、撞环、回退,然后才发现处方本身是错的 —— 而台账存在的意义正是让他不必重新发现这件事。不是引用旧测量,而是在本分支重测
把边加进 metadata-protocol 的 devDependencies,turbo 2.10.7 对
build与test两个 task graph 都直接拒绝(exit 1),随后回退(工作树已确认干净,package.json 不在本 PR diff 内):判据本来就在同一个文件里:
packages/spec/src/contracts/data-engine.test.ts那条 EXEMPT 早就写了「it cannot be pinned even in principle ... the import would invert the dependency」,只是从没套用到 metadata-protocol 这四条上。改了什么
只改这四条的
why/closes台账文字(protocol-publish-drafts-org-scope/protocol.runtime-authoring-gate/protocol.save-flow-canonicalization/sys-metadata-repository.recorded-by):why改成实测的环,并写明不能因此升级成 EXEMPT:不存在的是 devDependency 这条路线,条目本身靠下沉谓词仍可关闭,所以按台账自己的规则保持 DEBT。closes改成唯一存在的路线:把assertEngineDeleteDispatch下沉到两边都已依赖的包。可行性已静态核实并写进条目:objectql 与 metadata-protocol 都已依赖@objectstack/metadata-core,而后者dependencies只有 spec + zod、不含 objectql,故不引入新环;生产者packages/objectql/src/engine-delete-dispatch.ts没有任何 import(168 行自包含模块),所以下沉是一次搬移而非重构。@objectstack/spec/contracts作为另一候选保留,但注明仅当谓词属于契约层才对,不要默认选它。api不在 metadata 类型注册表里 —— Studio 直写路径完全不校验端点,publishPackageDrafts 也没有 E7 门 #5206 三条早先已改好的同族条目对齐,但不写硬编码的 sibling 计数:那三条写的「four/five sibling」在同族增至 7 条(各有 6 个 sibling)后已经漂移,本次改用免计数措辞(「every other metadata-protocol entry in this ledger」),避免再漂。未做也未声称做的事:本 PR 文件面只是台账文字,四个文件各自的 fake delete 当前是否被驱动没有探测,
why里如实写明。按台账自己的规则这不改变结论 —— 那是关于单个文件的论证,不是关于契约的论证(#5206 那条做了逐文件探测,本次没有,不冒充)。边界
⛔ 不实施下沉代码改动(engine-core 域,见 #4987 分诊的越界提示)、⛔ 不增删条目、⛔ 不改
file/unguarded/kind定位与判定字段、⛔ 不改检查脚本。下沉本身已另开 #5619(未指派)承接 —— 顺带记一笔:#4867 / #4981 / #5206 三条的
closes写的是「tracked as #4987」,而 #4987 的真实文件面只是措辞;#5619 的完成范围里包含把那三处引用改指过去(整批删除这 7 条时自然消失)。另:该文件不在
.gitattributes的 merge driver 列表里(那里显式注明 shrink-only ratchet 基线「deliberately absent」),是手写台账不是生成物,正常编辑。验证
pnpm check:engine-double-contract(self-test + 扫描)改动前后输出逐字节一致(diff无输出):判据即「无新增问题」:pinned/baseline 计数 24/34 不变,仅剩的 1 个 problem 是 #5604(
action-execution-calldata-not-found.test.ts69/102 行,#5584 引入,cli 座位在修)—— main 上本来就红,与本改动无关。JSON.parse通过,条目数 32 不变;round-trip 字节一致,故 diff 恰好 8 增 8 删(4 条 × why+closes)。脚本断言了$comment、条目数、每条的file/unguarded/kind未变,并在遇到非预期原文时直接抛错而不是改错条目。node scripts/check-nul-bytes.mjs:OK(5533 个跟踪文本文件,无裸控制字节);另做门禁盲区自扫grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]',干净。skip-changeset标签路线(未写空 frontmatter changeset)。已知环境红,与本 PR 无关:ESLint job 全仓红即 #5604 签名(非必需检查,不追);Check Changeset 首 run 可能因标签竞态红(#5580,同轮在修)。
Generated by Claude Code