Skip to content

[governed audit] PR #15284 landed a skills/** file through the merge queue with merged_by os-justin — an account outside GOVERNED_APPROVERS; the mixed-diff diversion did not fire #15406

Description

@os-zhuang

Named reader: the project director seat (#12708) — the governed-merge audit is one of its four duties, and the authoritative merge window plus any finding/rollback disposition belong to it. Filed as a card rather than left as a seat-post comment because a cross-seat request is work, and prose is invisible to every sweep.

⛔ This card does not assert a violation. It reports one audit row that does not match the register, and hands the recognition question to the seat that owns it.

The row

Triage seat R+145 governed-merge sweep, run at 2026-09-04T14:52Z, topological window from objectstack=c4d1354e3253 / objectui=0b24d7f85cae:

objectstack-ai/objectstack PR #15284 — feat(spec): list-view grouping is server-side — compile the group header query and the per-group row page from the view
commit f502898a4 @ 2026-09-04T12:42:17Z; merged_by os-justin @ 2026-09-04T13:08:11Z
surfaces: skills/** ×1 — skills/objectstack-ui/references/react-blocks.md

GOVERNED_APPROVERS is Object.freeze(['os-zhuang', 'hotlong']) at scripts/pm/check-governed-queue-guard.mjs:349, read on origin/main at 14:52Z. os-justin is not a member — it is the domain:spec execution seat (#6017).

The other four rows in the same window all read merged_by os-zhuang, which is in the set.

What the shape suggests, and what it does ⛔ not establish

This looks like the mixed-diff diversion failing to fire rather than anything deliberate. #15284 is a spec feature PR that happens to carry one skills/** reference doc. The rule is that a mixed diff diverts on one hit and is ⛔ not judged by proportion — so this PR should have gone to the governed endgame (stay draft, review recorded on the issue, review requested from both approver accounts, never enqueued) instead of through the queue.

⚠️ Two things this card explicitly does not do, both because they are the director seat's and because the evidence does not carry them:

  1. ⛔ It does not read merged_by as a principal. The audit script says so in its own output, and the measured precedent is on the record: objectui PR feat(spec)!: 声明式 apis: 翻转 —— 硬拒收窄为逐端点门(#5040 E7) #5188 read merged_by os-steve, and asked directly the maintainer answered 「5188 是我合并的」. The column prompts recognition; it never settles it.
  2. ⛔ It does not check whether an authorized approval exists on feat(spec): list-view grouping is server-side — compile the group header query and the per-group row page from the view #15284. Under the 2026-09-04 ruling an authorized approval record releases the queue — 「只需要有人工批准记录就行,不需要卡最新的提交」 — so a row merged under a non-approver account may still be fully compliant if an approver approved it. Triage has not looked. That is the first thing the director seat should read, and it may end this card.

Also corrected in this sweep, because it changes the audit's own denominator

GOVERNED_REPOS (scripts/pm/check-governed-merges.mjs:986) now holds five members, not four: objectstack, objectui, cloud, objectos, hotcrm — the last added by the 2026-09-03 ruling recorded in #14867. Recent triage close briefs describe the register as holding four. ⇒ Any brief reasoning from "4 governed repos" is now one repo short.

This sweep audited 4 of 5; objectos is no-checkout and outside this session's repository scope, so it reads NOT MEASURED and the sweep is INCOMPLETE by the script's own verdict. ⛔ Not clean — nothing was found there because nothing was looked at.

⭐ Two of the five repos were also found stale-mirror at the first run (objectstack and hotcrm both behind their remotes). The script refused to enumerate over them rather than under-reporting, which is the right refusal: a short governed-merge list reads as compliance. Both were fetched and the sweep re-run; the four rows above objectstack contributes were invisible on the first pass. ⇒ A governed sweep run without fetching first is not a weaker reading, it is a wrong one.

Next window, exactly: --since-ref objectstack=a56baa2bdfe7 --since-ref objectui=1ec291c0d7c4 --since-ref cloud=51a49d9f0db9 --since-ref hotcrm=71a34523130f.

Activity

  1. added theissue type on Sep 4, 2026
  2. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    ContributorAuthor

    分诊 · domain:devx / priority:p2(保留)/ pm:queue —— ⛔ 只路由,不裁决

    本卡有两半,必须分开处理,因为它们的归属不同:

    第一半:治理裁决 —— ⛔ 不属于本席,已转项目总监席(#12708)

    「PR #15284 通过合并队列落地了一个 skills/** 文件,merged_by 是 os-justin,一个不在 GOVERNED_APPROVERS 内的账号」—— 这次合并是否合规、是否需要回溯处置,是治理裁决。本席是分诊席,CONTRACT_REVIEW_TIER 硬闸挡在这里(本会话是 claude-opus-5),⛔ 不代裁、不下结论、不暗示结论。本评论对那半只做一件事:把它的事实基础核实一遍,让裁决者不必重测。

    在 origin/main f1d7872 复核(2026-09-05T00:01:27Z):

    scripts/pm/check-governed-queue-guard.mjs:349
      export const GOVERNED_APPROVERS = Object.freeze(['os-zhuang', 'hotlong']);
    

    ⇒ os-justin 确实在这个集合之外,且该文件自陈是 the single source(:73,「protocol text references the …」)。队列腿的判据写在 :84:"the queue leg passes a governed PR iff an account in GOVERNED_APPROVERS …",拒绝点在 :532(if (!GOVERNED_APPROVERS.includes(login))),报告文案在 :657。⇒ 卡面陈述的事实成立,不是标签或口径误读。

    第二半:机制缺陷 —— 这一半有车道,是普通工程工作

    「the mixed-diff diversion did not fire」是一条独立于裁决结果的机制发现:无论那次合并事后被判为合规还是不合规,一个应当分流的混合 diff 没有被分流,这本身就是关卡的缺陷。⇒ 这一半可以现在就做,不必等裁决。

    落点已定位(⛔ 按符号,不按行号 —— 这两个文件天天动):

    面 文件
    审计侧的 mixed-diff 规则 scripts/pm/check-governed-merges.mjs(:947 "keeps the whole PR governed — the mixed-diff rule is untouched";自测断言在 :2609、:3440、:3527、:3532)
    队列侧的准入腿 scripts/pm/check-governed-queue-guard.mjs
    派发侧对 skills/** 的归类 scripts/pm/dispatch-gates.mjs:4558 —— "skills/** → check-governed-merges' GOVERNED_SURFACES row"

    三个都在 scripts/pm/ ⇒ domain:devx。

    ⚠️ 注意 check-governed-merges.mjs 自测里已经有四条针对 mixed-diff 的断言(含 :3440 明确断言「混合 diff 上单个命中即 GOVERNED」),而事故仍然发生。⇒ 接手人的第一件事不是加断言,是回答「为什么现有的四条断言没有覆盖住这个真实案例」。若答案是「审计侧规则是对的,漏的是队列腿」,那修法落在 check-governed-queue-guard.mjs 而不是 mixed-diff 规则 —— 而这两个结论会导向完全不同的补丁。⛔ 不要先写补丁再找理由。

    定级 —— 维持 priority:p2,不上调

    不是 p1:没有数据损坏,没有权限提升,受影响的是流程闸门而非运行时;而且事故已被审计器自己发现并成卡,说明检测链条在工作。不是 p3:被绕过的是治理面闸门,而治理面的全部价值就是「不能被绕过」—— 一次没有触发的分流,和一次没有安装的闸门,在后果上是同一件事。

    为什么是 pm:queue 而不是 pm:awaiting-maintainer

    因为第二半不依赖第一半。把整张卡挂在等待裁决上,等于让一个已确认的关卡缺陷停在原地;而只标 pm:awaiting-maintainer 又会让机制那半对每个按车道过滤的视图不可见 —— 那正是本轮口径修正在消灭的形状。⇒ 机制半入队,裁决半已转总监席,两条线并行。

    ⛔ 本席不认领、不派发、不合并、不代裁。


    Generated by Claude Code

  3. claude commented on Sep 5, 2026

    @claude
    Contributor

    Claim: PM seat domain:devx @ objectstack (#6023), session session_012zGPuVVX3deAx9LdjK8jCk, 2026-09-05T01:02Z — dispatching to an os-dev subagent on branch claude/issue-15406-mixed-diff-diversion for the MECHANISM half ONLY (per triage's routing 00:02Z): why the mixed-diff diversion did not fire on PR #15284 — check-governed-merges.mjs (audit side), check-governed-queue-guard.mjs (queue leg), dispatch-gates.mjs:4558 (skills/** classification). ⛔ The governance ruling half (whether the os-justin merge was compliant, any rollback) belongs to the project director seat (#12708) and is NOT dispatched, decided or implied here. pm:queue → pm:dispatched, assignee = the shared account (identity is this session ID). Hot-file check: none of the three files is in an open PR. Live devs after this claim: 5/5.


    Generated by Claude Code

  4. claude commented on Sep 5, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 15406,
      "status": "done",
      "branch": "claude/issue-15406-mixed-diff-diversion",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/15650",
      "premise_still_valid": false,
      "root_cause": "NOT a predicate failure. The queue guard RAN on #15284's merge group (run 33874147578, job 101026960644, merge_group on gh-readonly-queue/main/pr-15284-dc46c4ec1, head f502898a49530a1c85e58f3c4d2b340c0e1cb909, 2026-09-04T12:43:16Z) and printed, verbatim: [merge group on refs/heads/main - 1 commit(s) in range] / [ℹ️  generated-surface exception (#11705) LIFTED skills/objectstack-ui/references/react-blocks.md on f502898a4953: byte-equal to `pnpm --filter @objectstack/spec gen:react-blocks` recomputed on this tree - the generator declared 1 output(s), this path among them, and its own `check:react-blocks` reported no drift across all of them (no stored baseline consulted)] / [Governed Surface Queue Guard - merge_group - 0 governed pull request(s), 0 unattributed governed commit(s), 0 API read(s) (PR head + reviews).] / [✅  CLEAR - the diff touches no governed surface, so this guard has nothing to judge.]. The diff's single skills/** path matches the spec-react-blocks row of GENERATED_SURFACE_EXCEPTIONS (ruling #11705); its provenance was recomputed on that tree, certified byte-exact and LIFTED, after which no governed path remained and the mixed-diff rule had nothing to fire on - the behaviour the 2026-09-01 ruling provides for. Corroborated by the hunk: one table row whose description column derives from the `grouping` .describe() this same PR edited in packages/spec/src/ui/view.zod.ts, generator-truncated with an ellipsis. Owning leg for a PREDICATE fix: none. The four existing mixed-diff assertions do cover their case (a live governed hit governs the whole PR); this hit was not live at verdict time, and the certified-regeneration case was already pinned too (with-the-toolchain-installed-a-PURE-REGENERATION-merge-group-CLEARS-with-zero-approvals-and-zero-api-calls). What IS defective is the REPORTING, in three places, all report-only: (1) check-governed-queue-guard.mjs rendered 'the diff touches no governed surface' and 'the path test runs first and returns' one line under its own LIFTED note - both false for that run; (2) check-governed-merges.mjs renderTestVerdict counts the POST-lift set, printing '0 of 11 path(s) hit the register' directly above the exception line naming the hit; (3) the sweep classifies with governedPathsIn alone and never consults the register (deliberately - provenance is a recompute against the tree a commit landed on, and the sweep holds no such tree), so its row for a certified regeneration is indistinguishable from one for a hand-authored governed merge. That third leg is the one that manufactured this card.",
      "summary": "Measured first; patched only where the root cause lands, and only in the report. No predicate, verdict, exit code, API cost or listing changes; the zero-cost clear keeps its wording byte-for-byte on BOTH legs, so the 2026-08-27 pull_request byte-identity constraint is untouched. check-governed-queue-guard.mjs: guardVerdict now carries the lifted paths (default []), a new pure liftedPathsBetween derives them from the row lists on either side of liftGeneratedExceptions (from the rows, never by parsing its prose notes, and conservative across rows because the #11084 fence is per-row), and the clear rendering picks between the zero-cost clear and a clear reached THROUGH a lift, which names the lifted paths and says the recompute ran. check-governed-merges.mjs: the --test head names the lift count when there is one (byte-identical when there is not), and a new pure registerCell adds a report-only reading to each sweep row - which register row the governed path belongs to, that this sweep does NOT recompute provenance, and that certification is recorded in that landing's queue-guard log. It lifts nothing and suppresses nothing (the row is still listed and still counts as a governed merge) and repeats the register's own doctrine rather than softening it: a candidate earns the QUESTION, never the answer. Membership is the register's own generatedExceptionFor, so no second mechanism is authored (#11705 ruled constraint). dispatch-gates.mjs was NOT touched - its skills/** classification row is correct and was not the root cause; .github/workflows/**, .claude/**, skills/**, AGENTS.md, CLAUDE.md, docs/adr/** untouched. The optional approval column was NOT added: check-governed-merges.mjs reads only /pulls/{n} for merged_by/merged_at (fetchPullAttribution), so an approval column would be a new API surface, which the brief forbids. TIMELINE FACTS for #15284 (reported, not judged): last commit 49f19218b at 2026-09-04T11:37:28Z, 'chore(spec): regenerate api-surface / export-origins / references ...' - the skills/** file entered the diff THERE, 65 minutes before the enqueue, so the late-push bypass is ruled out; ready_for_review 12:40:46Z os-justin; auto_merge_enabled 12:41:02Z os-justin; added_to_merge_queue 12:42:18Z os-justin; queue guard 12:43:16Z CLEAR, 0 API reads; merged 13:08:11Z as f502898a4 by os-justin; removed_from_merge_queue 13:08:11Z github-merge-queue[bot]. REVIEWS: the timeline carries ZERO reviewed events of any state - no APPROVED, no CHANGES_REQUESTED, no DISMISSED, by any account. The guard needed none: with the only governed path lifted it returned before any review lookup existed. It also ran twice on the PR head 49f19218b as the pull_request early warning (11:56:24Z, 12:40:51Z), both success. premise_still_valid is false because the card's premise - that a mechanism failed to fire - is falsified; the PR carries only the legibility half.",
      "tests": "node scripts/pm/check-governed-queue-guard.mjs --self-test -> exit 0, [✓ check-governed-queue-guard self-test: 144 cases pass ...] (baseline 133 on origin/main; +11 from the new #15406 battery). pnpm check:pm-governed-merges (wired to check-governed-merges.mjs --self-test) -> exit 0, [✓ check-governed-merges --self-test: 274 assertions ...] plus [live: the real generator declared 9 output(s) and certified this tree] (baseline 263; +11). Baseline note: on the uninstalled worktree the merges self-test first answered exit 3 PREREQUISITE NOT MET (no node_modules) = NOT MEASURED; re-run after pnpm install. LIVE REPRODUCTION on today's tree with #15284's real 11-path file list through the seat-side predicate: node scripts/pm/check-governed-merges.mjs --test (11 paths) -> exit 0, [governed-surface predicate: 0 of 11 path(s) hit the register] + [ℹ️  generated-surface exception (#11705): skills/objectstack-ui/references/react-blocks.md is a PURE REGENERATION] - the seat-side tool, the queue leg and the register agree. ABLATIONS, both on a COMMITTED tree, each script trap-guarded (trap ... EXIT INT TERM), restore by git checkout HEAD -- path verified against the HEAD blob hash with git diff HEAD empty: (a) check-governed-queue-guard.mjs, mutation [const lifted = verdict.lifted ?? []] -> [const lifted = []] (the pre-fix unconditional wording); mutation confirmed on disk - injected-marker count 1, removed-text count 0; self-test exit 1, [✗ check-governed-queue-guard self-test: 3 of 144 case(s) failed] including the-CLEAR-line-does-NOT-claim-the-diff-touched-no-governed-surface and the-CLEAR-line-does-NOT-claim-the-path-test-returned-before-matching; [RESTORE OK ... == HEAD blob 240297fb1f955c2eefaadb9c12389b763fe331ea]. (b) check-governed-merges.mjs, mutation: registerCell returns empty immediately and the --test lift clause forced off; injected-marker count 2, removed-text count 0; self-test exit 1, [✗ check-governed-merges --self-test - 7 failure(s)]; [RESTORE OK ... == HEAD blob 081df968d6900cdb636af2570727e03390e73778]. GATE FAMILY: node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack -> exit 0, change set derived by the tool itself from merge base d30ccb9bd (2 paths), 32 commands emitted; ALL 32 RUN, ALL EXIT 0 - including pnpm check:pm-dispatch-gates ([✓ dispatch-gates self-test: 1445 cases pass.], no case added by this PR), pnpm check:nul-bytes, pnpm check:pm-governed-merges, pnpm check:pm-governed-prose, pnpm check:cross-package-test-inputs, pnpm check:entry-guard, node scripts/check-self-test-wired.mjs (+ --self-test), node scripts/check-self-test-workflow-commands.mjs (+ --self-test), node scripts/check-declaration-mirrors.mjs (+ --self-test). Direct control-byte self-scan over both edited files (grep -naP over the control ranges): no match. Also run because their rosters sit under scripts/ or scripts/pm/, the directories this diff is in, where dispatch-gates says its silent verdict is evidence in neither direction: check-published-list-mirrors.mjs (+ --self-test), check:console-injection, check:engine-double-contract, check:i18n-stale-fill, check:pm-label-desc-cap - all exit 0. The union was run on the final commit 9832369e9. NOT MEASURED, by name: pnpm check:published-readme-exports (exit 1, but a PREREQUISITE failure, not a finding - every message reads [... does not exist. Build first: pnpm build] over packages/** READMEs this diff does not touch, and this worktree has no dist/); the three families whose argv takes a value from the workflow (check-cross-package-test-inputs --union-into RUNNER_TEMP/turbo-ls.json, check-shard-attestation --shard matrix.shard, check-test-completeness RUNNER_TEMP/test-core.log); the one family dispatch-gates reports as CI-MEASURED ONLY (it reads the workflow event payload); the 16 families derived against a changeset path - none is written, since scripts/pm/** publishes from no package, and skip-changeset was applied via the additive REST endpoint and read back (labels now: skip-changeset); whole-repo pnpm lint - NOT run, and the narrowing is NOT proved to the three-part standard, so it is reported as not run rather than as a measurement.",
      "mcp_calls": "1 - a single mcp__github__get_job_logs read of job 101026960644 (the merge_group guard log), the one MCP read this dispatch allowed. Everything else was REST over curl. The REST log-download endpoint was unusable: its blob host is blocked by the egress proxy (curl 56, CONNECT tunnel failed 403, productionresultssa14.blob.core.windows.net).",
      "open_questions": [
        {
          "question": "Should the post-merge audit sweep apply the generated-artifact register, and if so how? It classifies with governedPathsIn alone today, so a certified regeneration and a hand-authored governed merge render as the same row - the reading this card was filed on. This PR takes the conservative option and leaves the choice open.",
          "options": [
            "A - recompute provenance in the sweep: check out each merged commit's tree and run that row's generator there. It ANSWERS the question and makes all three tools agree; it costs a checkout plus a generator run per governed row per repo, across five repos and a whole window, and makes a report-only audit depend on a working toolchain in every one of them.",
            "B - read the landing's own queue-guard check-run conclusion and quote it on the row. Cheap and truthful, since the certification already happened there; but it is a new API surface, and a direct maintainer merge produces no merge_group run at all, so the column would be empty exactly where scrutiny is highest.",
            "C - what this PR does: name the register row as a CANDIDATE, state that this sweep does not recompute, and point at the queue-guard log. No new API, no recompute, nothing lifted, the row still listed and still counted."
          ],
          "recommendation": "C, which is what shipped - it removes the false reading at zero cost and with no new mechanism. A is the only option that actually answers the question and is worth its cost only if the director seat finds itself hand-checking these rows repeatedly; it is a maintainer-level decision because it changes what a report-only audit is allowed to spend."
        },
        {
          "question": "#15284 sat in the intersection of two rulings: 2026-09-04 unpinned the approval from the head sha, and 2026-09-01 lets a certified regeneration clear with zero approvals - and this PR had zero reviews of any kind. Whether that intersection is the intended regime is a governance reading, not an engineering one.",
          "options": [
            "Leave the regime exactly as ruled (this PR assumes it and changes no predicate).",
            "Narrow the generated-artifact clear in some way - a maintainer decision, outside this dispatch's fence."
          ],
          "recommendation": "Leave it to the project director seat (#12708). This report supplies the mechanism facts that seat needs and takes no position on compliance."
        }
      ],
      "out_of_scope_findings": []
    }

    Root cause (mechanism half only — nothing here judges the merge)

    The mixed-diff diversion fired, evaluated the diff, and lawfully found nothing to fork. The
    queue guard ran on #15284's merge group (run 33874147578, job 101026960644, merge_group on
    gh-readonly-queue/main/pr-15284-dc46c4ec1, head f502898a49530a1c85e58f3c4d2b340c0e1cb909,
    2026-09-04T12:43:16Z) and printed, verbatim:

    merge group on refs/heads/main — 1 commit(s) in range
      ℹ️  generated-surface exception (#11705) LIFTED skills/objectstack-ui/references/react-blocks.md on f502898a4953: byte-equal to `pnpm --filter @objectstack/spec gen:react-blocks` recomputed on this tree — the generator declared 1 output(s), this path among them, and its own `check:react-blocks` reported no drift across all of them (no stored baseline consulted)
    Governed Surface Queue Guard — merge_group — 0 governed pull request(s), 0 unattributed governed commit(s), 0 API read(s) (PR head + reviews).
      ✅  CLEAR — the diff touches no governed surface, so this guard has nothing to judge.
          Derived from GOVERNED_SURFACES in scripts/pm/check-governed-merges.mjs (5 surfaces),
          never from a restated list. ⛔ ZERO review lookups were made: the path test runs first and returns,
          so a GitHub API outage can never block a diff that touches nothing governed.
    

    The diff's single skills/** path — skills/objectstack-ui/references/react-blocks.md — matches
    the spec-react-blocks row of GENERATED_SURFACE_EXCEPTIONS (ruling #11705). Its provenance was
    recomputed on that tree, certified byte-exact and LIFTED; after that no governed path remained and
    the mixed-diff rule had nothing to fire on. The hunk corroborates it: one table row whose
    description column derives from the grouping .describe() that same PR edited in
    packages/spec/src/ui/view.zod.ts, truncated by the generator.

    Why the four existing mixed-diff assertions did not "cover" this: they do. They assert that a
    single live governed hit governs the whole PR. This hit was not live at verdict time, and the
    certified-regeneration case was already pinned as well. No predicate is patched.

    Reproduced live on today's tree with #15284's real 11-path file list through the seat-side
    predicate — node scripts/pm/check-governed-merges.mjs --test … → exit 0, NOT governed, with the
    same #11705 PURE REGENERATION line. The seat-side tool, the queue leg and the register agree.

    What actually failed: three report-side readings

    1. check-governed-queue-guard.mjs asserted "the diff touches no governed surface" and "the path
      test runs first and returns" one line under its own LIFTED note. Both false for that run.
    2. check-governed-merges.mjs renderTestVerdict counts the POST-lift set — "0 of 11 path(s) hit
      the register", printed directly above the exception line naming the hit.
    3. The sweep classifies with governedPathsIn alone and never consults the register
      (deliberately — provenance is a recompute against the tree a commit landed on, and the sweep
      holds no such tree), so its row for a certified regeneration is indistinguishable from a row for
      a hand-authored governed merge. That is the leg that produced this card.

    PR #15650 (draft) fixes all three, report-only: no predicate, verdict, exit code, API cost or
    listing changes, and the zero-cost clear keeps its wording byte-for-byte on both legs.

    Timeline facts for #15284 (reported, not judged)

    when (UTC) event actor
    11:37:28Z last commit 49f19218b — chore(spec): regenerate api-surface / export-origins / references … os-justin
    11:56:24Z, 12:40:51Z Governed Surface Queue Guard on the PR head (pull_request early warning) — both success —
    12:40:46Z ready_for_review os-justin
    12:41:02Z auto_merge_enabled os-justin
    12:42:18Z added_to_merge_queue os-justin
    12:43:16Z queue guard on the merge group — CLEAR, 0 API reads, react-blocks.md LIFTED —
    13:08:11Z merged as f502898a4 os-justin
    13:08:11Z removed_from_merge_queue github-merge-queue[bot]
    • Reviews: none. The timeline carries zero reviewed events of any state — no APPROVED, no
      CHANGES_REQUESTED, no DISMISSED, by any account. The guard needed none: with the only governed
      path lifted it returned before any review lookup existed (0 API read(s)).
    • No late push. The skills/** file entered the diff at 49f19218b (11:37:28Z), 65 minutes
      before the enqueue — the classic post-guard-push bypass is ruled out.
    • Not added: the optional report-only approval column. check-governed-merges.mjs reads only
      /pulls/{n} for merged_by/merged_at (fetchPullAttribution), so it would be a new API
      surface, which the dispatch forbids.

    The governance ruling half stays open for the project director seat (#12708); this comment and
    PR #15650 take no position on it.


    Generated by Claude Code

  5. claude commented on Sep 5, 2026

    @claude
    Contributor

    Mechanism half LANDED — PM seat domain:devx @ objectstack (#6023), session session_012zGPuVVX3deAx9LdjK8jCk.

    PR #15650 (Part of #15406) merged 2026-09-05T02:49:06Z as a55efc6c1 on main (squash, via the merge queue). Probed on re-fetched origin/main:

    scripts/pm/check-governed-queue-guard.mjs:959   export function liftedPathsBetween(before, after) {
    scripts/pm/check-governed-merges.mjs:2150       export function registerCell(entry) {
    scripts/pm/check-governed-merges.mjs:1186       (liftedCount > 0 ? ` after ${liftedCount} generated-artifact lift(s)` : '') +
    

    What this seat's half established, for the ruling half: the mixed-diff diversion FIRED on #15284's merge group (job 101026960644), its one skills/** path was the register's spec-react-blocks row, the recompute certified it byte-exact and LIFTED it, and the landing cleared with zero approvals and zero API reads exactly as the 2026-09-01 ruling provides. The predicate did not fail; three report-side readings did, and those are now fixed (report-only, verdicts/exit codes/API cost unchanged). Timeline facts and the two open governance questions (sweep-side recompute A/B/C — C shipped; whether the 2026-09-04 × 2026-09-01 ruling intersection is the intended regime) are in the PR body and the dev's report on this card.

    State transition: this seat's work on the card is complete; the remainder is the governance ruling, which belongs to the project director seat (#12708). pm:dispatched → pm:awaiting-maintainer in one label write; assignee released. The card stays open.


    Generated by Claude Code

  6. huangyiirene commented on Sep 9, 2026

    @huangyiirene
    Collaborator

    出口核验:⛔ 本卡不欠任何人工动作 —— 前提已证伪,剩下的是治理裁决。pm:awaiting-maintainer → needs-user-decision

    维护者 2026-09-09 指示「先处理 A 桶(真·只有你的手能做的)」,本卡被列在该桶内逐张核验。核验结论:它不属于那个桶。

    卡面自陈的第一件事已经做了,答案是「没有批准记录,而且不需要」

    本卡正文逐字:

    ⛔ It does not check whether an authorized approval exists on #15284 … Triage has not looked. That is the first thing the director seat should read, and it may end this card.

    独立复核(本会话,pull_request_read: get_reviews on PR #15284):返回空数组,零条 review,与 dev 报告 5548519947 的时间线读数(timeline 无任何 reviewed 事件)一致。

    ⇒ 但这不构成违规,因为守卫压根不需要 review:dev 已在合并组日志(job 101026960644)里逐字取到 —— 该 PR 唯一的 skills/** 路径 skills/objectstack-ui/references/react-blocks.md 命中 GENERATED_SURFACE_EXCEPTIONS 的 spec-react-blocks 行(裁决 #11705),在那棵树上重算、认证 byte-exact 并被 LIFTED;此后无受管路径残留,混合 diff 规则无物可触发。守卫返回 0 API read(s),正是 2026-09-01 裁决所规定的行为。

    ⇒ 「混合 diff 转向未触发」这个前提是假的。它触发了、求值了、并合法地判定无需分叉。 机制半边(三处 report-side 误读)已随 PR #15650 于 2026-09-05 落地。

    因此本卡剩下的是两问,⛔ 都是判断不是动作

    问一 —— 治理口径:2026-09-04 裁决(批准记录不再钉在 head sha)× 2026-09-01 裁决(认证过的纯重生成零批准即可放行)的交集,是不是你要的制度?#15284 在这个交集里以零 review 落地,形式上完全合规。若你认为「受管路径即使被 lift 也应留下一条人工痕迹」,那要收窄的是 2026-09-01 那条裁决,⛔ 不是这次落地。

    问二 —— 审计花费(dev 的 open question,C 已实施):事后审计 sweep 要不要应用生成物登记表?

    • A sweep 端重算来源:检出每个已合并 commit 的树、在那里跑该行的生成器。能真正回答问题,代价是每仓每个受管行一次检出加一次生成器运行,横跨五个仓,并让一份 report-only 审计依赖每个仓都有可用工具链。
    • B 读该次落地自己的 queue-guard check-run 结论并抄在行上。便宜且真实,但是新 API 面,且维护者直接合并根本不产生 merge_group 运行 ⇒ 恰恰在最该审视的地方这一列是空的。
    • C(已实施) 只把登记表行标为候选、声明本 sweep 不重算、指向 queue-guard 日志。零新机制、零新 API,行照列照计。

    ⇒ 只有当你发现自己在反复手工核这些行时,A 才值它的代价。

    状态转换(本笔)

    pm:awaiting-maintainer → needs-user-decision(SKILL.md:110/:126:决定待做 ≠ 决定已做只剩人工动作;needs-user-decision 与 pm:* 不并存)。domain:devx、finding、priority:p2 留下。

    ⚠️ 本卡是刚立的 #17017 的第 N 个实例:pm:awaiting-maintainer 有语义契约、零机器载体,于是「等判断」被写成了「等人工动作」,而没有任何谓词能发现。⛔ 本笔 ⛔ 不回填其余存量。


    Generated by Claude Code

  7. os-bill commented on Sep 9, 2026

    @os-bill
    Collaborator

    维护者速读

    事情:一条审计行说 PR #15284 带着一个 skills/** 文件、由非批准账户经合并队列落地。复核结果:那个文件是生成物(gen:react-blocks 重生成,与生成器输出逐字节一致),队列守卫在合并组上实际跑了、认证了,按 2026-09-01 裁决把它「抬走」(lift),剩下的 diff 无受管路径,零批准落地完全合规(合并组日志 job 101026960644)。机制侧的三处报告误读已随 PR #15650 修好。前提「混合 diff 转向未触发」已证伪。剩下两问,都是判断:

    • 问一(制度口径):2026-09-04 裁决(批准不钉 head)× 2026-09-01 裁决(认证过的纯重生成零批准放行)的交集——受管路径被 lift 后不留任何人工痕迹——是不是你要的制度?
    • 问二(审计花费):事后审计 sweep 要不要对生成物登记表重算来源?A 每次检出重跑生成器(能真正回答,但每仓每行一次检出加生成器运行、依赖五仓工具链);B 读那次落地的 queue-guard 结论抄在行上(便宜,但人工直合不产生 merge_group 运行,恰在最该看的地方为空);C(已实施)只在行上标「生成物候选」,把问题留给读者。

    选项:A(推荐) 制度维持原样(问一:是;问二:C 已实施),本卡关 completed。B 收窄 2026-09-01 裁决:被 lift 的受管路径仍须一条人工痕迹(批准账户的一次 review 或人工合并)——代价是每个纯重生成 PR 都排队等人。C 问二改走 sweep 端重算(原 A)。

    你要做的:回一个字母,A / B / C。

    • ① 项目长远合理性:A 缩小特例——「字节一致的重生成 = 非人工内容」在守卫处判一次,审计只提示不重判;B 给机器已证明的事再加一道人手,制度增生。
    • ② 实际业务拉动:零事故——该行落地内容与生成器输出逐字节相同,无人受影响;问二的重算方案跨五仓工具链,零拉动。
    • ③ 防 AI 犯错:守卫在合并组上响亮判定并留日志;真正的盲区是人工直合无 merge_group 运行 ⇒ 审计读不到结论——C 已如实标为「候选,非结论」,不装干净。
    • ④ 创业阶段不扩散:A 零新增;B 把纯重生成排进人工队列;C 加一个跨仓重算面。
      推荐 A(回退 B)。置信缺口:人工直合路径上的 lift 事实上不可被事后重验,C 的标注只提示不证明。

    裁后执行

    • A ⇒ 关 completed,摘 needs-user-decision;finding 同笔摘(已定级 p2)。
    • B ⇒ 立 skills 卡收窄 2026-09-01 裁决文本(受管面,人合)。
    • C ⇒ 立 skills 卡改 check-governed-merges 为 sweep 端重算。

    总监席第 20 场(session_01Tep4AYXZvyBA7jsvne5KZV)按决策箱勤务补齐四棱块与速读,2026-09-09T05:0xZ;⛔ 非裁决。


    Generated by Claude Code

  8. os-bill commented on Sep 9, 2026

    @os-bill
    Collaborator

    Ruling recorded — A: the governed regime stands as the two rulings intersect; the audit stays report-only with the candidate marker; card closes (director seat, summon #20, decision batch #106 item 4, 2026-09-09T05:1xZ)

    Provenance (who / verbatim / where): maintainer, live PM chat with this seat (session_01Tep4AYXZvyBA7jsvne5KZV, os-bill), 2026-09-09T05:0xZ, replying to batch #106 in which this card was item 4 with the four-facet block and 速读 at 5595794726 recommending A. Reply, verbatim: 「#106 同意」 — item 4 = A.

    Ruled. Q1 — the intersection of the 2026-09-04 ruling (an authorized approval record releases the queue without pinning the head) and the 2026-09-01 ruling (a byte-exact regeneration certified by the queue guard is lifted with zero approvals) is the intended regime: a lifted generated path leaves no human trace, by design (B refused). Q2 — C stands (the sweep marks generated-artifact candidates and does not recompute provenance; shipped in PR #15650); sweep-side recompute refused. PR #15284's landing was compliant (queue-guard job 101026960644: lift certified byte-exact, no governed path remained); nothing is rolled back.

    State, one write: closed completed; needs-user-decision and finding removed; priority:p2 · domain:devx kept.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions