Skip to content

[Decision] The authz census pins red main after a green merge, for the third time in ten days: run the static census files on PR and merge queue, make them a required local command, or derive the counts #26410

Closed

Description

@objectstack-fleet

Ruled: 6433001130 · letter C only (re-ruled from A + C, 6432893116) · 2026-10-27T03:27Z

Filing gate ②: a maintainer-only decision. Option 1 adds a CI lane, which is a new gate (「新增门禁默认否」), and narrows the #24073 / #22653 ruling that keeps the dogfood legs off PR and merge-queue runs. The question was put on #26400 by domain:spec seat 1 (comment 6432031749), answering @os-zhuang's 「这种数字意义大吗?如何避免类似的问题。」. Maintainer, 2026-10-27: 「需要我决裁的问题,立决策卡」. Filed by the triage seat (session_01AavokzJ5DndAwitDXvKy4U, seat post #6015). ⛔ Not a claim.

维护者速读

packages/qa/dogfood 里有两份权限普查测试,按条数钉住路由账本和 rest-server.ts 的注册点数。只要有人新增一条路由,就得同步改这两个数。但这两份测试只在 main 的 push 和定时任务里跑,PR 和合并队列都不跑,所以 PR 绿着合进去,main 才变红。10 天里第三次:#24057、#25988、#26361(这次红了 main 约 2.5 小时,p0 #26400,修复是 PR #26406)。请裁:A 加一条只跑这几份静态普查文件的 PR 和合并队列检查,几秒钟,只在改了路由文件时触发——这是新增门禁;B 不加 CI,让 dispatch-gates 把它们列为本地必跑命令,开发报告必须写已跑;C 把裸数字改成「从账本推导,只有未分类的路由才红」,纯数字变动不再红。选 A / B / C?可以 A+C。

Premises (measured)

Options

Option What Consequence Workload
A A PR and merge-queue job that runs only the static census files, path-triggered (packages/rest/src/**, packages/runtime/src/domains/**, packages/qa/dogfood/test/authz-*). The heavy dogfood legs stay off PRs (#24073 stands). The red lands on the author's PR, in seconds. One more CI job, but only on those paths. devx · 1 PR, Tier H (.github/workflows/**) · plus one required-context decision: advisory or required
B dispatch-gates derives the census files as required local commands for those paths, and the seat's ACCEPT checks the dev report shows them run. No CI cost. It depends on every dev and seat. The queue still cannot catch a miss, and P3 shows the warning was missed. skills/devx · 1 PR (scripts/pm/**)
C The census derives its population from the ledger and goes red only on a route that has no classification (reachable / blindSpot). Bump-only reds (#25988 was a docblock {@link}) disappear. A real new route is still caught only after merge, unless A or B is also chosen. devx · 1 larger PR (census rework)

Recommendation

A + C. A puts the check where the change is made. It runs in seconds and only on route files, so it is the narrowest gate that stops the class. C then makes the check measure the right thing: whether a new route has been classified, not how many routes there are. B alone would rely on the same local warning that P3 shows was missed. Because A is a new gate, it needs your explicit yes; without that, B + C is the fallback.

os-decision-facets
① 项目长远合理性:A+C 把一个「事后才红」的检查前移到 PR 上,并把裸计数改成按账本推导、看是否分类;不扩大 #24073 的范围,重型 dogfood 仍不上 PR。
② 实际业务拉动:10 天 3 次 main 变红,这次约 2.5 小时,期间发版被拒、每个带 ! 的 PR 报告里都多出 10 个红。
③ 防 AI 犯错:A 在作者的 PR 上直接拒绝,响亮失败;B 依赖开发和席位记得跑,P3 证明这个提醒已经被漏过。
④ 创业阶段不扩散:A 是新门禁(默认否),只按路径触发、只跑几秒;C 是重写已有测试,不新增键。
Prior rulings read: dogfood PR merge_group skip · authz census → #24073 (closed), #22653; 「新增门禁默认否」; 「平台测试清单反复变红,肯定要修啊」; ADR none; thread: #26400 (6432031749)

After the ruling

domain:devx dispatches the chosen letters. A is Tier H (.github/workflows/**), and the maintainer approves it at landing.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Brief-claimed-by: session_01KrKXQVvgYk2AJ4VkqMobyb · batch #406 · 2026-10-27T02:57Z

    Director seat, summon #51 continuation (ledger objectstack#12708). Presented to the maintainer in batch #406 as item 1 of 1. Seat increment (re-verified on origin/main e677770a; the card is not restated):

  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #406 item 1 · letters A + C · maintainer 「同意」 2026-10-27T03:18Z

    Recorded by the director seat (summon #51 continuation, session_01KrKXQVvgYk2AJ4VkqMobyb, ledger objectstack#12708). The maintainer answered batch #406 with 「同意」 — the seat letters. Brief 6432627947. A + C, and the maintainer's yes is the explicit flip of 「新增门禁默认否」 for this one check:

    • A — the static authz census runs on the PR and in the merge queue, as a filter-gated step inside an existing required context, not as a new job. Trigger paths: packages/rest/src/**, packages/runtime/src/domains/**, packages/qa/dogfood/test/authz-*. The file-reading census (authz-probe-blind-spot.test.ts) belongs in Lint & Repo Gates; the one that imports @objectstack/verify (authz-conformance.test.ts) in Test Core, where that closure is already built — the lane picks the exact job and says so in the PR body. ⛔ Not a new job with its own paths: (it could never be enrolled as a required context: check-required-contexts.mjs:265–275), and ⛔ no change to the three heavy legs' if: — dispatch-gates lists Dogfood Regression Gate as "scheduled BY YOUR PATHS" for a route-ledger.ts change, but its if: skips pull_request and merge_group, so neither PR CI nor the derived commands run the dogfood pins (main red after #24009) #24073 stands. The red lands on the author's PR.
    • C — the census derives its population from the route ledger and goes red only on a route with no classification (reachable / blindSpot); a bump-only change (a docblock {@link}, a reordered registration) no longer reds anything.
    • Not B alone: the same local warning (dispatch-gates.mjs:11522) was missed three times; B's local command may ride along in C's PR if the lane finds it free, but it is not the gate.

    Workload (card columns): A devx · 1 PR, Tier H (.github/workflows/ci.yml; lands by the maintainer's approval) · size S; C devx · 1 larger PR on the two census files (150 + 2,050 lines read) · size M; no measured precedent for either. Order: C may land first or together; A's step runs whatever census shape exists on its head. The in-flight fix PR #26406 (#26400, p0) is not displaced by this ruling.

    Execution: needs-user-decision → pm:queue in this act (domain:devx, p1, area:devpath); pm:awaiting-maintainer removed in the same stroke. The devx seat dispatches two cards or two PRs under this card, each citing Ruling-ref: this comment. Clause-②: no, Metadata-protocol: none.

  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #406 item 1 · re-ruled A + C → C only · maintainer 「c」 2026-10-27T03:27Z

    Recorded by the director seat (summon #51 continuation, session_01KrKXQVvgYk2AJ4VkqMobyb, ledger objectstack#12708). After the 「同意」 that recorded A + C (6432893116) the maintainer asked 「这个测试增加的耗时划算吗?这个是必要测试吗?」; the seat measured and answered, then the maintainer wrote 「c」. This re-rules the card to C only; A is withdrawn and 「新增门禁默认否」 stands unflipped — no census step runs on PRs or in the merge queue.

    What the measurement showed (the seat's reading, for the lane):

    C, concretely: the census derives its population from the route ledger; the hand-written census table and the count pin go (the cheapest form of C — derive what authz-conformance.test.ts needs instead of pinning a transcription of it), so no author edits a 1,670-line table to add a route, and a bump-only change (a docblock {@link}, a reordered registration) reds nothing. The discover() ratchet keeps refusing an unclassified route on main's push and scheduled runs, as today (#24073 stands). The lane re-reads the other readers of the census path (rest-route-ledger.ts, route-ledger.ts, rest-meta-auth.test.ts, dispatch-gates.mjs) before deleting; a reader that needs the table rather than a comment pointer is reported, not forced.

    Workload: devx · 1 PR · the two census files and the table (150 + 2,050 + 1,670 lines read) · size M · no measured precedent. Not Tier H unless dispatch-gates.mjs wording moves (scripts/pm/** is a seat-protocol surface; the lane declares it). Clause-②: no, Metadata-protocol: none.

    Execution: the card stays pm:queue (devx p1); the devx seat dispatches one card thread for C and ⛔ none for A. If a real UNCLASSIFIED red ever lands on main, a new card is filed then with the count. Ruling-ref: names this comment; 6432893116 is superseded for A.

  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 10 · 2026-10-27T04:22Z
    Session: session_01Q4MDXRbEJCNdPAP4SiXwp9 (devx seat 2) · card thread cmsg_01FdL1XeUyvVNxLreh3F4Qi99G8ApwiZzLyCouRQisBjZd
    Account: os-steve
    Branch: claude/project-thread-4g1xrr (the harness-pinned branch of the card thread; it names no issue, so this claim is the identity record; amended on spawn)
    Worktree: objectstack-issue-26410
    Domain: domain:devx
    Seat: domain:devx#2 (seat post #20163)
    File surface: packages/qa/dogfood/test/authz-probe-blind-spot.test.ts and authz-probe-blind-spot.census.ts (the 1,670-line hand table and its count pin go; the census derives its population from the route ledger), authz-conformance.test.ts only as far as it must read the derived set; readers re-read first: rest-route-ledger.ts, route-ledger.ts, rest-meta-auth.test.ts, scripts/pm/dispatch-gates.mjs (a reader that needs the table is reported, not forced). ⛔ Ruling C only: no new CI lane, no census step on PRs or the merge queue, discover()'s UNCLASSIFIED/STALE ratchet untouched. ⛔ scripts/pm/** wording moves make the PR Tier H: draft until a GOVERNED_APPROVERS approval · Amended on the thread's measurement (#26361's red was also the #17111 docblock pin, "docblock says 80 rows, the table holds 81", fixed in #26406): also packages/qa/dogfood/test/authz-conformance.matrix.ts (the docblock drops the two ledgers' "N rows", keeps the family/domain counts) and the #17111 section of authz-conformance.test.ts (pins the group counts only; the row-count doctoring case goes); comment pointers in rest-route-ledger.ts:134, route-ledger.ts:186, rest-meta-auth.test.ts:81, authz-conformance.test.ts:204 repointed to the census at 67461403. scripts/pm/dispatch-gates.mjs and its self-test untouched (path-only history and fixtures), so not Tier H. Open draft #26337 (another project, ADR-0142 phase 2) also edits authz-conformance.matrix.ts and route-ledger.ts: whichever lands second merges main
    Container & model: M, mode:thread, model: default tier (TIER_DEFAULT, from dispatch-gates --tier: no path-derived mandate), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — decision card, ruling C only
    Thread-read: 6433001130
    Ruling-ref: 6433001130 (supersedes 6432893116 for A)
    Premise: the three main reds (#24057, #25988, #26361 → #26400) were all the blind-spot count pin, none the discover() gate (the ruling's reading; the dev re-reads on origin/main)
    Serial constraints cleared: no in-flight PR of this seat touches packages/qa/dogfood/**


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26410,
      "status": "done",
      "branch": "claude/project-thread-4g1xrr",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26491",
      "session": "session_01ADHkmPfdxeQ7cdMHou5dY1",
      "premise_still_valid": false,
      "summary": "Ruling C landed as one draft PR. authz-probe-blind-spot.census.ts (1,691 lines) is deleted; authz-probe-blind-spot.test.ts derives population (imported ledger tables) and reach (the ledger probes' own scoped text read) and reds only on a ledger row the probes cannot name, plus derived header/kind checks and presence-only TRIPWIRE controls. Premise partly false: #26361's red also hit the #17111 docblock row-count pin in authz-conformance.test.ts, so (seat-approved scope extension) the matrix docblock now states only family/domain counts and the pin holds only those. discover() UNCLASSIFIED/STALE ratchet, baseline, matrix rows and CI untouched; no scripts/pm wording moved (not Tier H).",
      "tests": "head bd9b1ea5b0: pnpm --filter @objectstack/dogfood exec vitest run test/authz-probe-blind-spot.test.ts test/authz-conformance.test.ts under os-verify-lock: before (67461403) Test Files 2 passed, Tests 108 passed; after Test Files 2 passed, Tests 70 passed, VERDICT command-exit 0. Controls via scripts/ablation-replace.mjs on REST_ROUTE_LEDGER, each restored blob == HEAD b6dd2271294b: positive (row in existing family approvals) 70/70 green, nothing to edit; negative (new family zz-unclassified-probe) discover() UNCLASSIFIED rest-family:rest-route-ledger.ts:zz-unclassified-probe, 11 failed; negative (family 'approv' + 'als') the probe reads EVERY row reds, 12 failed. pnpm --filter @objectstack/dogfood typecheck exit 0.",
      "gates": "dispatch-gates --commands on bd9b1ea5b0: 56 derived, 56 exit 0 (2 first-pass exit-3 prerequisites cleared by unshallow + turbo build of packages/**, then exit 0); --ran: 56 derived famil(ies) accounted for, 56 run, 0 NOT-MEASURED (DERIVED zero). Roster families under packages/: check:authz-resolver, check:error-code-casing, check:filter-alias-parity exit 0. PR check-runs: in_progress at report time.",
      "line_budget": "7 files, +227 / -1870 (2097 changed, under 3000)",
      "deviations": [
        "Scope extended in place to authz-conformance.matrix.ts docblock and the #17111 section of authz-conformance.test.ts (seat amended claim file surface).",
        "Comment pointers re-pointed in packages/rest/src/rest-route-ledger.ts, packages/runtime/src/route-ledger.ts, packages/rest/src/rest-meta-auth.test.ts (comment-only).",
        "@objectstack/rest and @objectstack/runtime test/typecheck not run locally (comment-only diff); declared to Test Core.",
        "Reviewer request on the PR not made: it is an MCP GitHub write, which the dispatch order forbids."
      ],
      "files_changed": [
        "packages/qa/dogfood/test/authz-probe-blind-spot.census.ts (deleted)",
        "packages/qa/dogfood/test/authz-probe-blind-spot.test.ts",
        "packages/qa/dogfood/test/authz-conformance.test.ts",
        "packages/qa/dogfood/test/authz-conformance.matrix.ts",
        "packages/rest/src/rest-route-ledger.ts",
        "packages/runtime/src/route-ledger.ts",
        "packages/rest/src/rest-meta-auth.test.ts"
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "5 — issue_read x2, search_pull_requests x1, pull_request_read x1 (get), all reads",
      "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/dispatches, run 40453207242) and this os-dev-report comment (relay comment); plus git push (not REST)",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — the ledger probe pattern family: '([^']+)' mints a phantom key from a concatenated literal ('approv' + 'als' mints approv); caught by UNCLASSIFIED and the new row check, so a note only",
        "carrier: none · noted, not filed — rest-server-registrar-files.ts header still says each reader pins the list length; the derived check walks the list instead"
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    devx seat 2 · released: PR #26491 (Fixes #26410, Ruling-ref: 6433001130) merged as 98c02577. Its +/- lines on main match the reviewed head bd9b1ea5 in all 7 files. Ruling C is done:

    • The 1,691-line census table is deleted.
    • The reach check derives from the route ledgers and pins no count.
    • The matrix docblock states family and domain counts only, so a route added inside an existing family moves nothing.
    • discover()'s ratchet, the baseline and every CI lane are unchanged.
      These files first run in CI on main's next push or scheduled Dogfood Regression Gate; the seat reads that run. pm:dispatched comes off.

    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

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:devxpriority:p1High: required for production / M2teststooling

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions