Skip to content

refactor!: rename the guarded maintenance system to autorelease - #21

Merged
loadinglucian merged 4 commits into
mainfrom
feat/autorelease-rename
Aug 2, 2026
Merged

refactor!: rename the guarded maintenance system to autorelease#21
loadinglucian merged 4 commits into
mainfrom
feat/autorelease-rename

Conversation

@loadinglucian

@loadinglucian loadinglucian commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Renames the "guarded maintenance" system to autorelease across every
directory, workflow, script, schema, control, and prose reference, and moves the
system documentation out of README.md into a dedicated AUTORELEASE.md.

No behaviour changes. Every rename is a git mv, so history follows the files.

Companion to Bigpixelrocket/php-bin PR on the same branch name.

Merge this one first

This repository reads php-bin's operator control by path, from two places:

  • a sparse checkout of .github/autorelease-operator.json
  • a gh api read of the same path from php-bin main

php-bin main still carries the pre-rename filename until its own PR lands, so
both read sites now try the new path and fall back to the old one. That makes
this PR safe to merge first, and php-bin's safe to merge straight after.

Once php-bin main has landed, a small follow-up removes the fallback. Both
call sites carry a comment saying so.

The gh api site decides between the two names with one directory listing
rather than a probe. A probe's non-zero exit cannot separate "the file is
absent" from "the API call failed", so a transient error would have selected
the legacy path and broken merge admission for an unrelated reason.

One behaviour change, deliberate

Review surfaced a template-injection weakness that predates this branch, and it
is fixed here rather than deferred.

action_key comes out of the model-authored implementation plan, and it was
being written into $GITHUB_OUTPUT and then expanded into four run: scripts
as a raw ${{ }} expression. GitHub substitutes those into script text before
the shell parses it, so shell quoting cannot contain a hostile value, and a
newline alone would let it set arbitrary step outputs. admit-autorelease-plan
already rejects a malformed action key, so this was not reachable in practice,
but the workflow no longer depends on that single upstream check: its alphabet
is asserted where it leaves the JSON, and every later use reads it from an
env: map.

The base SHA and PR number interpolations move to the same env: pattern so
the file has one idiom for values entering a script.

Verification

  • ./scripts/test.sh — passes
  • verify-autorelease-system — 21/21 checks pass at these exact commits
  • markdownlint — clean

GitHub-side migration

The MAINTENANCE_OWNER repository variable must be recreated as
AUTORELEASE_OWNER, and the maintenance label renamed to autorelease
(renamed via the API, not recreated, so existing issues keep it).

The full ordered runbook is in the php-bin PR description.

Summary by CodeRabbit

  • New Features

    • Introduced a deterministic autorelease workflow for tracking php-bin support-policy updates.
    • Added fallback handling for legacy policy locations when the primary source is unavailable.
    • Added structured plan validation and protected-path controls.
  • Documentation

    • Added comprehensive autorelease setup, controls, recovery, and verification documentation.
    • Updated repository and workflow guidance to use autorelease terminology.
  • Bug Fixes

    • Improved policy retrieval behavior by distinguishing missing resources from transport failures.
    • Added validation for merge actions before execution.

Rename every "guarded maintenance" identifier to "autorelease" across
directories, workflows, scripts, schemas, controls, and prose, and move the
system documentation out of README.md into a dedicated AUTORELEASE.md.

The consumer reads php-bin's operator control by path, both from a sparse
checkout and over the API. php-bin main still carries the pre-rename filename
until its own autorelease PR merges, so both read sites try the new path and
fall back to the old one. Remove that fallback once php-bin main has landed.

BREAKING CHANGE: the MAINTENANCE_OWNER repository variable must be recreated as
AUTORELEASE_OWNER, and the maintenance label renamed to autorelease, in the
same window as this merge. The workflow filename changes from
maintenance-consumer.yml to autorelease-consumer.yml, so any saved dispatch
link must be updated.
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 939cf679-7ba8-43f3-9e23-b767870fdc6f

📥 Commits

Reviewing files that changed from the base of the PR and between 7cd8b65 and b6b7e74.

📒 Files selected for processing (2)
  • .github/workflows/autorelease-consumer.yml
  • test/test_autorelease.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/test_autorelease.py
  • .github/workflows/autorelease-consumer.yml

📝 Walkthrough

Walkthrough

The PR migrates the PHP policy consumer from maintenance to autorelease terminology, paths, artifacts, workflows, controls, schemas, documentation, and tests. Existing admission, validation, digest, and readiness gates remain in place.

Changes

Autorelease migration

Layer / File(s) Summary
Autorelease contracts and phase rules
.github/codex/autorelease/*, schemas/autorelease-plan.schema.json
Adds autorelease phase instructions and a structured plan schema for evidence, paths, gates, budgets, and completion.
Investigation workflow migration
.github/workflows/autorelease-consumer.yml
Updates control loading, investigation contracts, prompts, plans, and artifacts to autorelease paths.
Implementation, sealing, and repair flow
.github/workflows/autorelease-consumer.yml
Renames implementation and repair artifacts, sealing commands, validation outputs, and retained check records.
Merge admission and readiness flow
.github/workflows/autorelease-consumer.yml
Uses autorelease validation artifacts, branches, policy captures, admission inputs, and readiness records.
Runtime paths and protected controls
.github/CODEOWNERS, .github/workflows/protected-controls.yml, autorelease/*, scripts/*, .gitignore
Updates ownership, protected paths, entry points, policy fetch fallback, error messages, package metadata, and ignored run directories.
Documentation, settings, and test alignment
AUTORELEASE.md, README.md, docs/*, test/test_autorelease.py, autorelease-events/.gitkeep
Documents autorelease operation and updates repository settings, state records, tests, and event storage.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PolicySnapshot
  participant AutoreleaseWorkflow
  participant CodexAgent
  participant Admission
  participant Validation
  PolicySnapshot->>AutoreleaseWorkflow: provide captured policy data
  AutoreleaseWorkflow->>CodexAgent: submit autorelease phase contract
  CodexAgent-->>AutoreleaseWorkflow: return plan or patch
  AutoreleaseWorkflow->>Admission: validate plan and sealed artifact
  Admission-->>AutoreleaseWorkflow: return admission result
  AutoreleaseWorkflow->>Validation: verify digest-matched patch
  Validation-->>AutoreleaseWorkflow: return checks and readiness data
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the primary change: renaming the guarded maintenance system to autorelease.
Description check ✅ Passed The description covers the migration scope, verification results, compatibility fallback, security fix, and required GitHub-side changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/autorelease-rename

Comment @coderabbitai help to get the list of available commands.

Comment thread autorelease/consumer.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
.github/workflows/protected-controls.yml (1)

52-52: 🩺 Stability & Availability | 🔵 Trivial

Verify the repository variable migration before merge.

PROTECTED_REVIEWER now comes only from vars.AUTORELEASE_OWNER. If the variable is missing, reviewer is empty and no review can satisfy approved. If it names a different login from the intended CODEOWNERS owner, that owner’s approval does not satisfy this gate. Recreate AUTORELEASE_OWNER with the exact login and verify it before relying on this workflow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/protected-controls.yml at line 52, Verify the repository
variable used by PROTECTED_REVIEWER in the workflow is configured as
AUTORELEASE_OWNER, exists, and contains the exact intended CODEOWNERS owner
login; recreate or correct the variable before merging and confirm the approved
gate resolves to that reviewer.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/autorelease-consumer.yml:
- Line 221: Update the affected run steps in the workflow, including the
commands around base_sha, PR metadata, and action_key, to pass each needs.* or
steps.* value through the step’s env map and reference the corresponding shell
variable with $VAR inside the script. Apply this consistently at all flagged
sites while preserving the existing command behavior and validation.
- Around line 466-472: Update the gh pr create invocation in the autorelease PR
creation flow to construct the --body value with actual newline characters
rather than literal \n sequences. Preserve the existing validated commit text
and blank line between the two sentences.

In `@AUTORELEASE.md`:
- Around line 7-10: Update the scheduled `php-bin policy consumer` description
in AUTORELEASE.md to state that `autorelease/consumer.py` compares all
policy-change fields from `support-snapshot.json`: the policy digest,
incomplete-event state, policyInvariantsDigest, phpBinPolicyCommit, and
maintainedBranches. Preserve the existing clarification that it does not fetch
or classify upstream PHP lifecycle data.

In `@autorelease/consumer.py`:
- Line 115: Update the policy-invariant fetch flow around pinned_policy_urls,
fetch_policy_set, and fetch_url to try autorelease/policy-invariants.json first,
then retry maintenance/policy-invariants.json only on a not-found response.
Preserve the successful response bytes and record the URL that supplied them,
and add coverage for both primary and fallback paths.

In `@test/test_autorelease.py`:
- Line 66: Update the protected-path assertion in the relevant autorelease test
to use .github/workflows/autorelease-consumer.yml instead of the old
autorelease.yml path, ensuring it validates the renamed consumer workflow.

---

Nitpick comments:
In @.github/workflows/protected-controls.yml:
- Line 52: Verify the repository variable used by PROTECTED_REVIEWER in the
workflow is configured as AUTORELEASE_OWNER, exists, and contains the exact
intended CODEOWNERS owner login; recreate or correct the variable before merging
and confirm the approved gate resolves to that reviewer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2fb305ce-b89b-4a10-a06e-a5714e7b23f2

📥 Commits

Reviewing files that changed from the base of the PR and between affc477 and 340ab17.

📒 Files selected for processing (23)
  • .github/CODEOWNERS
  • .github/codex/autorelease/implementation.md
  • .github/codex/autorelease/investigation.md
  • .github/codex/autorelease/repair.md
  • .github/codex/autorelease/shared.md
  • .github/workflows/autorelease-consumer.yml
  • .github/workflows/protected-controls.yml
  • .gitignore
  • AUTORELEASE.md
  • README.md
  • autorelease-events/.gitkeep
  • autorelease/__init__.py
  • autorelease/admission.py
  • autorelease/consumer.py
  • autorelease/protected-paths.json
  • docs/admin-state/mise-php-after.json
  • docs/repository-settings.md
  • schemas/autorelease-plan.schema.json
  • scripts/admit-autorelease-plan
  • scripts/consume-php-policy
  • scripts/seal-autorelease-patch
  • scripts/verify-merge-admission
  • test/test_autorelease.py

Comment thread .github/workflows/autorelease-consumer.yml Outdated
Comment thread .github/workflows/autorelease-consumer.yml
Comment thread AUTORELEASE.md Outdated
Comment thread autorelease/consumer.py Outdated
Comment thread test/test_autorelease.py Outdated
pinned_policy_urls returned only autorelease/policy-invariants.json, but
php-bin main keeps maintenance/policy-invariants.json until its own autorelease
change merges. Because this repository must merge first, every policy capture
in that window would have failed before compare or the operator pause could
run.

fetch_first_url tries the current path and falls through to the older one only
on a 404, so a transport failure still raises instead of silently reaching for
the older document. The capture record already reports which URL supplied the
bytes. Remove the fallback once php-bin main has landed.

AUTORELEASE.md said the consumer compares only the policy digest and
incomplete-event state; it also compares the invariants digest, the php-bin
policy commit, and the maintained branches.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1a9ab65. Configure here.

Comment thread .github/workflows/autorelease-consumer.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/test_autorelease.py`:
- Around line 108-109: Update the assertRaises call around
pinned_policy_urls("main") to expect ConsumerError instead of the broad
Exception type, preserving the test’s verification of the intended rejection
contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 736c6e12-b1cc-48e6-85a0-f6f2a10cf9c5

📥 Commits

Reviewing files that changed from the base of the PR and between 340ab17 and 1a9ab65.

📒 Files selected for processing (3)
  • AUTORELEASE.md
  • autorelease/consumer.py
  • test/test_autorelease.py

Comment thread test/test_autorelease.py Outdated
@loadinglucian

Copy link
Copy Markdown
Contributor Author

Review round 1 summary

Every finding was checked against the code before deciding. Pushed as 1a9ab65.

Fixed

Finding What changed
autorelease/consumer.py invariants path The important one, flagged independently by both Bugbot and CodeRabbit, and both were right. fetch_url retries the same URL and then raises, so this was a hard failure of every policy capture in the window between the two merges, not a degraded path. New fetch_first_url tries the current path and falls through to maintenance/policy-invariants.json only on a 404, so transport failures still raise. Tests cover the preferred path, the fallback, and the failure case.
AUTORELEASE.md policy comparison compare() triggers on policyDigest, policyInvariantsDigest, phpBinPolicyCommit and maintainedBranches, plus the incomplete event check. The text said only the digest and incomplete-event state.
test/test_autorelease.py protected path Was asserting on .github/workflows/autorelease.yml, a file that has never existed here. Now uses the real autorelease-consumer.yml.

Answered, no change needed

The AUTORELEASE_OWNER nitpick on protected-controls.yml:52 is right that an absent or mismatched variable makes the gate unsatisfiable. It is already step 1 of the migration runbook, before either merge, and the php-bin PR description now spells out that the value has to be the exact CODEOWNERS login rather than just present.

Declined, with reasons

Template injection in autorelease-consumer.yml. Identical to maintenance-consumer.yml on main, so the rename moved the pattern rather than introducing it. The reasoning is sound and the values are only safe today because of upstream validation that could be loosened later. Kept out so this PR stays a clean, revertible rename; tracked as a follow up with the matching ${{ inputs.* }} sites in php-bin.

Literal \n\n in the generated PR body. A real bug, and also present on main. Same follow up, and the printf form suggested is the fix that will be used.

Verification

./scripts/test.sh passes in both repos, verify-autorelease-system passes 21 of 21 at these commits, markdownlint is clean.

This PR still needs to merge before php-bin's.

The action key comes out of a model-authored plan. Admission already rejects a
malformed one, but the value crossed into $GITHUB_OUTPUT and four run scripts
as a raw ${{ }} expansion, which GitHub substitutes into script text ahead of
the shell. Its alphabet is now asserted at that boundary and every later use
reads it from an env map.

The base SHA and PR number interpolations move to the same env pattern so the
workflow has one idiom for values entering a script.
The merge-admission step probed for .github/autorelease-operator.json and fell
back to the pre-rename filename on any non-zero exit, so a transient API error
selected the legacy path. One directory listing now decides it, and anything
other than a definite answer fails the step.

Also tightens the pinned_policy_urls rejection test to ConsumerError, matching
the idiom the rest of the file already uses.
@loadinglucian

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Not chasing you, the automatic pass got dropped. The commit status on this head reads "Review rate limited" and has not moved since the push landed, so the latest commits have not been looked at yet. Requesting one now that the window should have cleared.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

@loadinglucian I will review the latest commits on this pull request.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@loadinglucian
loadinglucian merged commit 30a967d into main Aug 2, 2026
4 of 5 checks passed
@loadinglucian
loadinglucian deleted the feat/autorelease-rename branch August 2, 2026 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant