Skip to content

Document serialized release backport policy#4592

Open
justin808 wants to merge 28 commits into
mainfrom
codex/release-backport-policy
Open

Document serialized release backport policy#4592
justin808 wants to merge 28 commits into
mainfrom
codex/release-backport-policy

Conversation

@justin808

@justin808 justin808 commented Jul 12, 2026

Copy link
Copy Markdown
Member

Why

React on Rails release backports need a repo-specific operating rule that prevents independently merged main PRs from being combined into one release/X.Y.Z PR. The closed aggregate #4590 exposed that gap.

This policy intentionally lives in React on Rails rather than the portable agent-workflows pack: release trains and serialized backports are consumer-specific behavior, and React on Rails is currently the concrete consumer that needs it.

What changed

  • make one merged source PR per release PR the canonical React on Rails rule
  • require serial merge/refetch/branch sequencing against the current release tip
  • document squash-commit and true merge-commit cherry-pick forms
  • preserve each source PR's applicable changelog entry, then reconcile and stamp after the final accepted release set lands
  • document the narrow maintainer-approved inseparability exception
  • document explicit authority requirements for closing aggregate PRs and deleting their branches
  • add the rule to the release-train evaluation skill and release runbook

Process-gap disposition

Validation

  • release-train skill quick validation
  • .agents/bin/agent-workflow-seam-doctor
  • Prettier on all changed files
  • Lychee offline and pre-push online link checks
  • required OSS RuboCop: 234 files, no offenses
  • pre-commit and pre-push hooks
  • independent review and simplify passes: clean

The configured Codex review model was unavailable in the installed Codex version, so the required independent review fallback used Claude Opus 4.8 and every finding was resolved before the final clean pass.

Summary by CodeRabbit

  • Documentation
    • Added new guidance for evaluating backport “shape” for main → active release/X.Y.Z targets, including serialized one-source-at-a-time sequencing in a shared release-line order.
    • Updated workflow instructions to record serial order when multiple release/X.Y.Z targets are selected and apply the backport rules consistently.
    • Expanded runbook steps for backport preparation, including lane reuse vs dedicated backport lanes, refreshed validation before merges, and strict provenance/cherry-pick attribution requirements.
    • Clarified conflict handling, validation/QA/review checkpoints per backport source, and changelog/RC changelog reconciliation and re-audits.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Release-train evaluation rules and maintainer documentation now require serialized, lease-guarded one-source-PR backports, preserve cherry-pick provenance, define bundling exceptions, and add guarded promotion, recovery, and closeout procedures.

Changes

Release backport guidance

Layer / File(s) Summary
Evaluation workflow and backport shape rules
.agents/skills/react-on-rails-release-train-issue-evaluation/SKILL.md
Adds serialized backport-shape rules, release-tip validation, provenance requirements, changelog reconciliation, bundling constraints, and serial target reporting.
Lease and serialized backport execution
AGENTS.md, internal/contributor-info/release-train-runbook.md
Defines the canonical release-line lease, heartbeat checks, source-shape-aware backports, validation gates, and retained changelog handling.
Lease-guarded promotion and closeout
internal/contributor-info/release-train-runbook.md
Adds lease checks for promotion, forward-porting, branch deletion, and audited selective closeout with evidence and atomic ref updates.
Preview and guarded release instructions
internal/contributor-info/releasing.md
Replaces live examples with preview-oriented commands and updates reconciliation, recovery, and failure-handling guidance.
Forward-port policy
AGENTS.md
Requires release/* to main cherry-picks with provenance, retained-source re-auditing, and guarded release-helper usage.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Coordinator
  participant AgentCoord
  participant OriginMain
  participant ReleaseBranch
  Coordinator->>AgentCoord: Claim release-line:X.Y.Z lease
  AgentCoord-->>Coordinator: Confirm active lease
  Coordinator->>OriginMain: Refresh and validate source
  Coordinator->>ReleaseBranch: Cherry-pick source with -x
  Coordinator->>AgentCoord: Renew lease before merge
  ReleaseBranch-->>Coordinator: Record backport and changelog reconciliation
Loading

Possibly related PRs

Suggested labels: documentation

Suggested reviewers: ihabadham

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: documenting the serialized release backport policy.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/release-backport-policy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown

Greptile Summary

This PR documents the serialized release backport rule. The main changes are:

  • One merged source PR per release backport PR.
  • Serial branch creation from the refreshed release tip.
  • Cherry-pick provenance for squash and merge commits.
  • Changelog retention, reconciliation, and final stamping guidance.
  • Maintainer-approved exceptions for inseparable changes.
  • Aggregate release PR close and branch-retention rules.

Confidence Score: 5/5

This looks safe to merge after a small wording cleanup.

  • The release backport policy is documentation-only.
  • The main flow is consistent across the changed files.
  • One runbook sentence should match the stricter write-authorization wording used by the release-train skill.

internal/contributor-info/release-train-runbook.md

Important Files Changed

Filename Overview
.agents/skills/react-on-rails-release-train-issue-evaluation/SKILL.md Adds source-atomic backport shape rules to the release-train evaluation skill.
AGENTS.md Adds the top-level release policy for serial one-source-PR backports.
internal/contributor-info/release-train-runbook.md Adds detailed backport steps, with one authorization wording mismatch to tighten.

Reviews (1): Last reviewed commit: "Document serialized release backport pol..." | Re-trigger Greptile

Comment thread internal/contributor-info/release-train-runbook.md Outdated
Comment thread AGENTS.md Outdated
@claude

claude Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review: Document serialized release backport policy

Docs-only change (SKILL.md, AGENTS.md, release-train runbook) codifying a "one merged source PR per release backport PR, serialized" rule, prompted by the #4590 gap. Overall this is well-scoped and internally consistent — the three docs reinforce each other, cherry-pick guidance (-x, -m 1 -x for merge commits) matches existing conventions used elsewhere in the runbook, and the changelog-reconciliation and aggregate-PR-closure authority rules align with the repo's existing git-safety boundaries (never delete branches without explicit authorization, etc.).

Findings

  • Left an inline nit on AGENTS.md:692 — the condensed bullet says "give it its own release branch," but the immediately preceding bullet just defined "release branch" as the singular ephemeral release/X.Y.Z branch. The new bullet actually means a topic branch cut from the release tip for the individual backport (as the runbook version correctly spells out: "create a branch from its current tip"). Low risk since the runbook has the disambiguated version, but AGENTS.md is supposed to be the terse rule an agent follows directly, so the ambiguity is worth tightening.
  • Minor style nit: internal/contributor-info/release-train-runbook.md:220 uses -> ("one source PR -> one release PR") where the rest of the file's prose consistently uses the unicode arrow for flow descriptions (e.g. "phase→gate table", "1 → 2 → 4 → 5"). Not functionally significant, just an inconsistency with the file's own established convention.

No issues found with:

  • Logical consistency across the three edited docs (SKILL.md, AGENTS.md, runbook) — the condensed AGENTS.md rule, the skill's "Backport Shape" section, and the runbook's step-by-step procedure all agree.
  • The narrow "behaviorally inseparable" exception is appropriately gated behind explicit maintainer approval, avoiding a loophole that swallows the rule.
  • No code/runtime changes, so no security, performance, or test-coverage implications beyond doc accuracy.

…t-policy

* origin/main: (33 commits)
  Release: add auditable accelerated RC async gates (#4669)
  Release: handle optional required-check metadata (#4685)
  Release: forward-port post-pull prerelease guard (#4680)
  Forward-port stable RSC 19.2.1 to main (#4672)
  Forward-port Pro license metadata to main (#4668)
  Docs: clarify local benchmark workflow (#4665)
  Fix Hacker News demo-fleet smoke path (#4664)
  Release: reuse verified ShakaPerf pre-run evidence (#4662)
  Release: require strict HEAD evidence before retry guidance (#4661)
  Fix: support React 18 non-RSC streaming (#4658)
  Docs: compare Next.js with Rails async-props streaming (#4651)
  Docs: add reusable demo fleet RC update prompt (#4649)
  CI: run Pro compatibility smokes in hosted tests (#4656)
  Fix ambiguous prerelease retries (#4654)
  Test: add packaged Pro smokes for React 16 and 17 (#4652)
  docs: clarify release version ownership and RSC promotion (#4650)
  [Pro] Keep react-on-rails-rsc out of non-RSC entry graphs (fixes React 18 builds on rc.9) (#4641)
  ci: make benchmark proof gates replayable (#4626)
  Test: keep React 19 coverage out of the React 18 lane (#4635)
  Redact prerender secrets and harden service checks (#4624)
  ...

# Conflicts:
#	internal/contributor-info/release-train-runbook.md
@justin808

Copy link
Copy Markdown
Member Author

Address-review summary

Scan scope: full history via check all reviews.

Mattered

  • Corrected the aggregate-PR closure boundary to require explicit write authorization, matching the release-train skill. Fixed in 1b97c5a2b56bca4f842d074f76899ea2939e01ac; reply and resolved thread.

Optional

  • Clarified that each source PR gets a backport branch off the release tip, not another release/X.Y.Z branch. Fixed in 1b97c5a2b56bca4f842d074f76899ea2939e01ac; reply and resolved thread.

Skipped

  • Three automated summary/status comments contained no additional actionable item beyond the two inline threads; recorded as no-action outcomes.

Stale-base race control — checklist+replay

  • Mechanism target: checklist+replay.
  • Motivating miss: this release-policy PR was 33 commits behind origin/main, so landing a new gate without rechecking in-flight work could apply stale policy.
  • Race-control option: require affected in-flight PRs to update to current main and rerun the new checker/current CI before merge; the batch coordinator must recheck the current base/head immediately before merging.
  • Replay evidence (2026-07-16): swept all open PRs. No open PR targets release/*; the only open PR touching the newly enforced policy surfaces was Document serialized release backport policy #4592 at its old head. Merged current origin/main without history rewriting, preserved the concurrent prerelease-dependency runbook section, and produced head 1b97c5a2b56bca4f842d074f76899ea2939e01ac. The final diff remains exactly the three release-policy paths, and script/ci-changes-detector origin/main classifies it documentation-only with no hosted jobs recommended.
  • Non-goal: do not create a broad enforcement script or mutate unrelated open PRs as part of this focused policy clarification.

Verification

  • Agent-workflow seam doctor, focused policy assertions, docs sidebar, Prettier, ESLint, CI-equivalent OSS RuboCop, pre-commit hooks, pre-push hooks, and online link checks passed.
  • codex review --base origin/main completed cleanly for the final three-file diff with no actionable findings.
  • Decision points requiring maintainer judgment: 0. Churn: one consolidated base-update/review-fix push.

Next default scan starts after this comment. Say check all reviews to rescan the full PR.

Comment thread internal/contributor-info/release-train-runbook.md Outdated
@claude

claude Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review: Document serialized release backport policy

This is a docs-only PR (no runtime code) adding a "one source PR per release backport PR, serialized" rule across three files: AGENTS.md (canonical policy), the release-train issue-evaluation skill, and the release-train runbook. Overall the policy is well-motivated (closing the gap exposed by #4590) and the three copies are substantively consistent with each other.

Overview

  • AGENTS.md: adds one consolidated bullet to the "Release-Train Branching And Phase Gating" rules stating the one-source-PR-per-backport, serial-branch-off-refreshed-tip rule, changelog-entry retention/reconciliation, and the narrow maintainer-approved inseparability exception.
  • Skill (react-on-rails-release-train-issue-evaluation/SKILL.md): adds a "Backport Shape" section with the same rules, and a step 7 telling the evaluator to record serial order and apply those rules.
  • Runbook (release-train-runbook.md): adds a "Backport merged main PRs one at a time" subsection with a concrete numbered procedure (verify → branch → cherry-pick → resolve conflicts → validate/merge → refetch tip → reconcile changelog), plus prose on not bundling PRs and on handling existing aggregate PRs.

Issue found (posted inline)

In the runbook, the "search open PRs for an existing aggregate before branching" instruction is placed as the last paragraph of the subsection, after the numbered 1–7 procedure — but step 2 of that procedure is itself the branch-creation step. An agent following the numbered steps top-to-bottom would branch before ever reaching the "check for an aggregate first" instruction, which undercuts the exact failure mode (#4590) this PR is meant to prevent. Recommend folding that check into the numbered list as step 1, ahead of "fetch the release branch and create a branch from its current tip." Left an inline comment with specifics.

Minor / non-blocking

  • Wording of the "don't bundle because of shared X" list drifts slightly between the three copies (SKILL.md includes "milestone" as a bundling-excuse to reject; AGENTS.md and the runbook don't). Not a contradiction, just a minor drift worth tightening for a single source of truth.
  • AGENTS.md and the runbook already mix -> and for arrows elsewhere in the file, so the new -> usage in the runbook ("one source PR -> one release PR") is consistent with existing (inconsistent) file style — not something introduced by this PR, just noting it's not a new problem.

Correctness / security / performance

Not applicable — this PR only changes markdown process documentation and doesn't touch runtime code, tests, or CI configuration, so there's no correctness, security, or performance surface to review beyond the policy text itself.

Test coverage

N/A for a docs-only change; the PR description notes prettier, lychee link checks, and rubocop were run, which is reasonable diligence for this kind of change.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b97c5a2b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .agents/skills/react-on-rails-release-train-issue-evaluation/SKILL.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
internal/contributor-info/release-train-runbook.md (2)

270-273: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Require passing gates before merging each backport.

“Run” does not prevent merging after a failed validation, QA, or review gate. Require all applicable gates to be green, or require a documented maintainer-authorized waiver before merging.

Proposed wording
-   Run the release-phase validation, QA, and review gates, then merge the PR.
+   Run the release-phase validation, QA, and review gates. Merge the PR only
+   after they are green or a documented maintainer-authorized waiver is recorded.
🤖 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 `@internal/contributor-info/release-train-runbook.md` around lines 270 - 273,
Update the release-train runbook step covering release-phase validation, QA, and
review gates to require every applicable gate to pass before merging each
backport. Permit merging only when a documented maintainer-authorized waiver
exists for a failed or unavailable gate.

280-282: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Require verified maintainer authorization for exceptions and destructive actions.

“Maintainer-approved” and “explicit write authorization” do not identify a trusted approver or approval record. Public GitHub text must not grant this authority without verified authorship or approval.

  • internal/contributor-info/release-train-runbook.md#L280-L282: require approval from a verified authorized maintainer for bundling exceptions.
  • internal/contributor-info/release-train-runbook.md#L288-L291: require separately verified authorization before closing an aggregate PR or deleting its branch.
🤖 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 `@internal/contributor-info/release-train-runbook.md` around lines 280 - 282,
Update the bundling-exception guidance at
internal/contributor-info/release-train-runbook.md lines 280-282 to require
approval from a verified, authorized maintainer, including an identifiable
approval record. Update the aggregate PR closure and branch deletion guidance at
lines 288-291 to require separately verified authorization before either
destructive action.

Source: Coding guidelines

🤖 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.

Outside diff comments:
In `@internal/contributor-info/release-train-runbook.md`:
- Around line 270-273: Update the release-train runbook step covering
release-phase validation, QA, and review gates to require every applicable gate
to pass before merging each backport. Permit merging only when a documented
maintainer-authorized waiver exists for a failed or unavailable gate.
- Around line 280-282: Update the bundling-exception guidance at
internal/contributor-info/release-train-runbook.md lines 280-282 to require
approval from a verified, authorized maintainer, including an identifiable
approval record. Update the aggregate PR closure and branch deletion guidance at
lines 288-291 to require separately verified authorization before either
destructive action.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6c8085ba-ff08-46e6-8ca6-68e742ee9295

📥 Commits

Reviewing files that changed from the base of the PR and between e0e8d87 and 1b97c5a.

📒 Files selected for processing (2)
  • AGENTS.md
  • internal/contributor-info/release-train-runbook.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • AGENTS.md

@justin808

Copy link
Copy Markdown
Member Author

Address-review summary

Scan scope: since previous summary at 2026-07-16T10:18:25Z.

Addressed

  • Moved release-target PR, coordination, and owned remote-branch discovery ahead of branch creation; preserved ordinary issue started-lane checks while distinguishing completed main source state from a release-backport lane. Replies: ordering thread, started-lane thread. Both threads are resolved.
  • The final local review loop also closed edge cases around approved inseparable aggregates, reused-PR/release-tip freshness, squash provenance, single-source attribution, multi-commit rebase mapping, common normalization, conflict ordering, changelog classification, live-main eligibility, one-commit rebase handling, and final-ref race checks.

Skipped

  • No distinct actionable feedback was skipped. Automated status/summary material was treated as supporting context where it repeated the resolved inline findings.

Verification

  • Published head: 2dc9eec896ec678be05b2adf85bb5ba5cecdae6f (remote verified exact).
  • Independent final review: clean; no remaining findings.
  • Review inventory: zero unresolved threads after the cutoff scan.
  • Local: OSS RuboCop (237 files, 0 offenses), pnpm run lint, Prettier/format check, seam doctor, docs-sidebar check, git diff --check, and offline Markdown link validation all passed.
  • Pre-push: online Markdown link validation passed (21/21).
  • CI detector: documentation-only change; recommended hosted CI selection NONE. GitHub current-head checks are running; markdown links and the initial change detector are already green.
  • origin/main advanced after final review from 49835c72 to 6325e108; the new commit touches only CHANGELOG.md plus Pro runtime/tests, with no overlap in this PR's three policy/runbook files or CI configuration. The coordinator will perform the planned final base sync/current-head gate after maker closeout.
  • Labels: unchanged/none. Benchmarks and runtime/performance validation: not applicable to this docs/policy-only change.

Churn

  • One consolidated final push followed the local fix/review loop; no nit-only or force pushes.

Next scan should use this summary's creation timestamp as the review cutoff and inspect only later feedback.

#### Backport merged `main` PRs one at a time

When maintainers select one or more merged `main` PRs for the release train,
use **one source PR -> one release PR**. When there are multiple selections,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Minor style nit: this doc otherwise uses the Unicode for prose arrows (e.g. "1 → 2 → 4 → 5", "main → release/X.Y.Z"), reserving ASCII -> for code/CLI snippets. one source PR -> one release PR here is prose, so would be more consistent.

`main`, stop unless a maintainer renews the backport approval with that
current state.
3. If step 1 found a valid backport PR, update its branch onto the current
release tip under the repository's branch-rewrite policy. Repeat the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

"the repository's branch-rewrite policy" isn't a defined term anywhere else in the repo docs (checked AGENTS.md, CLAUDE.md, and the rest of this file) — it reads like it should link to the force-push/rebase rules in AGENTS.md's Git Safety section (e.g. "Force-push after a clean rebase ... is OK without asking"), but there's no explicit pointer. Worth linking to the actual section so this isn't a dangling reference for whoever executes this step.

Comment on lines +293 to +297
commits that landed from the PR on `main`, mapping the PR commits to landed
commits with merge metadata and stable patch IDs. Cherry-pick every landed
commit oldest-first with `git cherry-pick -x <source-sha>` only after the
maintainer-approved merge plan required by step 7 exists. Stop if the
complete mapping cannot be proven or that merge plan is absent.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ordering issue: this step-4 bullet gates cherry-picking on "the maintainer-approved merge plan required by step 7" — i.e. the plan must already exist before step 4 runs. But step 7 (later in the doc) is where that requirement is actually spelled out ("Stop for a maintainer-approved merge plan until…"), and it's phrased as a merge-time gate, not something to front-load. A reader/agent following the steps in order will hit this at step 4 with no prior instruction on how/when to obtain that plan, then only learn the full requirement three steps later.

Consider either (a) adding an explicit early step that says "for a multi-commit rebase-merged source PR or aggregate, obtain maintainer approval for the merge plan before branching/cherry-picking," or (b) rewording this bullet to point forward more explicitly, e.g. "...only after obtaining the maintainer-approved merge plan described in step 7's stop condition."

@claude

claude Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review

Documentation/policy-only PR: adds a serialized-backport rule (one merged main PR per release/X.Y.Z backport PR) across AGENTS.md (canonical summary), the release-train-issue-evaluation skill, and the release-train runbook (detailed procedure). No runtime code is touched.

Overview

  • Establishes "one source PR → one release backport PR," processed serially, in response to the [Pro] Backport RSC retries and license configuration to 17.0.0 #4590 aggregate-PR incident.
  • Details cherry-pick provenance rules (-x footer normalization, mainline-parent choice for merge commits, handling of multi-commit rebase-merged sources).
  • Adds duplicate-lane detection (search existing PRs/branches/coordination state before creating a new one) and a narrow, maintainer-approved exception for combining behaviorally inseparable changes.
  • Threads changelog-entry preservation and reconciliation through the backport flow.
  • Cross-links are consistent with the existing "AGENTS.md is canonical, runbook has full detail" architecture stated at the top of the runbook.

Strengths

  • The three files stay consistent with each other on substance (duplicate-lane checks, liveness/supersession re-checks immediately before merge, footer normalization, changelog handling) despite each targeting a different audience/verbosity level.
  • The UNKNOWN-classification claim about the changelog sweep for rebase-merged multi-commit backports checks out against .agents/skills/update-changelog/bin/changelog-merged-prs — that script maps commits to PRs via the GitHub API and has no cherry-pick-footer parsing, so cherry-picked commits (new SHAs) genuinely would go unmapped. Good grounding for a fairly specific technical claim.
  • Scoping this to React on Rails' AGENTS.md/runbook rather than the portable agent-workflows pack (per the PR description) matches the "release trains are consumer-specific" rationale.

Issues found (posted as inline comments)

  1. Dangling reference — "the repository's branch-rewrite policy" (runbook line 282) isn't a defined term anywhere in the repo's docs; it should point at the actual force-push/rebase rules in AGENTS.md's Git Safety section.
  2. Forward-reference ordering — the multi-commit rebase-merge bullet in step 4 (runbook lines 293–297) requires "the maintainer-approved merge plan required by step 7" to already exist, but step 7 is where that requirement is actually introduced. A reader following the steps in order hits this gate before the doc has explained how to satisfy it.
  3. Minor style nitinternal/contributor-info/release-train-runbook.md:262 uses ASCII -> in prose ("one source PR -> one release PR"), where the rest of the document consistently uses for prose arrows and reserves -> for code/CLI snippets.

General observation (not inline-commented)

The new prose is very dense — long, multi-clause sentences packing several conditionals into one paragraph (especially the single-paragraph AGENTS.md addition and the "Excluded started lanes" bullet in the skill file). It's technically precise and internally consistent, but a maintainer skimming under time pressure may have trouble parsing it correctly on first read. Not blocking, but worth a readability pass (e.g., breaking the AGENTS.md paragraph into a short bullet list) in a follow-up if this policy gets revised again.

No security, performance, or test-coverage concerns — this is process documentation with no executable surface.

* origin/main:
  Fix Pro performance mark fallback accumulation (#4690)
justin808 added 15 commits July 16, 2026 02:55
…t-policy

* origin/main: (30 commits)
  Fix SSR crash on unpaired UTF-16 surrogates from JS JSON output (#4710) (#4726)
  Remove false Doctor pack-tag pairing warnings (fixes #4619) (#4724)
  Fix Pro renderer artifact cache identity (#4701)
  [Pro] Skip stream caches for error-containing renders (fixes #4581) (#4722)
  docs: mark 16.2.0 immediate_hydration override note as historical (fixes #4639) (#4725)
  Redact RSC rendering error details from client DOM in production (#4631)
  Fix fragile envSpecific gsub silently leaving lazy compilation on (#4632)
  Docs: node-renderer default setup requires Node.js 20+ (Fastify 5) (#4733)
  [Pro] Harden loadable-stats success-cache test; route worker tests through formAutoContent shim (partially addresses #4506) (#4721)
  Add rsc-guardrails agent skill + payload-escaping regression test + advisory hook (#4599)
  Regenerate llms-full references (#4728)
  CI: make hosted dispatch exact-head idempotent (#4692)
  Docs: normalize version floors, release metadata, and branch links (#4709)
  Docs: fix node-renderer startup, versions, and missing config options (#4707)
  Docs: fix Shakapacker build & migration recipes (#4703) (#4708)
  Docs: document Pro ExecJS profiling prerequisites & missing cached helpers (#4706)
  docs: correct OSS helper & API-reference examples (broken/stale snippets) (#4637)
  Docs: correct immediate_hydration removal details (#4638) (#4640)
  CI: route gem generator specs by changed paths (#4691)
  Prevent oversized GitHub release failures (#4714)
  ...
…t-policy

* origin/main:
  CI: keep ShakaPerf release workflows YAML-lint clean (#4741)

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e51825acd7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

--branch "release/${RELEASE_VERSION}" \
--phase release-write-serialization \
--status in_progress \
--ttl 900

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Remove unsupported heartbeat TTL flag

The current agent-coord CLI synopsis lists --ttl for claim but not for heartbeat, so copying this bootstrap makes agent-coord heartbeat fail with a usage error immediately after the 4-hour claim has already been written. In that state acquire_release_line_lease never succeeds and can leave the release line blocked until takeover or expiry; use the CLI's default heartbeat TTL or add heartbeat TTL support before documenting this flag.

Useful? React with 👍 / 👎.

(.heartbeats | length == 1) and
(.heartbeats[0].agent_id == $holder) and
(.heartbeats[0].instance_id == $instance) and
(.heartbeats[0].target == $target) and

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Compare heartbeat target as a raw target

After the heartbeat write succeeds, this assertion still rejects the valid lease because the heartbeat was created with --repo shakacode/react_on_rails --target "${RELEASE_LINE_TARGET}", and the agent-coord heartbeat schema stores repo and raw target separately. Comparing .heartbeats[0].target to the synthetic shakacode/react_on_rails#release-line:... string therefore keeps require_live_release_line_lease false for the release coordinator; check .repo and raw .target separately or match the actual scoped-status schema.

Useful? React with 👍 / 👎.

# If a PR is required, complete its exact-head gates, then in the merger's shell:
FORWARD_PORT_PR="${FORWARD_PORT_PR:?set the forward-port PR number or URL}"
require_live_release_line_lease || { return 1 2>/dev/null || exit 1; }
gh pr merge "${FORWARD_PORT_PR}" --rebase # stop if this would queue or defer the merge

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Prevent queued PR merges after the lease check

When this runs against a branch with merge queue enabled, or when required checks are not complete, gh pr merge --rebase may schedule work instead of merging immediately: the GitHub CLI manual says pending checks enable auto-merge and passed checks add the PR to the queue. That means the merge can happen after this pre-command lease check expires or after the audited refs change, contradicting the surrounding “stop if this would queue or defer” requirement; add a precheck/API path that fails unless the merge completes synchronously, or avoid this command in queued contexts.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@internal/contributor-info/release-train-runbook.md`:
- Around line 736-737: Fence every closeout write before execution: make the
live forward-port helper preview-only or guard its individual writes with
require_live_release_line_lease, rather than checking only afterward. In the tag
closeout flow, perform the lease check before git tag -a creates the tag, and
retain the existing check immediately before the atomic git push.

In `@internal/contributor-info/releasing.md`:
- Around line 732-739: Update the NPM registry query in the release recovery
instructions to use pnpm instead of npm, specifically the command under step 2
alongside the existing RubyGems query. Preserve the package name, version
placeholder, and read-only verification intent.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e9069bb8-7250-42e9-a9cd-9d92f8e54e68

📥 Commits

Reviewing files that changed from the base of the PR and between 2dc9eec and e51825a.

📒 Files selected for processing (4)
  • .agents/skills/react-on-rails-release-train-issue-evaluation/SKILL.md
  • AGENTS.md
  • internal/contributor-info/release-train-runbook.md
  • internal/contributor-info/releasing.md

Comment on lines +736 to +737
require_live_release_line_lease || { return 1 2>/dev/null || exit 1; }
git push # push main directly or push the exact forward-port PR branch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Fence every closeout write before it occurs.

Line 735 runs the live forward-port helper even though Lines 712-713 mark normal mode as blocked; the lease check at Line 736 is too late to fence that write. Likewise, git tag -a at Line 920 precedes the lease check at Line 929. Keep the helper preview-only or guard individual writes, and move the tag check before tag creation while retaining the check before the atomic push.

Also applies to: 920-933

🤖 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 `@internal/contributor-info/release-train-runbook.md` around lines 736 - 737,
Fence every closeout write before execution: make the live forward-port helper
preview-only or guard its individual writes with
require_live_release_line_lease, rather than checking only afterward. In the tag
closeout flow, perform the lease check before git tag -a creates the tag, and
retain the existing check immediately before the atomic git push.

Comment on lines +732 to +739
1. Stop the compound helper and keep the release-line lease. Do not delete or move tags, rewrite the
release branch, rerun publication, or manually publish missing packages.
2. Check what was published with read-only registry queries:
- NPM: `npm view react-on-rails@X.Y.Z`
- RubyGems: `gem list react_on_rails -r -a`

2. If the git tag was created but packages weren't published:
- Delete the tag: `git tag -d vX.Y.Z && git push origin :vX.Y.Z`
- Revert the version commit: `git reset --hard HEAD~1 && git push -f`
- Start over with `bundle exec rake "release[X.Y.Z]"`

3. If GitHub release creation fails after successful publishing:
- Fix GitHub auth (`gh auth login`) or permissions
- Ensure `CHANGELOG.md` has matching header `### [X.Y.Z]`
- Do not rerun registry publication; the failure message prints the GitHub-only recovery command
- Rerun only: `bundle exec rake "sync_github_release[X.Y.Z]"`

4. If some packages were published but not others:
- You can manually publish the missing packages:
```bash
cd packages/react-on-rails && pnpm version X.Y.Z && pnpm publish
cd ../react-on-rails-pro && pnpm version X.Y.Z && pnpm publish
gem release
```
`pnpm publish -r` will publish all packages where current version isn't published yet.
3. Record the exact branch tip, local and remote tag identity, published artifact set, and helper output.
4. Follow the [Release-Train Runbook](release-train-runbook.md#serialize-every-release-line-write) for
guarded live recovery. If lease state or any remote/artifact identity is `UNKNOWN`, remain stopped.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- internal/contributor-info/releasing.md (around lines 732-739) ---'
sed -n '728,742p' internal/contributor-info/releasing.md

echo
echo '--- search for registry-check commands ---'
rg -n '\b(npm|pnpm)\s+view\b|\b(npm|pnpm)\s+info\b' internal/contributor-info . -g '*.md' -g '*.mdx' || true

Repository: shakacode/react_on_rails

Length of output: 2209


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- pnpm CLI help (view/info) if available ---'
if command -v pnpm >/dev/null 2>&1; then
  pnpm --help | sed -n '1,120p' || true
  echo
  pnpm help view 2>/dev/null | sed -n '1,120p' || true
else
  echo 'pnpm not installed in sandbox'
fi

Repository: shakacode/react_on_rails

Length of output: 2769


🌐 Web query:

pnpm view command syntax package metadata equivalent to npm view version

💡 Result:

The command in pnpm that is equivalent to npm view is pnpm view [1][2]. As of recent versions, pnpm includes a native view command that functions similarly to npm view [2]. The syntax is [1]: pnpm view [field] For example, to view the version of a package, you can run: pnpm view version When no package name is provided, pnpm defaults to the package defined in the current project manifest (package.json) [1]. Like npm view, pnpm view also supports the --json flag to output metadata in JSON format [1][2]. Additionally, pnpm provides aliases for this command, including info, show, and v [2][3]. top_results: [1][2][4]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

pnpm help -a | sed -n '1,220p' | rg -n '^( *[a-z,/-]+ +)?(view|info|show)\b' || true
echo
echo '--- pnpm help info ---'
pnpm help info 2>/dev/null | sed -n '1,120p' || true
echo
echo '--- pnpm help show ---'
pnpm help show 2>/dev/null | sed -n '1,120p' || true

Repository: shakacode/react_on_rails

Length of output: 580


Use pnpm view for the registry check

Line 735 should use the pnpm equivalent of npm view so this stays consistent with the repo’s package-manager rules, e.g. pnpm view react-on-rails@X.Y.Z.

🤖 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 `@internal/contributor-info/releasing.md` around lines 732 - 739, Update the
NPM registry query in the release recovery instructions to use pnpm instead of
npm, specifically the command under step 2 alongside the existing RubyGems
query. Preserve the package name, version placeholder, and read-only
verification intent.

Source: Coding guidelines

Comment on lines 323 to +332
**Step 1b — cut rc.0 from the branch.** After at least one CI run finishes on the `release/17.0.0` tip,
ensure the rc changelog header is present (`$react-on-rails-update-changelog rc`
targeting the branch), then cut rc.0 with a
bare release — the version is read from CHANGELOG.md, so you do **not** pass `17.0.0.rc.0`:
targeting the branch). The bare release command reads the version from CHANGELOG.md, so you do **not**
pass `17.0.0.rc.0`. It is currently an unfenced compound writer: preview and prepare the cut, but stop
before live execution until the wrapper contract above is implemented.

```bash
# On release/17.0.0, with CHANGELOG.md stamped ### [17.0.0.rc.0]:
bundle exec rake release # reads 17.0.0.rc.0 from CHANGELOG.md, bumps version.rb, tags v17.0.0.rc.0, publishes
require_live_release_line_lease || { return 1 2>/dev/null || exit 1; }
# BLOCKED: bundle exec rake release would bump, tag, and publish without per-write lease fences.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This PR's stated purpose (per the PR description) is "document serialized release backport policy" — but this hunk (and the parallel edits at promote and close-out) does something much bigger: it turns bundle exec rake release into a literal # BLOCKED: comment with no runnable command, pending a "repository-owned wrapper" that doesn't exist anywhere in this repo (grep -rn "wrapper contract" internal/ AGENTS.md only finds references added by this PR itself).

Concretely, as written, a maintainer following this runbook can no longer cut an RC, promote a final, or close out a release line using the documented/previously-working scripted paths (script/release-finish, bundle exec rake release, script/release-forward-port) — every one of them is now dry-run/preview-only. That's a much bigger behavioral change than "one source PR per release backport," isn't mentioned in the PR description, and leaves the release process undocumented/unusable until a wrapper that isn't part of this PR is built.

Is disabling live releases repo-wide actually intended scope here? If so it deserves its own PR/description (and ideally the wrapper itself, or at least a tracking issue) rather than being folded into the backport-policy PR.

Comment thread AGENTS.md
- **`main` never freezes.** It stays in the `beta` phase and keeps absorbing batch work the whole time.
- **RCs stabilize on an ephemeral `release/X.Y.Z` branch** (one branch per final target, deleted after the final ships; tags are the durable record). Only stabilizing fixes target `release/*`; new features keep targeting `main`.
- **Forward-port every `release/*` fix to `main` with `git cherry-pick -x <sha>`.** Never `git merge release/X.Y.Z` into `main` — that leaks the RC version-bump commits onto `main`.
- **Serialize every release-line write; backport one merged source PR per release PR.** Before creating, updating, tagging, promoting, merging, or deleting `release/X.Y.Z`—including release-line creation, every RC cut or re-spin, release-first stabilizers, `main` backports, changelog or metadata PRs, final promotion, and branch deletion—acquire and hold the canonical `release-line:X.Y.Z` coordination lease defined before Step 1 of the release-train runbook. Source-scoped claims do not serialize release writers. One dedicated release coordinator owns the lease and serial dispatch. Chain later batch lanes with `depends_on`, and do not launch them before the preceding merge is terminal. A writer that cannot participate in the canonical lease must stop; the repository's merge-group CI does not rerun release-specific source-liveness, provenance, attribution, manual QA, or review gates and is not an alternative. Refresh the dedicated heartbeat at the runbook cadence during long gates, and immediately before every write or merge require the canonical claim to be active, unexpired, and owned by the expected coordinator with a live matching heartbeat; stop if the guard is unavailable or its state is `UNKNOWN`. Search release-targeted PRs, targeted coordination, and owned remote branches so an existing valid lane is reused instead of duplicated. Give a new lane its own branch off the release tip, validation, QA, and PR. For a `main` backport, also require source-atomic `git cherry-pick -x` provenance: before updating or branching, fetch `origin/main` and confirm its source patch is still live there; a reverted or superseded source requires renewed maintainer approval. Merge it before updating a reused PR onto the refreshed release tip or branching the next backport; immediately before merge, refetch both `origin/main` and the release tip, and update plus rerun the gates if either relevant state changed. Each commit created by a `main`-to-release backport and landed on the release branch must contain exactly one direct `git cherry-pick -x` footer; record inherited provenance in the PR instead of copying another footer. A backport with exactly one source commit must be squash-merged with a final subject ending in `(#<backport-pr-number>)` and the direct footer in its body; a rebase merge is unsupported because an unattributed source subject can make the changelog sweep report `UNKNOWN`. For a multi-commit rebase-merged source PR or explicitly approved inseparable aggregate, stop for a maintainer-approved merge plan until the repository can preserve both one normalized release commit per source commit and changelog-sweep PR attribution; never produce a multi-footer commit. Do not combine independent source PRs because they share a release target, component, or `CHANGELOG.md`; shared metadata is a serialization reason. Combine only behaviorally inseparable fixes with an explicit maintainer-approved rationale covering review, testing, and rollback. Each backport retains its source PR's applicable changelog entry; after every backport retained in the final release set lands, reconcile those entries and stamp or regenerate the RC changelog. Before every RC cut or re-spin and final promotion, fetch `origin/main` and revalidate every retained main-origin backport; a source patch that is no longer live blocks the release until a maintainer explicitly reapproves retaining it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This bullet is a single ~350-word run-on sentence-fragment paragraph packed into one bullet point (compare to the concise one-liner it replaced). It mixes at least 5 distinct rules (lease acquisition, lane reuse, cherry-pick provenance, merge-method requirements, changelog reconciliation) with no structure. As the canonical policy doc (per CLAUDE.md: "AGENTS.md is the canonical policy"), this is hard to scan, hard to keep consistent with the fuller runbook version, and easy to have drift between the two copies of essentially the same rules (this bullet vs. the ## Serialize every release-line write section + #### Backport merged main PRs one at a time section in release-train-runbook.md). Consider trimming this to a short pointer into the runbook section rather than restating the entire procedure inline.

Comment on lines +188 to +225
jq -e \
--arg holder "${RELEASE_COORDINATOR_ID}" \
--arg instance "${RELEASE_COORDINATOR_INSTANCE_ID}" \
--arg target "shakacode/react_on_rails#${RELEASE_LINE_TARGET}" \
'(.claims | length == 1) and
(.claims[0].status == "active") and
(.claims[0].agent_id == $holder) and
(.claims[0].instance_id == $instance) and
(.claims[0].expires_at != "UNKNOWN") and
((.claims[0].expires_at | fromdateiso8601) > now) and
(.heartbeats | length == 1) and
(.heartbeats[0].agent_id == $holder) and
(.heartbeats[0].instance_id == $instance) and
(.heartbeats[0].target == $target) and
(.heartbeats[0].liveness == "live")' \
>/dev/null <<<"${lease_json}"
}

acquire_release_line_lease() {
"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded" --timeout 20 status \
--repo shakacode/react_on_rails --target "${RELEASE_LINE_TARGET}" --json \
>/dev/null || return 1
"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded" --timeout 20 claim \
--agent-id "${RELEASE_COORDINATOR_ID}" \
--instance-id "${RELEASE_COORDINATOR_INSTANCE_ID}" \
--repo shakacode/react_on_rails \
--target "${RELEASE_LINE_TARGET}" \
--branch "release/${RELEASE_VERSION}" \
--ttl 14400 || return 1
heartbeat_release_line_lease || return 1
require_live_release_line_lease
}

acquire_release_line_lease
lease_status=$?
if [ "${lease_status}" -ne 0 ]; then
echo "release-line lease unavailable or UNKNOWN; stop" >&2
return "${lease_status}" 2>/dev/null || exit "${lease_status}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

require_live_release_line_lease hard-requires .claims | length == 1 and .heartbeats | length == 1 from agent-coord status --target ... --json. Elsewhere in this repo's docs (agent-coordination-backend.md), targeted agent-coord status is described as returning current lane state, but I don't see the backend's JSON schema confirming that heartbeats is always a singleton (vs. a history/log array) for a target that has been heartbeated many times over a multi-hour release. If the backend ever returns more than one heartbeat record (e.g. recent history) for the same target, this check fails closed every time — which is safe, but would make the whole release process permanently stuck rather than just failing on genuine staleness. Worth explicitly confirming against the backend schema/CLI docs (agent-coord config show --json) before this ships as the gating check for every release write.

@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review summary

This is a documentation-only PR (4 files: AGENTS.md, the release-train runbook, releasing.md, and the release-train-issue-evaluation skill), so "code quality/bugs/security/perf" translate to correctness and internal consistency of the policy prose and the embedded shell/jq snippets.

Overview

The stated goal is to codify "one merged main PR per release/X.Y.Z backport PR" as policy, prompted by the closed aggregate #4590. The actual diff is much larger than that: it also introduces a brand-new release-line:X.Y.Z coordination-lease mechanism (claim/heartbeat/renew via agent-coord) and, as a side effect, converts every previously-runnable release-automation command (bundle exec rake release, script/release-finish, script/release-forward-port, sync_github_release) throughout the runbook and releasing.md into dry-run/preview-only invocations, with several literal # BLOCKED: placeholders, pending a "repository-owned wrapper" that isn't implemented anywhere in this PR or the rest of the repo.

Main concern (see inline comment on release-train-runbook.md)

Scope: the PR body only describes the backport-serialization rule, but the diff effectively disables the documented live-release workflow repo-wide (branch cut, RC cut, promotion, closeout all now say "stop until the wrapper contract above is implemented"). That's a significant, undisclosed behavioral change to maintainer-facing release tooling docs bundled into a PR framed as a narrower policy addition. Worth confirming this is intentional and, if so, splitting it out with its own description (and ideally landing the wrapper alongside it, or a tracking issue for it) so it's reviewable on its own merits.

Other points

  • AGENTS.md's new bullet (~350 words, one run-on sentence) duplicates the fuller runbook sections almost verbatim. Since AGENTS.md is called out as the canonical policy source in CLAUDE.md, having two long-form copies of the same rule set is a maintenance/drift risk — consider condensing to a pointer into the runbook.
  • The new require_live_release_line_lease jq check assumes .claims and .heartbeats are always singleton arrays for a target. This fails closed (safe) if that assumption is wrong, but "fails closed" here means the entire release process gets stuck rather than surfacing a targeted staleness error — worth confirming against the agent-coord backend schema before this becomes a hard gate on every release write.
  • The new atomic-push / tag-based selective-closeout sequence (SHA256-stamped closeout tag, --force-with-lease on both branch delete and new tag) is intricate and only exists as markdown — it has no test coverage and will only be exercised for real during an actual live release. Given the complexity, consider a dry-run rehearsal against a throwaway branch/tag before this becomes the documented closeout path.

Nothing here is a security issue in the traditional sense (no app code changed), but the lease/lock design is effectively a distributed-coordination protocol now embedded in prose rather than code, which carries real correctness risk if the assumptions above don't hold.

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