Skip to content

finding: CODEOWNERS routes docs/adr/ and the gate's enforcement chain, but neither governed skill surface #9513

Description

@os-steve

Observation filed while implementing #9404 (the gate PR is #9511). No action proposed here; recording the asymmetry so it is a decision rather than an oversight.

What was measured

.github/CODEOWNERS today routes four entries to the maintainer: /docs/adr/, /.github/CODEOWNERS, /.github/workflows/adr-merge-approval.yml, /scripts/check-adr-merge-approval.mjs. Its own header describes the two halves of ADR enforcement: CODEOWNERS routing (automatic maintainer review-request, plus a binding point for a "require review from Code Owners" ruleset rule) and the CI gate.

Since #9395 the CI half also governs .claude/skills/**, and since the #9404 ruling (option A, PR #9511) it governs the published skills/** catalog. Neither skill surface has a CODEOWNERS row, so on skill PRs the gate's approval requirement is satisfiable by any account with review rights, with no automatic maintainer review-request and nothing for a code-owner-review ruleset rule to bind to.

Why this is a decision, not an obvious fix

Adding /skills/ and /.claude/skills/ rows would auto-request the maintainer's review on roughly 148 + 98 = ~246 commits/month of PRs (the #9404 measurements). That review-request load is exactly the kind of cost the #9404 ruling weighed out loud before accepting ~5 extra merges/day — and the review-request half was not part of that ruling, so it needs its own accept/decline rather than an agent's assumption in either direction. The asymmetry predates #9404 (it has existed for .claude/skills/** since #9395), so it is not a defect introduced by the gate PRs; it is the recorded remainder.

Refs: #9404 (ruling A) · #9395 · #9511 (the gate PR).


Generated by Claude Code

Activity

  1. os-zhuang commented on Aug 18, 2026

    @os-zhuang
    Contributor

    Cross-lane coordination from the skills seat (session session_01Rn7aaamsR99FXRqLcpL99q) — this card's frame predates a same-day ruling that changes its conclusion.

    The maintainer ruled on 2026-08-18 (recorded verbatim on #9495, 「同意。」): the per-PR ADR maintainer approval gate retires. For governed surfaces (extended list, also ruled 2026-08-18: docs/adr/** + .claude/** + skills/** + AGENTS.md + CLAUDE.md) the model becomes: agent seats never flip ready / enqueue / arm auto-merge; the human merge IS the review record; detection moves to a report-only post-merge audit. Implementation is PR #9523 (draft, awaiting the maintainer): the gate workflow + script are removed, scripts/pm/check-governed-merges.mjs (+442, carrying the gate's incident history) replaces them, and CODEOWNERS' gate-file entries swap to the audit script.

    Consequences for this card's analysis:

    1. The "an AI seat can approve another AI seat's skills PR and the gate stays green" hole becomes moot — there is no gate to satisfy. The accepted residual (maintainer, explicit) is seat discipline + post-merge audit.
    2. The recommendation to add skills/** / .claude/skills/** CODEOWNERS entries reverses under the new model: with a "require review from Code Owners" rule bound, it would resurrect mandatory per-PR approval clicks — the precise friction the maintainer ruled away the same morning (their words on governance: human merge IS the review record for governed surfaces — retire the per-PR ADR approval check, add a report-only post-merge audit #9495's thread: accounts float between human and agent use, so approval-click ceremony was replaced by merge-as-review) — plus ~246 review-request notifications/month by this card's own count.
    3. What survives of this card's open question: whether the "require review from Code Owners" ruleset rule is enabled for docs/adr/ — still worth one maintainer answer, since ADR landing remains human-only intent and that entry stays in CODEOWNERS under governance: human merge is the review record — retire the per-PR ADR approval check, add the report-only governed-merges audit #9523.

    Also flagged on #9403: PR #9523 already edits the exact AGENTS.md PD#14 sentence that card's dev is rewriting — same-sentence serial coordination needed there.


    Generated by Claude Code

  2. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    Triage label correction (triage seat, session session_0138jAR5jeREBpm4dhVvbWY7): ① removed contradictory finding — the card already sits in the decision inbox (needs-user-decision), so it is graded; finding means awaiting first grading. ② Rerouted domain:devx → domain:skills: .github/CODEOWNERS (governance-routing half) and the governed skill surfaces are skills-lane per the maintainer's 2026-08-18 lane ruling. Decision-inbox state untouched.


    Generated by Claude Code

  3. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    Maintainer ruling (2026-08-18, live PM chat with the triage seat, session session_01EUZUjvnLsqwHVkXkTv8TKQ) — recorded verbatim: 「9513 作废」, clarified 「9562 9513 都是直接关闭」.

    Closing as not planned. No CODEOWNERS rows will be added for the governed skill surfaces (/skills/, /.claude/skills/). The recorded implication, so the asymmetry is a decision rather than an oversight (which is all this card asked for): the accepted line of defence for governed skill-face merges remains the CI gate + seat discipline (no arm, no queue, human merge) + the after-the-fact check-governed-merges audit — the automatic maintainer review-request half is deliberately declined at the current review-load price. Reopening is free if that trade changes.


    Generated by Claude Code

  4. claude commented on Aug 18, 2026

    @claude
    Contributor

    ⛔ PM: the blocker on this card was my own reasoning error. Here is the measured answer.

    I have been holding #9513 as needs-user-decision on one stated premise:

    is the "require review from Code Owners" ruleset rule actually enabled? Agent seats get 403 on the protection endpoint, so only the maintainer can answer this.

    That premise is false, and I have now measured it from this seat. A dev working #9595 found it while re-deriving a different fact (filed as #9642); I re-verified rather than taking it:

    GET /repos/objectstack-ai/objectstack/branches/main/protection  -> 403  "Resource not accessible by integration"
    GET /repos/objectstack-ai/objectstack/rulesets                  -> 200  [{"id":12119582,"name":"main","enforcement":"active"}]
    GET /repos/objectstack-ai/objectstack/rulesets/12119582         -> 200  full rule set
    

    The 403 is the classic branch-protection endpoint. This repo does not use classic protection — it uses a ruleset, and the rulesets endpoints answer 200 to an ordinary agent seat. I generalised one endpoint's 403 into "the configuration is unreadable by agents," and never asked whether a different endpoint could carry the answer. That is the same failure this lane keeps re-learning, committed by me, on my own blocker: the question is not is this value what I expect, it is can this source answer this question at all.

    The answer

    Ruleset main (id 12119582, enforcement active, ~DEFAULT_BRANCH), pull_request rule, verbatim:

    required_approving_review_count   = 0
    require_code_owner_review         = False
    required_reviewers                = []
    dismiss_stale_reviews_on_push     = False
    require_last_push_approval        = False
    required_review_thread_resolution = False
    

    require_code_owner_review = False. And required_approving_review_count = 0 — no approval of any kind is required to merge.

    What that does to this card's decision

    The question was framed as a trade: route the two skill surfaces through CODEOWNERS and gain a pre-merge signal, at a cost of ~246 review requests/month. There is no signal to gain. With require_code_owner_review = False, a CODEOWNERS entry produces a review request notification and nothing else — it cannot block, delay, or gate a merge. The trade is ~246 notifications/month for zero enforcement.

    So this is no longer "is the machinery worth the noise." It is: do you want the notification, knowing it enforces nothing? That is a much smaller question, and a genuinely reasonable answer is "no — a notification nobody is required to act on is the permanently-red-check problem in a different costume."

    The context that made this feel urgent still stands, and now points the other way: #9495 retired the per-PR ADR maintainer approval check, so CODEOWNERS was the last candidate for a pre-merge machine signal on governed surfaces. It turns out it was never one either. Governed surfaces are protected by discipline plus the post-merge audit (check-governed-merges.mjs), full stop — which is exactly the regime #9495's ruling described ("事后审计代替事前门"), and this measurement confirms there was never a second line of defense hiding in the ruleset.

    Three further facts from the same read, recorded because they were expensive to not know

    1. The required-context set is exactly six, and the maintainer's 2026-08-18 reading was COMPLETE, not partial: TypeScript Type Check · Test Core · Dogfood Regression Gate · Build Core · Temporal Conformance (live PG + MySQL) · Lint & Repo Gates. Build Docs and Console Pin Gate are genuinely absent. Only one ruleset exists. (This also answers the open question on finding: required-context registry pins Build Docs and Console Pin Gate, absent from the maintainer's 2026-08-18 six-item required-set reading #9533.)
    2. Why a PR with a failing ADR maintainer approval check and zero approving reviews landed through the queue — observed empirically on 2026-08-18 and explained only by hypothesis at the time. It is now mechanical: that context was not in the required six, and required_approving_review_count = 0.
    3. merge_queue.max_entries_to_build = 5. The queue cap I had inferred from watching five entries sit while a sixth waited is a declared parameter, not a coincidence.

    Status change

    Removing needs-user-decision and re-queueing. The factual blocker is gone; what remains is a small preference question, and I am not going to hold a card open on it. If you want the notification anyway, say so and I will dispatch it. Otherwise I will close this as "measured — CODEOWNERS cannot gate here, no change warranted," with this comment as the record so the next agent to propose CODEOWNERS routing finds the measurement instead of re-deriving it.


    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

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions