12 Commits
Author SHA1 Message Date
yeasy 1499d4e6ef ci: stop pinning the attest action's SHA inside the test that guards it
供应链测试把 action 的 **SHA 按字面钉死**:

    self.assertIn("actions/attest-build-provenance@0f67c3f... # v4.1.1", ...)

Dependabot 升级这个 action 时改的正是被断言的那一行,于是断言必然失败、`build` 红、
PR `mergeStateStatus=BLOCKED`。这是**结构性死锁**:该 action 的任何一次升级都会打挂
钉死它的测试,PR 永远合不进来。**全集群 7 个仓库钉的是同一个 SHA,6 个 PR 同时卡在这里**
(agentic #13、aifbs #8、ai_security #17、blockchain #176、ceg #16、docker_practice #578)。
反证很干净:另外 4 个断言写成 `assertIn("actions/attest-build-provenance@")` 的仓库
(claude_guide / peg / fde / llm_internals)**同一个升级早就合进去了**。

断言真正要守的是「release job 必须用 SHA 钉住这个 action」——**这个意图不需要记住是哪个
SHA**。改为 `assertRegex(..., r"actions/attest-build-provenance@[0-9a-f]{40} # v\d")`:
仍然强制 40 位 SHA + `# vN` 溯源注释,**比那 4 个仓库现用的宽松写法更严**,但升级不再撞墙。
同批把 aifbs / ai_security 里 `dependabot/fetch-metadata@25dd0e3... # v3.1.0` 的同款钉死
一并改掉(未升级该 action,只解除钉死)。

同时在主干上直接升掉 Dependabot 提的两个版本,**SHA 逐个用 GitHub API 解引用核过**
(`browser-actions/setup-chrome` 的 tag 是 annotated tag,要走 `git/tags` 再取
`.object.sha`,直接读 `git/ref/tags` 会拿到 tag 对象的 SHA 而误判):

- `actions/attest-build-provenance` 0f67c3f… v4.1.1 → 4d10147… v4.2.2
- `browser-actions/setup-chrome` 2e1d749… v2.1.2 → 48ad923… v2.2.0(blockchain_guide 已在 2.2.0)

**负向验证**(AGENTS.md 核心约定 4,逐条证明新断言没被改成永真):把 pin 换成浮动 tag
`@v4` → FAIL;保留 SHA 但删掉 `# vN` 注释 → FAIL;还原 → OK。七个仓库各跑一遍,
结果一致。而「换一个合法 SHA 应当通过」这一条由本提交自身证明——pin 从 v4.1.1 换到
v4.2.2,测试全绿。

各仓库 `check_project_rules`、`unittest discover -s tests -p 'test_*.py'`、
`git diff --check` 均通过;docker_practice 另跑 `npm test` 通过。
2026-08-25 14:43:03 -07:00
yeasy f315ef93b3 test: 新增中文排版门禁(中英文空格 + 含中文括号全角)
今天这批 style 提交把两项排版统一到位,但**没有任何东西拦住下一段正文漂回去**:`check_project_rules.py` 看围栏与链接,`check_emphasis.py` 看加粗标记,工作区的 `format_checker.py` 看引号、围栏语言与标题空行——**行内排版此前一道门禁都没有**。漂移到什么程度是有实测的:同集群一本书的中英文边界曾有 45% 未空格、另一本的含中文括号是 50/50,而且都是在**同一个文件内**混用。

两条规则:

- **规则一**:汉字不得与 `[A-Za-z0-9]` 直接相邻。`Harness的定义`、`第4章` 违规。
- **规则二**:括号内容含任何中文时必须用全角。`(用户命名空间映射)` 违规;**纯拉丁内容的半角括号一律合法**——`新建一个层 (Layer)`、`项目(Agent)的经验` 都不报,因为它们的内容里没有中文。

**刻意不检查**中文标点与拉丁字符之间的空格(`(如 UI、监控服务)`)——全集群一致不加,全角标点本身自带视觉留白。

**负向验证**(AGENTS.md 核心约定 4:不可能失败的检查不构成证据):把本书扫改前(`ef262553~1`)的内容原样喂给这道门禁,报出 规则一 **28 处**、规则二 **338 处**;喂当前内容,报 **0 处**。

文件自带 9 个用例,其中 5 个专门钉住「不该报的别报」和「该报的必须报」:纯拉丁括号不报、行内代码/链接目标/裸 URL/HTML 属性/行间公式不报,而 `<span>中文abc</span>` 的**标签之间的文字**要报、`定价 $25/$125 per M tokens` 这种成对的 `$` **不得**被当成公式把中间的正文遮蔽掉、`| <1% | … | >400ms |` 这种表格行**不得**被当成一个 HTML 标签。后两条是扫改时真踩过的坑,掩码写松了会静默漏报。

占位符取私用区字符(既非汉字也非拉丁字符也非数字),且每条掩码正则都排除该区间——否则贪婪的 `\S+` 会把前一条规则刚放下的占位符一起吞掉。
2026-08-24 16:06:29 -07:00
yeasy 657c0b25df test(html-reader): guard the bold-lead-in list rendering with real pandoc
The reason 640 collapsed lists shipped green is that no test exercised real
markdown->HTML rendering — the existing build_html_reader tests stub pandoc with
a fake, covering TOC/mermaid plumbing but never the markdown parse. This feeds
the exact bold-lead-in pattern through the real pandoc invocation the reader uses
and asserts the list survives as <ul>. Proven both ways: passes with the
extension, fails when it is removed.
2026-07-23 22:57:35 -07:00
yeasy 898fb10bbe ci: track the latest mdPress release instead of a per-repo pinned version
Per the author: mdPress should default to the latest release.

The cluster had drifted to three versions (0.7.10 x4, 0.7.11 x9, 0.7.14 x1),
and nine of those were pinned to bytes upstream had rebuilt under an existing
tag — the exact thing the harness move to 0.7.14 refused to do on principle.
Pinning also took CI down cluster-wide twice when a tag was rebuilt, because
the digest no longer matched. Latest is now 0.7.15; nothing was on it.

Each of the 43 install sites now resolves the newest release at build time by
following the /releases/latest redirect (no api.github.com call, so no
unauthenticated rate limit on shared runner IPs) and exports the version via
GITHUB_ENV.

Integrity is kept, not dropped: the archive is verified against that same
release's published checksums.txt, and a missing entry aborts the step rather
than passing silently. The honest trade-off is that this verifies the download
rather than pinning an immutable artifact — a rebuilt release is now followed
instead of failing the build. That is the intended behaviour here, since the
rebuild breakage was the problem being solved and upstream is the same author.

Tests updated in step: 12 suites asserted the literal MDPRESS_SHA256 as a
proxy for "this download is checksum-verified". They now assert checksums.txt,
which is where that guarantee lives.
2026-07-23 13:47:03 -07:00
yeasy f82e13017d ci: add Identity Guard rejecting AI-assistant commit attribution
起因:blockchain_guide 上曾有一个 claude/novel-content-extraction-r0wys3
分支,4 个提交的 author 和 committer 都是 Claude <noreply@anthropic.com>
(内容还是与本书无关的小说抓取脚本)。分支已删除,但暴露出一个缺口:
既有的 .git/hooks/commit-msg 只查提交信息里的 Co-authored-by 尾注,
查不到身份字段;而且本地钩子不随仓库分发,那 4 个提交来自云端会话,
根本不经过本地钩子。

因此把闸门放到服务端:本工作流在 push 与 pull_request 上扫描本次新增
提交的 author/committer 身份与 Co-authored-by 尾注,命中即失败。
本地另配 pre-commit(拦当前身份)与 pre-push(拦 cherry-pick/rebase
带进来的外来提交)作为纵深防御,二者不入库。

判定刻意收窄,避免误伤本仓库群里大量讨论 Claude/Codex 的正文:
只检查身份字段与行首锚定的 Co-authored-by 尾注,绝不扫描自由文本;
姓名要求全等("Claude Dubois" 这样的真人不受影响),邮箱按厂商域名
(含子域)匹配,并覆盖 claude[bot] 这类 GitHub App 身份。

已验证:
- 用被删分支的真实 4 个提交做回归,push / pull_request / 新建分支
  三种到达形态全部拦下;
- 全部 14 个仓库的完整历史(5,715 个提交,含 docker_practice 1,591
  个多人历史与 claude_guide 339 个满是 Claude 的提交)零误报;
- dependabot 的 Co-authored-by、真人 Claude Dubois、正文提到
  co-authored-by 但非尾注的提交,均正确放行;
- 范围解析不出来时 fail closed,只有确实没有 head 提交(删分支)才放行;
- tags-ignore 避免发布 tag 触发一次重复的全量审计。
2026-07-22 15:24:38 -07:00
yeasy 2ef6d80d4f fix(ci): make publication checks runner-safe 2026-07-11 06:44:12 -07:00
yeasy 44822cea16 test(ci): enforce preview publish step order 2026-07-10 19:29:30 -07:00
yeasy 1f970681ee test(ci): enforce exact preview tag commands 2026-07-10 19:29:30 -07:00
yeasy 397c66673b fix(ci): fail closed on preview lookup errors 2026-07-10 19:29:30 -07:00
yeasy 8cd6094ae9 fix(ci): keep preview tag current 2026-07-10 19:29:30 -07:00
yeasy ee0fbd7d38 fix(ci): attest releases and validate offline examples 2026-07-10 19:29:30 -07:00
yeasy daa6661b2b fix(ci): harden publishing and validate examples 2026-07-10 19:29:30 -07:00