chore(scripts,ci): 决策框架四份副本的结构同构门禁(轴数/轴序/绑定句)(#5798) - #5865
Merged
Conversation
同一套 binding 决策评估框架在仓库里手写了**四份**,跨三个文件:内部 agent 协议两份(`.claude/skills/pm-dispatch/SKILL.md` 的第 8 步、`.claude/agents/os-dev.md`), 已发布给第三方的一份文件里两份(`skills/objectstack-pm-dispatch/SKILL.md` 的正文 + 它内嵌的 dev-agent 模板)。此前**没有任何门禁比对它们**。 后果实测发生过:#5130(2026-08-04)把内部框架由两轴扩为三轴,发布版镜像 原封不动,分叉存在两天 —— 装了这份 skill 的第三方 PM agent 按两轴呈报, 本仓按三轴 —— 直到人工发现,再花一个 issue 加一轮维护者裁决(#5451 / PR #5799)才补齐。本门禁就是 #5130 当时缺的那个机制。 判据是**结构同构,刻意不逐字**: - 轴数(每份自洽,且四份相等); - 轴名序列,经脚本内显式的 `AXIS_MAP`(内部中文 ⇄ 发布英文名词映射)比对, 顺序有意义; - 绑定句在位(声明了轴却不把推荐意见绑定到轴上,就不是同一套框架); - 文件内其它处对轴数的引述(`the deep three-axis analysis`)与框架一致 —— #5130 当时也得改这一处。 ⛔ 不做逐字比对:#5451 裁定 B 让发布版**刻意泛化**(去掉「创业项目」自我 描述与本仓单号,扩张姿态改由安装方 conventions 文件声明)。逐字门禁会永久 红灯,然后被删掉而不是被遵守。self-test 有一例专门钉这个方向:只改措辞 (抹掉单号、替换自我描述)必须**保持绿**。 两条设计约束来自既有教训: - **提取失败即红**(#4690 反模式):锚点找不到框架段就失败并点名,绝不静默 跳过。 - **锚点不含被比对的值**(#5680):锚点**捕获**数词(`%N%`)而非写死 「three」。这一条初稿踩过:英文绑定句的量词与轴数**共变**(三轴写 `all three axes`,两轴写 `both axes`),写死 `all` 的锚点拿真实的 pre-#5799 树一跑,报的是「绑定句不在位」,而真相是「这份两轴、其它三轴」 —— 正是 #5680 说的把「不相等」降级成「提取不到」。改为 `%Q%` 吞掉整个 量词后,报的是轴数分歧,并准确指出发布版缺的是 business-need 轴。 分层:门禁放根 `scripts/`,不放 `packages/spec`。既有的 `check:skill-refs` / `check:skill-docs` 在 spec 包里,是因为它们是**生成器**(源是 `packages/spec/src`),并登记在 spec 的 check:generated 账本里;本门禁不读 spec 源、不产出任何生成物,只比对两份手写文档,其中一份(`.claude/**`) spec 包本不该知道。跨仓 prose 策略门禁历来住在根 scripts/ (check:role-word / check:doc-authoring / check:nul-bytes 都从这里扫 skills/)。 CI 接线在 `lint.yml` 的 typecheck job,紧邻 `check:skill-refs`,理由注释引用 它那条同源理由(「These ship to third parties via `npx skills add`, so the drift is served straight to consumers' agents」)—— SKILL.md **正文**同样这么 发出去,而既有两个门禁只看 frontmatter 与生成索引。放这个 job 也是同一条 反休眠理由:无 paths filter 且为必需检查;`.claude/**` 过滤器尤其会瞎掉, 因为有一半副本住在那里。 另附反休眠判据:扫 `.claude/**` 与 `skills/**` 的 markdown,出现第五份带 框架指纹却未登记在 `COPIES` 的副本即红(#4291 手工输入清单腐坏的教训)。 Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE
|
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 6, 2026 09:56
os-zhuang
enabled auto-merge
August 6, 2026 09:56
Contributor
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 31091255496 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
This was referenced Aug 6, 2026
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 #5798
按 PM 裁定的方向 A 最小形态落地:比对两份手写副本的框架结构,不逐字比对。⛔ 未做方向 B(单一来源派生)。
问题
同一套 binding 决策评估框架在仓库里手写了四份,跨三个文件:
internal-pm.claude/skills/pm-dispatch/SKILL.md第 8 步internal-dev.claude/agents/os-dev.mdpublished-pmskills/objectstack-pm-dispatch/SKILL.md正文npx skills add直读仓库)published-dev此前没有任何门禁比对它们。#5130(2026-08-04)把内部框架由两轴扩为三轴,发布版镜像原封不动,分叉存在两天:装了这份 skill 的第三方 PM agent 按两轴呈报,本仓按三轴,直到人工发现,再花一个 issue 加一轮维护者裁决(#5451 / PR #5799)才补齐。本门禁是 #5130 当时缺的那个机制。
判据(结构同构,⛔ 刻意不逐字)
AXIS_MAP(内部中文 ⇄ 发布英文名词映射表)比对,顺序有意义;the deep three-axis analysis)与框架一致 —— pm-dispatch SKILL:决策分析轴由两条扩为三条 —— 补「实际业务需求」轴与创业聚焦原则(维护者 2026-08-04 指示) #5130 当时也得改这一处;.claude/**与skills/**的 markdown,出现第五份带框架指纹却未登记在COPIES的副本即红(ci.yml 的 generated paths filter 是门输入集合的手工副本、无人对账——三次漂移在案,收编剩余 4 个门后应整个删除 #4291 手工输入清单腐坏的教训)。⛔ 不逐字比对是刻意的:#5451 裁定 B 让发布版泛化(去掉「创业项目」自我描述与本仓单号,扩张姿态改由安装方 conventions 文件声明)。逐字门禁会永久红灯,然后被删掉而不是被遵守。self-test 有一例专门钉这个方向:只改措辞必须保持绿。
两条设计约束来自既有教训
提取失败即红(#4690 反模式):锚点找不到框架段就失败并点名,绝不静默跳过。
锚点不含被比对的值(#5680):锚点捕获数词(
%N%)而不写死「three」。这一条初稿踩过 —— 英文绑定句的量词与轴数共变(三轴写all three axes,两轴写both axes),所以写死all的锚点等价于把轴数写进锚点。拿真实的 pre-#5799 树(77adf297f^)一跑,初稿报的是:真相是「这份两轴、其它三轴」,而门禁说的是「找不到绑定句」—— 正是 #5680 讲的把「不相等」降级成「提取不到」。改为
%Q%(吞掉整个量词、只捕获数词)后,同一棵树报的是:即准确指出发布版当时缺的是 business-need 轴。这是本 PR 最强的一条证据:门禁拿真实的历史现场跑出真实的诊断,不只是过合成 fixture。self-test 里
two-axis copy phrased "both axes" → red on the COUNT, not on extraction一例把这个教训钉住(该例还断言错误信息里不得出现「找不到」类措辞)。分层理由(为何是根
scripts/,不是packages/spec)既有的
check:skill-refs/check:skill-docs住在 spec 包,是因为它们是生成器(源为packages/spec/src),并登记在 spec 的check:generated账本里。本门禁不读 spec 源、不产出任何生成物,只比对两份手写文档,其中一份(.claude/**)spec 包本不该知道;放进去还会被拖进那个「有生成器」的账本。跨仓 prose 策略门禁历来住在根scripts/(check:role-word/check:doc-authoring/check:nul-bytes都从这里扫skills/)。已跑
check:generated --reconcile-only确认无关联:该账本只读packages/spec/package.json,18 check: + 13 gen: 全部已分类,绿。CI 接线
.github/workflows/lint.yml的 typecheck job(必需检查、无 paths filter),紧邻check:skill-refs,理由注释引用它那条同源理由 ——「These ship to third parties vianpx skills add, so the drift is served straight to consumers' agents」。SKILL.md 正文同样这么发出去,而既有两个门禁只看 frontmatter 与生成索引。放这个 job 也是同一条反休眠理由;.claude/**过滤器尤其会瞎掉,因为有一半副本住在那里。验证
真仓现状比对 绿(#5799 已合,首跑即绿,符合本单排序理由):
pnpm check:skill-frame-sync(self-test + 真仓,CI 即这条)—— 12 例全过,先红后绿四个方向都在:fixture 用的是真实文档在内存里的变体,不是合成样本;每处变异都断言「确实改到了」,所以 fixture 漂移会响亮失败,而不是让一个期望红的用例悄悄变绿(实跑中确实触发过一次:
structurally hard to的换行位置对不上,门禁自己报了self-test fixture drifted: mutation target not found)。其余门禁:
node scripts/check-nul-bytes.mjs→OK (scanned 5692 tracked text file(s) … no raw ASCII control bytes)node scripts/check-workflow-status-functions.mjs(动了 workflow)→OK (scanned 22 workflow file(s), 39 job(s), 21 job-level if: … all naming a status function),--self-test34 断言过grep -naP的 C0 + DEL 字符类)→ 零命中npx eslint scripts/check-skill-frame-sync.mjs→ 干净changeset
无
.changeset/*.md:改动面为门禁脚本 + CI + 根 package.json 脚本,非发布面,对使用者无行为变化 —— 走skip-changeset标签路线。Generated by Claude Code