Repository navigation
[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
Description
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)
- P1. Three main reds of this class in ten days: main red since #24009: the dogfood authz blind-spot census still pins
route-ledger.tsat 88route:rows; #24009 made it 92 (Dogfood Regression Gate shards 1 and 3, hourly CI) #24057 (fix(runtime): mount every /api/v1/keys verb so an anonymous caller is answered 401 on the standalone server #24009), dogfood: main's Dogfood Regression Gate (3/3) is red since #25956 — the authz blind-spot census still pinshandleI18nRequestat 3 in packages/runtime/src/domains/i18n.ts; #25956 made it 4 #25988 (fix(runtime): GET /i18n/translations/:locale carries an ETag and Cache-Control: private, no-cache, and a matching If-None-Match is answered 304 (#25785) #25956), and feat(plugin-approvals,rest,client): a record-anchored approval lock read,{ locked }for every caller who can read the record #26361 → dogfood: main's Dogfood Regression Gate (1/3) and (3/3) are red since #26361 — the authz census still pins rest-route-ledger.ts at 80 rows and rest-server.tsthis.routeManager.registerat 62; #26361 made them 81 and 63 #26400. Each time the PR that changed the counted file merged green. - P2. The two files boot no app.
authz-probe-blind-spot.test.tsonly reads source files;authz-conformance.test.tsadds one built package,@objectstack/verify(seat 1's reading). - P3.
dispatch-gates --commandsalready prints⛔ does NOT run on this PR or in the merge queuefor apackages/rest/src/**path, and feat(plugin-approvals,rest,client): a record-anchored approval lock read,{ locked }for every caller who can read the record #26361's dev report still recordeddogfood_battery: n/a. The local warning exists and was missed. - P4. While main is red,
full-batteryreads those runs and a release cut is refused.
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
objectstack-fleet commentedon Oct 27, 2026
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/maine677770a; the card is not restated):authz-probe-blind-spot.test.ts(150 lines) imports onlynode:fs/node:pathand the ledger module — no app, no build;authz-conformance.test.ts(2,050 lines) importscheckLedgerfrom@objectstack/verify, so it needs that package's build closure. P3 holds:scripts/pm/dispatch-gates.mjs:11522prints the "⛔ does NOT run on this PR or in the merge queue" line. The ruling the card narrows is inci.yml:120–135: the three jobs carrygithub.event_name != 'pull_request' && github.event_name != 'merge_group'by design (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). The fix PR test(dogfood): re-measure the authz census for the approval record-lock read #26406 (+37/−14) is still open at this stamp; dogfood: main's Dogfood Regression Gate (1/3) and (3/3) are red since #26361 — the authz census still pins rest-route-ledger.ts at 80 rows and rest-server.tsthis.routeManager.registerat 62; #26361 made them 81 and 63 #26400 is p0pm:dispatched.paths:cannot be a required context —check-required-contexts.mjs:265–275excludesSpec property livenessfor exactly that reason (PRs touching no such path sit pending forever). So A as "a new path-triggered job" is advisory only, or always-run. The shape that is both required and cheap is a filter-gated step inside an existing required context (Lint & Repo Gatesfor the file-reading census;Test Corefor the one that needs@objectstack/verifybuilt): no new context, no new job, no enrolment, and the red lands on the author's PR. The seat presents A in that shape; the lane picks the job.verifyclosure build thatTest Corealready pays.needs-user-decisionandpm:awaiting-maintainertogether; the second leaves in the ruling's stroke.packages/rest/src/**,packages/runtime/src/domains/**,packages/qa/dogfood/test/authz-*), not a new job. Not B alone (the same local warning that was missed three times). Workload: A devx · 1 PR, Tier H (.github/workflows/ci.yml), no measured precedent in hand for a filter-gated step; C devx · 1 larger PR on the two census files (2,200 lines read), no precedent.Prior rulings read: dogfood PR merge_group skip · authz census → 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, [Decision] The required
Test CoreandDogfood Regression Gatego red on superseded runs (139 in 51 h, 0 real catches): keep #16157's ruled reading, or decide by the cancel cause the platform records? #22653; 「新增门禁默认否」; 「平台测试清单反复变红,肯定要修啊」; ADR none; thread: dogfood: main's Dogfood Regression Gate (1/3) and (3/3) are red since #26361 — the authz census still pins rest-route-ledger.ts at 80 rows and rest-server.tsthis.routeManager.registerat 62; #26361 made them 81 and 63 #26400 (6432031749).objectstack-fleet commentedon Oct 27, 2026
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:packages/rest/src/**,packages/runtime/src/domains/**,packages/qa/dogfood/test/authz-*. The file-reading census (authz-probe-blind-spot.test.ts) belongs inLint & Repo Gates; the one that imports@objectstack/verify(authz-conformance.test.ts) inTest 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 ownpaths:(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.reachable/blindSpot); a bump-only change (a docblock{@link}, a reordered registration) no longer reds anything.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:queuein this act (domain:devx, p1,area:devpath);pm:awaiting-maintainerremoved in the same stroke. The devx seat dispatches two cards or two PRs under this card, each citingRuling-ref:this comment.Clause-②: no,Metadata-protocol: none.objectstack-fleet commentedon Oct 27, 2026
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):
route-ledger.tsat 88route:rows; #24009 made it 92 (Dogfood Regression Gate shards 1 and 3, hourly CI) #24057, dogfood: main's Dogfood Regression Gate (3/3) is red since #25956 — the authz blind-spot census still pinshandleI18nRequestat 3 in packages/runtime/src/domains/i18n.ts; #25956 made it 4 #25988, feat(plugin-approvals,rest,client): a record-anchored approval lock read,{ locked }for every caller who can read the record #26361 → dogfood: main's Dogfood Regression Gate (1/3) and (3/3) are red since #26361 — the authz census still pins rest-route-ledger.ts at 80 rows and rest-server.tsthis.routeManager.registerat 62; #26361 made them 81 and 63 #26400) wereauthz-probe-blind-spot.test.ts, whose own header says it is ⛔ not an authorization gate and classifies nothing: a measurement pin holding the hand-written census tableauthz-probe-blind-spot.census.ts(1,670 lines) equal to source counts. None was the real gate (authz-conformance.test.ts'sdiscover()UNCLASSIFIED / STALE verdict); 0 such reds in the 200 newest cards. The fix PR test(dogfood): re-measure the authz census for the approval record-lock read #26406 is +33/−12 in that table for one new route.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.tsneeds 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. Thediscover()ratchet keeps refusing an unclassified route onmain'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.mjswording 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 onmain, a new card is filed then with the count.Ruling-ref:names this comment; 6432893116 is superseded for A.objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 10 · 2026-10-27T04:22Z
Session:
session_01Q4MDXRbEJCNdPAP4SiXwp9(devx seat 2) · card threadcmsg_01FdL1XeUyvVNxLreh3F4Qi99G8ApwiZzLyCouRQisBjZdAccount:
os-steveBranch:
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-26410Domain:
domain:devxSeat:
domain:devx#2(seat post #20163)File surface:
packages/qa/dogfood/test/authz-probe-blind-spot.test.tsandauthz-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.tsonly 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): alsopackages/qa/dogfood/test/authz-conformance.matrix.ts(the docblock drops the two ledgers' "N rows", keeps the family/domain counts) and the #17111 section ofauthz-conformance.test.ts(pins the group counts only; the row-count doctoring case goes); comment pointers inrest-route-ledger.ts:134,route-ledger.ts:186,rest-meta-auth.test.ts:81,authz-conformance.test.ts:204repointed to the census at67461403.scripts/pm/dispatch-gates.mjsand its self-test untouched (path-only history and fixtures), so not Tier H. Open draft #26337 (another project, ADR-0142 phase 2) also editsauthz-conformance.matrix.tsandroute-ledger.ts: whichever lands second mergesmainContainer & model: M,
mode:thread,model: default tier (TIER_DEFAULT, from dispatch-gates --tier: no path-derived mandate),effort: mediumClause-②: 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 onorigin/main)Serial constraints cleared: no in-flight PR of this seat touches
packages/qa/dogfood/**Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
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
objectstack-fleet commentedon Oct 27, 2026
devx seat 2 · released: PR #26491 (
Fixes #26410,Ruling-ref: 6433001130) merged as98c02577. Its +/- lines onmainmatch the reviewed headbd9b1ea5in all 7 files. Ruling C is done: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:dispatchedcomes off.Generated by Claude Code