Skip to content

chore(norms): let the loop open host PRs, keep merging with the owner - #53

Merged
Alex1990 merged 1 commit into
mainfrom
norms/loop-host-prs
Sep 16, 2026
Merged

Alex1990 merged 1 commit into
mainfrom
norms/loop-host-prs

Conversation

@Alex1990

Copy link
Copy Markdown
Owner

What

Two halves of one change: the loop may be the maker of changes to its own host, and
the ruleset makes sure it still cannot be the one that merges them.

  • docs/agents/ops.md - a host change (scripts/loop/**) is no longer by itself a
    reason to route a task to needs-triage. The loop may open these PRs; the owner
    review is the checker. Review the diff, not the run log: the same PR can edit
    gh-check.mjs and the agent prompts. This supersedes the host-change routing
    recorded in the triage of The #50 pr author is wrong #52.
  • .github/CODEOWNERS (new) - * owned by the repository owner, plus explicit
    entries for /.github/ and /scripts/ as the GitHub docs recommend, so a PR
    cannot quietly shed the ownership it is subject to (CODEOWNERS is read from the
    base branch).
  • scripts/loop/README.md - ruleset payload and rationale updated for the two rules
    that were just switched on.

Ruleset change (applied through the API, cannot be a file change)

Main branch (id 21855851), read back from the API:

"required_approving_review_count": 1,
"require_code_owner_review": true,
"require_last_push_approval": true,
"bypass_actors": [{ "actor_id": 3141679, "actor_type": "User", "bypass_mode": "pull_request" }]

current_user_can_bypass reads back pull_requests_only, so the owner can still
merge. Why both switches exist:

  • the loop holds pull-requests: write, so without a code-owner requirement it could
    approve a PR it did not author (one the owner opened, or a dependabot PR) and then
    merge it with the Contents: write it needs for branch pushes;
  • require_last_push_approval stops a rewritten PR branch from being self-approved.

Net effect: the loop keeps the ability to change its own host, and nothing reaches
main without the owner approving it.

Note

Dependabot PRs are covered by * too, so they now need the owner approval as well
(the bypass still allows merging them without a second reviewer).

Verification

  • gh api repos/Alex1990/tiny-oss/rulesets/21855851 read back with both flags true
    and current_user_can_bypass: pull_requests_only.
  • CODEOWNERS syntax: gh api repos/Alex1990/tiny-oss/codeowners/errors reads the
    default branch, so it can only be checked after this lands.

The loop may now be the maker of changes to its own host (scripts/loop/**); the owner review is the checker, so a host change is no longer by itself a reason to route a task to needs-triage. The gate that keeps this honest is the ruleset, not the loop's restraint: the Main branch ruleset now carries require_code_owner_review and require_last_push_approval, and .github/CODEOWNERS owns '*' for the repository owner, so a bot approval cannot meet the review requirement.
@github-actions

Copy link
Copy Markdown
Contributor

Coverage

Metric % Covered / Total
Lines 90.19% 1003/1112
Statements 89.06% 1083/1216
Functions 91.03% 193/212
Branches 76.43% 519/679

@github-actions github-actions Bot added the needs-triage Maintainer needs to evaluate (loop can't decide; too risky; external PR) label Sep 16, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Loop triage — needs-triage (human-owned; the loop must not decide this one).

This PR is a norms-layer change (docs/agents/ops.md) plus loop-host documentation (scripts/loop/README.md) and a new .github/CODEOWNERS. It is authored by the repository owner. The loop must not be the maker or the checker for the norms/host it runs on (AGENTS.md; precedent #36/#37/#47/#49/#51/#52), and the change is already written — only your review/merge decision remains. Routing to the human inbox; the loop will not open, approve or merge anything for this task.

Verified read-only

  • gh pr view 53 → OPEN, headRefName: norms/loop-host-prs, baseRefName: main, author: Alex1990, mergeable: MERGEABLE, reviewDecision: REVIEW_REQUIRED, labels: [].
  • 3 files, +42/−3 (.github/CODEOWNERS new; docs/agents/ops.md +9; scripts/loop/README.md +14/−3), single commit 4fce6ec by Alex Chao; no loop-task: marker, so the router correctly sends this owner repo PR to triage, not pr-review.
  • gh api repos/Alex1990/tiny-oss/rulesets/21855851 → enforcement: active; the pull_request rule now carries required_approving_review_count: 1, require_code_owner_review: true, require_last_push_approval: true, dismiss_stale_reviews_on_push: true. The two flags this PR describes are live.
  • .github/CODEOWNERS is not on main yet (contents/.github/CODEOWNERS → 404) and codeowners/errors → 404, consistent with the PR's own note that the syntax check can only run after this lands.

Findings for the human (not blockers the loop may act on)

  1. The bypass actor could not be verified from inside the loop. With the job token the ruleset read-back is "bypass_actors": null and "current_user_can_bypass": "never". That is expected to be a permission artifact — the token has no administration scope, and the PR body reports the owner's PAT reading pull_requests_only. But it is exactly the failure mode scripts/loop/README.md warns about: since * is owned solely by @Alex1990, an owner-authored PR cannot receive a non-bypass code-owner approval (GitHub forbids self-approval), so this PR merges only if the bypass is real. Please confirm with an admin-scoped read (current_user_can_bypass == "pull_requests_only").
  2. Owner-authored PRs are now bypass-only by construction. With require_code_owner_review: true and a single code owner who is frequently the author, every owner-authored PR depends on the bypass; another collaborator's approval will not satisfy the code-owner rule. It is a deliberate consequence of the diff, but worth stating so it is not discovered later.
  3. This PR supersedes the host-change routing recorded in the triage of The #50 pr author is wrong #52, as its body says. That does not make it loop work: it changes the norms themselves, so it stays human-owned regardless of the new rule.

No ready-for-agent work exists.

@Alex1990
Alex1990 merged commit 6a57a66 into main Sep 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-triage Maintainer needs to evaluate (loop can't decide; too risky; external PR)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant