{"owner":"shakacode","repo":"react_on_rails","hasSkills":true,"totalSkillsCount":6,"totalTokensCount":13955,"categories":["root-instruction","claude-rule","mcp-config","marketplace","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"react_on_rails":{"command":"npx","args":["-y","@modelcontextprotocol/server-react_on_rails"]}}},"found":["llms.txt","CLAUDE.md","AGENTS.md",".cursor/mcp.json",".claude-plugin/marketplace.json",".claude-plugin/plugin.json"],"skills":{"llms.txt":"# React on Rails\n\nReact on Rails integrates React with Ruby on Rails. Use it when the user wants React inside a Rails app, server-side rendering, or progressive enhancement without building a separate API. Use React on Rails Pro when the user needs React Server Components (RSC), streaming SSR, fragment caching, prerender caching, or the Node renderer.\n\nUse this file as the short machine-readable route map. Use `./llms-full.txt` for the expanded OSS reference and `./llms-full-pro.txt` for the expanded React on Rails Pro reference. Use `./AGENTS_USER_GUIDE.md` for the repo-oriented guide to the machine-readable layer.\n\n## Canonical entry points\n\n- Human docs overview: https://reactonrails.com/docs/\n- OSS docs hub: https://reactonrails.com/docs/introduction\n- Pro docs hub: https://reactonrails.com/docs/pro\n- RSC docs hub: https://reactonrails.com/docs/pro/react-server-components\n- Expanded machine-readable reference (OSS): `./llms-full.txt`\n- Expanded machine-readable reference (Pro): `./llms-full-pro.txt`\n- Agent usage guide: `./AGENTS_USER_GUIDE.md`\n\n## Package pairing\n\n- OSS: Ruby gem `react_on_rails` plus npm package `react-on-rails`\n- Pro: Ruby gem `react_on_rails_pro` plus npm package `react-on-rails-pro`\n- Optional Pro Node renderer: npm package `react-on-rails-pro-node-renderer`\n- Do not use `react_on_rails_pro` with the base `react-on-rails` npm package\n\n## Start here by task\n\n- New Rails app with React:\n  - Quick Start: https://reactonrails.com/docs/getting-started/quick-start\n  - Create a New App: https://reactonrails.com/docs/getting-started/create-react-on-rails-app\n  - Tutorial: https://reactonrails.com/docs/getting-started/tutorial\n- Existing Rails app:\n  - Install into an Existing Rails App: https://reactonrails.com/docs/getting-started/existing-rails-app\n  - Using React on Rails: https://reactonrails.com/docs/getting-started/using-react-on-rails\n  - Architecture overview: https://reactonrails.com/docs/core-concepts/how-react-on-rails-works\n- Styling:\n  - Tailwind CSS v4 recipe: https://reactonrails.com/docs/building-features/styling-with-tailwind\n- Choosing OSS vs Pro:\n  - OSS vs Pro: https://reactonrails.com/docs/getting-started/oss-vs-pro\n  - Pro hub: https://reactonrails.com/docs/pro\n  - Upgrade to Pro: https://reactonrails.com/docs/pro/upgrading-to-pro\n- React Server Components:\n  - RSC hub: https://reactonrails.com/docs/pro/react-server-components\n  - RSC tutorial: https://reactonrails.com/docs/pro/react-server-components/tutorial\n  - Add RSC to an existing Pro app: https://reactonrails.com/docs/pro/react-server-components/upgrading-existing-pro-app\n- Node renderer:\n  - Pro overview: https://reactonrails.com/docs/pro/node-renderer\n  - Technical basics: https://reactonrails.com/docs/building-features/node-renderer/basics\n  - JS configuration: https://reactonrails.com/docs/building-features/node-renderer/js-configuration\n- View transitions (experimental, unsupported):\n  - View Transitions recipe + Turbo interplay: https://reactonrails.com/docs/building-features/view-transitions\n- Hydration scheduling:\n  - Defer React root hydration/rendering until immediate, visible, or idle: https://reactonrails.com/docs/building-features/hydration-scheduling\n- Configuration and deployment:\n  - Configuration overview: https://reactonrails.com/docs/configuration\n  - Pro configuration: https://reactonrails.com/docs/configuration/configuration-pro\n  - Deployment: https://reactonrails.com/docs/deployment\n  - Security model and hardening: https://reactonrails.com/docs/deployment/security-model-and-hardening\n  - Troubleshooting: https://reactonrails.com/docs/deployment/troubleshooting\n- Upgrading and migration:\n  - Upgrading: https://reactonrails.com/docs/upgrading/upgrading-react-on-rails\n  - Pro coupled upgrade checklist (gem + npm + lockfiles, RC version formats, RSC manifest verification): https://reactonrails.com/docs/pro/updating#coupled-pro-upgrade-checklist\n  - OSS release notes: https://reactonrails.com/docs/upgrading/release-notes\n  - Pro release notes: https://reactonrails.com/docs/pro/release-notes\n  - Migrate from Next.js: https://reactonrails.com/docs/migrating/migrating-from-nextjs\n  - Migrate from react-rails: https://reactonrails.com/docs/migrating/migrating-from-react-rails\n  - Migrate from Inertia Rails: https://reactonrails.com/docs/migrating/migrating-from-inertia-rails\n  - Migrate to RSC: https://reactonrails.com/docs/migrating/migrating-to-rsc\n\n## Routing notes\n\n- Prefer the canonical Pro hub at `https://reactonrails.com/docs/pro`.\n- `https://reactonrails.com/docs/pro/react-on-rails-pro` currently redirects to the canonical Pro hub URL above.\n- Keep the machine-readable layer small: use the hub pages above first, then open only the task-specific docs you need.\n","CLAUDE.md":"# CLAUDE.md\n\nTool-specific guidance for Claude Code in this repository.\n\n## Source of Truth\n\n`AGENTS.md` is the canonical policy for:\n\n- Commands, tests, and lint workflow\n- Formatting and style requirements\n- Git/PR safety boundaries\n- Project directory boundaries\n\nIf this file conflicts with `AGENTS.md`, follow `AGENTS.md`.\n\n## Behavioral Defaults\n\n- When confident in your changes, **commit and push without asking for permission**. Always monitor CI after pushing, and use the `+ci-*` PR comment commands from `AGENTS.md` when asking maintainers to run, stop, or waive hosted CI.\n- **When `merge_authority` is `auto_merge_when_gates_pass` and the release-mode gate is satisfied, merge; do not stop at a recommendation.** `ask` requires one confirmation before merging, and `none` grants no merge authority. See `AGENTS.md` → Confidence notes for the full tri-state rule, confidence threshold, and required PR-description evidence.\n- Check `main` CI status at session start (injected by `.claude/hooks/main-ci-status.sh`) and again before `gh pr create` or pushing to `main`. See `AGENTS.md` → \"Main branch health\" for the decision framework when `main` is red.\n\n## Git Safety\n\n- **Clean rebase → `git push --force-with-lease` without asking.** When `git rebase origin/main` (or `git pull --rebase`) reports no conflicts, every commit is preserved — republishing is the expected workflow. Just push and report the result.\n- **Ask first when force-pushing in these cases:** you resolved rebase conflicts, you dropped/squashed/reordered commits, or the remote branch has commits you don't have locally.\n- **NEVER `git reset --hard`** on a branch with existing commits (yours or others'). This destroys work. Use a worktree or a new branch instead.\n- **NEVER force-push to `main` or `master`.**\n- If a rebase has conflicts you can't resolve cleanly, abort and ask the user how to proceed.\n\n## Claude-Specific Workflow\n\nUse these docs for Claude-oriented operational guidance:\n\n- `.claude/docs/avoiding-ci-failure-cycles.md`\n- `.claude/docs/replicating-ci-failures.md`\n- `.claude/docs/playwright-e2e-testing.md`\n- `.claude/docs/merge-conflict-workflow.md`\n- `.claude/docs/pr-splitting-strategy.md`\n- `.claude/docs/changelog-guidelines.md`\n- `.claude/docs/project-architecture.md`\n- `.claude/docs/rails-engine-nuances.md`\n- `.claude/docs/debugging-webpack.md`\n- `.claude/docs/rbs-type-checking.md`\n- `.claude/docs/conductor-compatibility.md`\n- `.claude/docs/testing-build-scripts.md`\n- `.claude/docs/main-health-monitoring.md`\n- `.claude/docs/managing-file-paths.md`\n- `.claude/docs/docs-competitive-landscape.md`\n- `.claude/docs/docs-templates.md`\n- `.claude/docs/manual-dev-environment-testing.md`\n- `.claude/docs/validating-node-renderer-changes.md`\n\nFor Pro-package specifics, also read `react_on_rails_pro/CLAUDE.md`.\n","AGENTS.md":"# AGENTS.md\n\nInstructions for AI coding agents working on the React on Rails codebase.\n\nReact on Rails is a Ruby gem + npm package that integrates React with Ruby on Rails, providing server-side rendering (SSR) via Node.js or ExecJS. This is a monorepo: the open-source gem lives at `react_on_rails/`, the npm package at `packages/react-on-rails/`, and the Pro package at `react_on_rails_pro/`.\n\n## Reusable Workflows\n\n- `AGENTS.md`: canonical entry point for agent instructions and workflow discovery\n- Shared agent workflow skills may be installed in the user's or agent's normal\n  skill directory and reused across repos; they must resolve repo-specific\n  values through this repo's `AGENTS.md` seam. The canonical shared source is\n  [`shakacode/agent-workflows`](https://github.com/shakacode/agent-workflows).\n  Use that repo's `agent-workflows-status` and `upgrade-agent-workflows`\n  helpers to keep installed Codex or Claude homes current.\n- When updating reusable agent workflows, skills, commands, or prompt\n  templates, first consider whether the change belongs in\n  `shakacode/agent-workflows` rather than this repo; keep local edits focused on\n  React on Rails-specific policy, seams, or overrides.\n- `.agents/skills/`: repo-specific skills, explicit overrides, and\n  repo-pinned helper `bin/` copies for checkout-only agent sessions. Keep shared\n  workflow `SKILL.md` files installed in the user's or agent's normal skill\n  directory; duplicating them here creates duplicate Codex skill picker entries.\n  Current repo-specific skills include `$stress-test`,\n  `$optimize-rsc-performance`, `$react-on-rails-update-changelog`, and\n  `$react-on-rails-release-train-issue-evaluation`.\n- `.claude/skills`: symlink to `.agents/skills` so Claude Code exposes the\n  repo-specific local skills kept by this checkout. Shared skills should come\n  from the installed shared pack, not this symlink.\n- `.agents/workflows/`: repo-local workflow files for Codex, GPT, and other\n  non-Claude tools when this checkout needs copy/paste workflows or overrides.\n- `.agents/bin/shared-skill-dir`: helper for workflow files that need a\n  repo-pinned helper copy or installed/shared skill directory.\n- `.agents/skills/*/bin`: repo-pinned shared helper scripts for workflows that\n  must run inside checkout-only or directory-restricted agent sessions. These\n  directories intentionally do not include duplicate shared `SKILL.md` files.\n- This repo deliberately does not adopt the pack's\n  `autonomous-merge-eligibility`, `merge-assurance`, `pr-merge-submit`, or\n  `autonomous-merge-closeout` helpers as repo-pinned merge or closeout gates.\n  When pack logic probes those absent helpers, its result is a structural\n  `UNKNOWN` for the unadopted helper chain, not evidence that a particular PR\n  is blocked. The adopted React on Rails merge seam is\n  `script/pr-merge-ledger <PR> --strict`, followed by the applicable phase and\n  merge-authority gates in this `AGENTS.md`. Shaka merge preference is `ask`;\n  GitHub remains authoritative for merge queue and required checks.\n- `.agents/.rubocop.yml`: lint seam for repo-local agent helper scripts. Keep it\n  aligned with `shakacode/agent-workflows/.rubocop.yml`, with only local\n  toolchain compatibility adjustments such as this repo's supported Ruby target.\n- `.agents/agent-workflow-drift.yml`: immutable source revision and reviewed\n  exact/overlay mapping for repo-pinned shared workflow files. Required CI checks\n  out that revision, runs the consumer-owned completeness test, then runs the\n  source pack's read-only drift checker. Update the manifest and hashes only as\n  part of a reviewed shared-workflow reconciliation.\n- If a tool or skill picker only exposes installed/global skills, treat those\n  skills as launchers. Installed/global skills never override this repo's\n  `AGENTS.md`; repo-local files win only when this repo explicitly names or\n  keeps a local copy/override.\n- Installed Shaka is the only seam validator. It validates\n  `.agents/agent-workflow.yml`; required CI pins the reviewed Shaka Git revision\n  and runs candidate-only validation. Pack management helpers such as `agent-workflows-status`,\n  `install-agent-workflows`, `upgrade-agent-workflows`, and `bin/validate`\n  remain transitional installed/shared-pack tools.\n- `.agents/bin/agent-workflow-drift-manifest-test.rb`: the consumer-owned\n  completeness boundary for pinned shared files. It governs explicit files and\n  whole source-pack prefixes, including reviewed source-only exclusions, so a\n  new upstream helper cannot silently escape the drift manifest.\n- `internal/contributor-info/agent-workflow-adoption.md`: React on Rails'\n  current Shaka seam boundary, transitional source-pack content, and validation\n- `internal/contributor-info/portable-agent-workflows-seam-design.md`: current\n  Shaka seam architecture and legacy retirement status\n- `internal/contributor-info/agent-pr-batch-skills.md`: contributor guide for choosing and sequencing `$plan-issue-triage`, `$plan-pr-batch`, and `$pr-batch`\n- `internal/contributor-info/multi-batch-operations.md`: operator guide for running multiple batches across machines, launch surfaces, and repos\n- `internal/contributor-info/issue-evaluation.md`: principles for deciding whether issues and proposed fixes are worth implementing\n- When deciding whether an issue or proposed fix is worth doing, use the\n  installed/shared `$evaluate-issue` skill; a short invocation is\n  `$evaluate-issue` or \"Is this issue worth fixing?\"\n- When deciding whether a React on Rails issue belongs on the active release\n  train (`release/X.Y.Z`, especially `release/17.0.0`) or should wait for\n  `main`, use the repo-local\n  `.agents/skills/react-on-rails-release-train-issue-evaluation/SKILL.md`; a\n  short invocation is `$react-on-rails-release-train-issue-evaluation`.\n- When the user wants a ready prompt for review-only GitHub issue triage or an\n  all-open-issues audit, use the installed/shared `$plan-issue-triage` skill; a\n  short invocation is `$plan-issue-triage` or \"Plan an issue triage\"\n- When the user wants a generated whole-surface issue/PR inventory, dependency\n  graph, and capacity-aware batch split, use the installed/shared `$triage`\n  skill; a short invocation is `$triage` or \"Run triage\"\n- When the user wants to choose issues or PRs for a future agent/Codex/Claude\n  batch, use the installed/shared `$plan-pr-batch` skill to produce a ready\n  `$pr-batch` goal; a short invocation is `$plan-pr-batch` or \"Plan a PR batch\"\n- When the user wants a multi-issue or multi-PR agent/Codex/Claude batch, use the\n  installed/shared `$pr-batch` skill; a short invocation is `$pr-batch`,\n  \"Run an agent batch\", \"Run a Codex batch\", or \"Run a Claude batch\"\n- When the user wants to stop or cancel an in-flight Codex/Claude batch (for example to relaunch it with updated skills), follow the **Cancelling Or Stopping A Batch** protocol in `.agents/workflows/pr-processing.md#cancelling-or-stopping-a-batch`; there is no short skill invocation for this coordinator action\n- When the user wants to audit merged batch work, missed reviews,\n  release-candidate risk, or possible bad merges, use the installed/shared\n  `$post-merge-audit` skill; reusable prompts live in\n  `.agents/workflows/post-merge-audit.md`\n- When the user wants an adversarial PR review, red-team review, Claude/Codex\n  comparison review, or a stricter pre-merge gate, use the installed/shared\n  `$adversarial-pr-review` skill; reusable prompts live in\n  `.agents/workflows/adversarial-pr-review.md`\n- When the user assigns an issue, PR, review-fix pass, or merge queue to an agent, follow `.agents/workflows/pr-processing.md`\n- When the user asks to address PR review comments, use the installed/shared\n  `$address-review` skill; `.agents/workflows/address-review.md` remains a\n  copy/paste prompt for assistants without skill support\n- When the user wants to manually verify a bug-fix PR by reproducing the failure\n  before the fix and confirming it is gone after (with captured evidence or\n  screenshots, optionally posted to the PR and issue), use the installed/shared\n  `$verify-pr-fix` skill; a short invocation is `$verify-pr-fix` or\n  \"manually verify this fix\"\n- When the user explicitly asks for destructive React on Rails stress testing,\n  use the repo-local `.agents/skills/stress-test/SKILL.md`; a short invocation is\n  `$stress-test`\n- When the user plans, implements, validates, or reviews RSC page performance\n  optimization in this repo, use the repo-local\n  `.agents/skills/optimize-rsc-performance/SKILL.md`; a short invocation is\n  `$optimize-rsc-performance`\n- When React on Rails release-train changelog work needs `target=release` or a\n  PR targeting `release/X.Y.Z`, use the repo-local\n  `.agents/skills/react-on-rails-update-changelog/SKILL.md`; a short invocation\n  is `$react-on-rails-update-changelog`. For ordinary mainline changelog updates\n  on `main`, use the installed/shared `$update-changelog` skill.\n- When a maintainer wants to run or inspect RC/beta validation across the demo\n  fleet, use the repo-local `.agents/skills/run-fleet-validation/SKILL.md`; a\n  short invocation is `$run-fleet-validation`. Its Ruby generator reads\n  `internal/contributor-info/demo-fleet.yml` and emits a complete lifecycle pack:\n  release/capability preflight, balanced subagent-driven hard-gate prompts,\n  report-only soft-track coverage, a durable result ledger/schema, independent\n  audit, authorized merge, reachability/tree-parity proof, and tracker closeout.\n  The same skill also generates public-only standing-health packs that verify\n  stable artifact currency, exact-default-head CI/smoke, review-app capability,\n  default-branch staleness, and the evaluated Dependabot v1 policy without\n  mutating demo repositories.\n- Default simplify model: `claude-opus-4-8`\n\n## External Flagship Demo Coordination\n\nThe public [`shakacode/react-on-rails-demo-flagship`](https://github.com/shakacode/react-on-rails-demo-flagship)\nrepo is the single clone-and-run flagship example for React on Rails Pro, React Server Components, React 19,\nstreaming SSR, the Node renderer, Shakapacker, and Rspack.\n\nUpdate that demo repo when changes in this monorepo affect the recommended user-facing Pro/RSC path, including:\n\n- React on Rails Pro or RSC generator output (`--pro`, `--rsc`, `react_on_rails:pro`, `react_on_rails:rsc`)\n- Pro installation, licensing, or \"license optional for evaluation/demo/non-production\" messaging\n- React, React DOM, `react-on-rails-rsc`, Shakapacker, Rspack, or Node renderer version pins/defaults\n- Auto-bundling behavior for `.client.` / `.server.` files or the `'use client'` directive\n- Streaming SSR/RSC helper usage, Node renderer configuration, Docker, or deployment defaults, including changes that\n  affect `bin/smoke` or Docker smoke-validation steps the demo repo runs during verification\n\nWhy: the flagship demo is the external proof that the Pro/RSC happy path works in a real Rails app. If this monorepo\nchanges the recommended path but the demo stays stale, agents and users will copy the wrong setup.\n\nKeep one flagship demo for now. Do not create a separate OSS-only flagship unless the user explicitly asks. The demo's\nREADME should document how to turn Pro/RSC off for comparison, but the default app should remain Pro + RSC.\nAdditional examples are valuable when they teach distinct repo-generation patterns, but they should not dilute or\ncompete with the flagship Pro/RSC path.\n\nThe machine-readable catalog of demos, tiers, and packages is `internal/contributor-info/demo-fleet.yml`.\n\nWhen updating the demo, make the change in a separate checkout/branch of `react-on-rails-demo-flagship`, regenerate and\ncommit lockfiles when dependency changes alter them, and do not mix demo repo commits into this monorepo. Use the\nJavaScript package manager declared by the demo repo (`packageManager` field or lockfile), then run focused validation\nsuch as:\n\n- `bundle install`\n- the lockfile install command for the declared package manager (`npm ci` for the current flagship)\n- `bin/shakapacker` or the equivalent asset build command documented by the demo repo\n- `bin/smoke` or Docker smoke validation\n\n## Canonical Agent Policy\n\n`AGENTS.md` is the canonical source for repository-wide agent rules:\n\n- Commands and test/lint workflow\n- Code style and formatting expectations\n- Git/PR boundaries and safety rules\n- Directory and documentation boundaries\n\nOther agent-facing docs (for example `CLAUDE.md`) should contain only tool-specific workflow notes and link back here.\nIf there is a conflict, `AGENTS.md` wins.\n\n## React on Rails Pro Guardrails\n\nReact on Rails Pro includes the Ruby Pro tree and the Pro npm packages:\n\n- `react_on_rails_pro/`\n- `packages/react-on-rails-pro/`\n- `packages/react-on-rails-pro-node-renderer/`\n\nBefore modifying, copying, vendoring, porting, or reimplementing Pro code from\nany of those paths, read and follow the Pro-specific guardrails in\n[`react_on_rails_pro/AGENTS.md`](react_on_rails_pro/AGENTS.md). Those guardrails\ndo not replace the Pro license or EULA; they tell agents when to stop and ask\nfor explicit licensing confirmation.\n\n## Freshness And Skill Resolution\n\nBefore planning issue/PR work, creating a new branch, or creating a new\nworktree, run:\n\n```bash\ngit fetch --prune origin main\n```\n\nBase new issue branches and new worktrees on the freshly fetched `origin/main`\nunless the user explicitly asks to reproduce an old SHA, continue an existing PR\nbranch, bisect, or work offline. Creating a new worktree does not fetch from\nGitHub by itself.\n\nAfter fetching, verify the `## Agent Workflow Configuration` seam before relying\non installed/shared skills for issue, PR, or batch work:\n\n```bash\nshaka seam check --root \"$(pwd)\" --ref \"$(git rev-parse origin/main)\"\n```\n\nThis trusted-ref check establishes workflow policy. Candidate CI validation uses\nthe separately pinned Shaka checkout with `--local`, which grants neither policy\nnor merge authority.\n\nIf a workflow explicitly needs a repo-local `.agents/skills/...` file, it should\nbe a repo-specific local skill such as `stress-test` or\n`optimize-rsc-performance`, release-branch changelog handling such as\n`react-on-rails-update-changelog`, a pinned helper `bin/` copy without\n`SKILL.md`, or a deliberate override. Shared workflow skills normally resolve\nfrom the installed/shared pack for picker-visible instructions. Helper commands\nmay resolve to repo-pinned `.agents/skills/<skill>/bin` copies so checkout-only\nor directory-restricted agents can still run repo workflows. If a required\nrepo-local skill or `.agents/workflows/...` file is missing in the checkout but\npresent on `origin/main`, update the worktree before continuing; if it is still\nmissing, report the repo workflow state as `UNKNOWN`.\n\nFor user-installed shared skills, check the installed pack with:\n\n```bash\nagent-workflows-status --host codex\n```\n\nUse `--host claude` for Claude Code installs. Upgrade the transitional shared\npack, then validate this repository with trusted Shaka:\n\n```bash\nupgrade-agent-workflows --host codex\nshaka seam check --root \"$(pwd)\" --ref \"$(git rev-parse origin/main)\"\n```\n\n<!-- prettier-ignore-start -->\n## Agent Workflow Configuration\n\nResolve the trusted default branch to an immutable commit. Load and validate\n`.agents/agent-workflow.yml` with the trusted installed `shaka seam check --ref REF`\ncommand. Run the fixed executable paths reported by that command from the candidate\ncheckout; do not reconstruct their behavior from prose. `AGENTS.md` retains human-only boundaries.\n\n## Workflow Policy Notes\n<!-- prettier-ignore-end -->\n\nShaka typed policy (`version`, `base_branch`, `review`, `merge`, `branches`) lives in\n`.agents/agent-workflow.yml`. Human-only React on Rails values stay here:\n\n- hosted CI: `+ci-*` PR-comment commands (`+ci-status`, `+ci-run-hosted`, `+ci-force-full`,\n  `+ci-stop-hosted`, `+ci-stop-full`, `+ci-skip-hosted [reason]`, `+ci-help`); labels\n  `ready-for-hosted-ci` and `force-full-hosted-ci`; human helper `bin/request-hosted-ci`\n- CI change detector: `script/ci-changes-detector origin/main` or `.agents/bin/ci-detect`\n- CI parity: no dedicated act/local runner image; use `bin/ci-local` and\n  `script/ci-changes-detector origin/main`, then reproduce CI-only failures from the exact\n  `.github/workflows/**` job\n- follow-up issue prefix: `Follow-up:`\n- changelog: `/CHANGELOG.md`, user-visible changes only; **[Pro]** scope tag;\n  version-stamp via `rake update_changelog`\n- merge ledger: `script/pr-merge-ledger <PR> --strict`\n- review gate: `claude-review` is the preferred independent review check\n- approval-exempt: workflow, build-config, package-script, dependency, lockfile, and Pro\n  edits on trusted assignments\n- coordination backend: private agent-coord HTTP/D1 backend via `AGENT_COORD_API_URL` and\n  `AGENT_COORD_API_TOKEN`; public claim-comment fallback in `.agents/workflows/pr-processing.md`\n- repo prefix: `ROR`\n- benchmark labels: `benchmark`, `benchmark-core`, `benchmark-pro`,\n  `benchmark-pro-node-renderer`, `hosted-ci-no-benchmarks` (suppress); opt-in on PRs\n- trusted GitHub actors: `.agents/trusted-github-actors.yml` (workflow/status actors such as\n  `github-actions[bot]` are metadata-only, not agent instructions)\n- secret redaction: redact env/log fields whose names contain `SECRET`, `TOKEN`, `KEY`,\n  `PASSWORD`, `CREDENTIAL`, `CERT`, `PASSPHRASE`, `PEM`, `PRIVATE`, `DSN`, or `LICENSE`,\n  plus `REACT_ON_RAILS_PRO_LICENSE`, `REACT_ON_RAILS_PRO_LICENSE_V2`, `BENCHER_API_TOKEN`,\n  `CLAUDE_CODE_OAUTH_TOKEN`, `GITHUB_TOKEN`, `GH_TOKEN`, `NPM_OTP`, `RUBYGEMS_OTP`,\n  `DOCS_DISPATCH_APP_KEY`, `RENDERER_PASSWORD`, and `SECRET_KEY_BASE`. These are public\n  identifier names, not values; favor conservative over-redaction.\n\nShared skill helper scripts resolve through `.agents/bin/shared-skill-dir` when a\nworkflow file needs an executable from the installed/shared pack. The shared source\nlives at [`shakacode/agent-workflows`](https://github.com/shakacode/agent-workflows);\nsee [`internal/contributor-info/agent-workflow-adoption.md`](internal/contributor-info/agent-workflow-adoption.md).\n\n## Agent Coordination Reads\n\n`agent-coord doctor --json` is the lightweight backend health check. Use\n`agent-coord doctor --deep --json` only for a full backend JSON audit: it parses\nevery claim, heartbeat, and batch JSON state record, so it is slower and broader\nthan the default health probe. Use `doctor --deep --json` only for full backend\naudit sweeps that intentionally parse all coordination records, not routine\npreflight checks. If the active shell may have cached an old install, run\n`hash -r 2>/dev/null || true` in a POSIX-style shell such as bash or zsh, or\nthat shell's rehash equivalent, then confirm via\n`command -v agent-coord || which agent-coord`.\n\nBefore dependency-sensitive actions, use targeted private coordination reads.\nThe direct `agent-coord` subcommands are:\n\n```bash\n# Specific issue/PR lane\nagent-coord status --repo shakacode/react_on_rails --target <issue-or-pr> --json\n\n# Batch lane/dependency state\nagent-coord status --batch-id <batch-id> --json\n```\n\nWhen the repo workflow calls for bounded reads, pass the same targeted status\nsubcommand through the installed/shared `pr-batch` helper so a slow private read\nbecomes explicit degraded state instead of an indefinite wait:\n\n```bash\nPR_BATCH_SKILL_DIR=\"${PR_BATCH_SKILL_DIR:-$(.agents/bin/shared-skill-dir pr-batch)}\"\n\n# Specific issue/PR lane\n\"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded\" --timeout 20 status --repo shakacode/react_on_rails --target <issue-or-pr> --json\n\n# Batch lane/dependency state\n\"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded\" --timeout 20 status --batch-id <batch-id> --json\n```\n\nDo not use broad `agent-coord status` for routine lane checks. Broad private\ncoordination reads are audit-only; if they time out, exit 1 (unexpected error),\nor exit 2, report private coordination as `UNKNOWN`/degraded and use structured\npublic claim comments only as advisory evidence. Any non-zero exit other than\n`CLAIM_REFUSED` (exit 3) is treated as `UNKNOWN`/degraded. If targeted status\nexits 0, private coordination state is authoritative. Refused claims\n(`CLAIM_REFUSED` / exit 3) remain hard stops for machine agents.\n\n## Commands\n\n```bash\n# Install dependencies\n# The committed root Gemfile.lock is generated with Bundler 4.0.10; use Bundler\n# 4.0.10 or newer before running root bundle commands.\nbundle && (cd react_on_rails && bundle) && pnpm install\n\n# The root Gemfile is intentionally limited to repo-wide lint, hook, release,\n# and benchmark script spec tooling. After changing package Gemfiles, run bundle\n# install in that package directory; after changing the root Gemfile, run bundle\n# install at the repo root to sync the tooling lock.\n\n# Build TypeScript → JavaScript\npnpm run build\n\n# Lint (MANDATORY before every commit)\n(cd react_on_rails && BUNDLE_GEMFILE=../Gemfile bundle exec rubocop) # OSS Ruby lint — CI-equivalent\n# Pro Ruby lint — CI-equivalent when Pro files or RuboCop config change\n(cd react_on_rails_pro && BUNDLE_GEMFILE=../Gemfile bundle exec rubocop --ignore-parent-exclusion)\npnpm run lint                                                    # JS/TS via ESLint\npnpm start format.listDifferent                                  # Check Prettier formatting\n(cd react_on_rails && bundle exec rake lint)                     # Package lint task (Ruby + JS + formatting)\n\n# Optional Ruby diagnostic from the repo root (not the CI contract)\nBUNDLE_GEMFILE=\"$(git rev-parse --show-toplevel)/Gemfile\" bundle exec rubocop\n\n# Auto-fix formatting\n(cd react_on_rails && bundle exec rake autofix) # Preferred for all formatting\n\n# Run tests\n(cd react_on_rails && bundle exec rake run_rspec:gem)   # Ruby unit tests (gem code)\n(cd react_on_rails && bundle exec rake run_rspec:dummy) # Ruby integration tests (dummy Rails app)\npnpm run test                        # JavaScript/TypeScript tests\n(cd react_on_rails && bundle exec rake)                 # Full package suite (lint + tests except examples)\n\n# Type checking\npnpm run type-check                  # TypeScript\n(cd react_on_rails && bundle exec rake rbs:validate) # RBS signatures\n\n# Additional test subsets\n(cd react_on_rails && bundle exec rake run_rspec) # All Ruby tests\n(cd react_on_rails && bundle exec rake all_but_examples) # All tests except generated examples\n(cd react_on_rails && bundle exec rake run_rspec:shakapacker_examples_basic) # Single example test\n\n# Documentation checks\nscript/check-docs-sidebar            # Validate docs sidebar coverage\nbin/check-links                      # Markdown link checks (requires lychee)\n\n# Full initial setup\nbundle && (cd react_on_rails && bundle) && pnpm install && \\\n  (cd react_on_rails && bundle exec rake shakapacker_examples:gen_all node_package && bundle exec rake)\n\n# CI/workflow linting\nactionlint                           # GitHub Actions lint\nyamllint .github/                    # YAML lint (do NOT run RuboCop on .yml files)\n\n# Dependency version updates\nrake shakapacker:update_version[9.6.1]  # Update shakapacker across the monorepo\n```\n\n### Updating Shakapacker\n\nUse `rake shakapacker:update_version[VERSION]` to update shakapacker across the entire monorepo. This single command updates all Gemfiles, package.json files, Gemfile.lock files, and pnpm-lock.yaml. Do **not** manually edit individual version references — always use the rake task to keep everything in sync.\n\nThe task handles Ruby version switching for apps that require a different Ruby version (set `RUBY_VERSION_MANAGER` to `rvm`, `rbenv`, `asdf`, or `mise` if needed; defaults to `rvm`). It continues gracefully if a single lock file update fails (e.g., due to a missing Ruby version).\n\nAfter Shakapacker version or default updates, check the External Flagship Demo Coordination section to decide whether the\nflagship demo needs the same change.\n\n## Testing\n\n- **Prefer local testing over CI iteration** — don't push \"hopeful\" fixes. Apply the **15-minute rule**: if 15 more minutes of local testing would catch the issue before CI does, spend the 15 minutes.\n- **Never claim a test is \"fixed\" without running it locally first.** Use \"This SHOULD fix...\" or \"Proposed fix (UNTESTED)\" for unverified changes.\n- **Automated tests passing is necessary but not sufficient.** If your changes affect how the app starts, builds, or serves, you must also verify the dev environment manually. See [Manual Dev Environment Testing](.claude/docs/manual-dev-environment-testing.md) for the full checklist.\n- **Ruby**: RSpec. Unit tests in `react_on_rails/spec/react_on_rails/`, integration tests via a dummy Rails app in `react_on_rails/spec/dummy/`.\n- **JavaScript/TypeScript**: Jest. Tests in `packages/react-on-rails/tests/`.\n- **E2E**: Playwright. Tests in `react_on_rails/spec/dummy/e2e/playwright/e2e/`. Run with `cd react_on_rails/spec/dummy && pnpm test:e2e`.\n- **The dummy app** (`react_on_rails/spec/dummy/`) is a full Rails application used for integration testing. Many tests require it.\n\nRun specific test files:\n\n```bash\n(cd react_on_rails && bundle exec rspec spec/react_on_rails/path/to/spec.rb)\ncd react_on_rails/spec/dummy && bundle exec rspec spec/path/to/spec.rb\n```\n\n## Project Structure\n\n| Directory                                        | Purpose                                                                                  |\n| ------------------------------------------------ | ---------------------------------------------------------------------------------------- |\n| `react_on_rails/lib/react_on_rails/`             | Ruby gem source — helpers, configuration, SSR pool, engine                               |\n| `react_on_rails/lib/generators/`                 | Rails generators for `react_on_rails:install`                                            |\n| `react_on_rails/spec/`                           | RSpec tests (unit + integration via dummy app)                                           |\n| `react_on_rails/spec/dummy/`                     | Full Rails app for integration testing and E2E                                           |\n| `packages/react-on-rails/src/`                   | TypeScript source — client-side React integration                                        |\n| `packages/react-on-rails/tests/`                 | Jest tests for the npm package                                                           |\n| `react_on_rails_pro/`                            | Pro package (separate gem + npm)                                                         |\n| `rakelib/`                                       | Rake task definitions                                                                    |\n| `docs/oss/`                                      | OSS documentation — published to the [ShakaCode website](https://reactonrails.com/docs/) |\n| `docs/pro/`                                      | Pro documentation — installation, configuration, RSC, node renderer, caching             |\n| `internal/contributor-info/`                     | Internal contributor docs (not published to the website)                                 |\n| `internal/planning/`                             | Internal planning docs, designs, and drafts                                              |\n| `internal/react_on_rails_pro/contributors-info/` | Internal Pro contributor docs (not published to the website)                             |\n| `internal/analysis/`                             | Investigation and analysis documents (kebab-case `.md` files)                            |\n\n## Code Style\n\n### Ruby (RuboCop)\n\nLine length max 120 characters. Run `bundle exec rubocop [file]` to check.\n\n**Line length — break long chains:**\n\n```ruby\n# Bad\ncontent = pack_content.gsub(/import.*from.*['\"];/, \"\").gsub(/ReactOnRails\\.register.*/, \"\")\n\n# Good\ncontent = pack_content.gsub(/import.*from.*['\"];/, \"\")\n                      .gsub(/ReactOnRails\\.register.*/, \"\")\n```\n\n**Named subjects in RSpec:**\n\n```ruby\n# Bad\nsubject { instance.method_name(arg) }\n\n# Good\nsubject(:method_result) { instance.method_name(arg) }\n```\n\n**Security violations — scope disable comments tightly:**\n\n```ruby\n# rubocop:disable Security/Eval\nexpect { evaluate(sanitized_content) }.not_to raise_error\n# rubocop:enable Security/Eval\n```\n\n### JavaScript/TypeScript\n\nPrettier handles all formatting. Never manually format — run `rake autofix` instead.\n\n### GitHub Actions\n\nFor GitHub Actions jobs that install Ruby gems, prefer `.github/actions/setup-bundle` over hand-written `actions/cache` plus `bundle install` steps.\nThe action validates a committed `Gemfile.lock`, configures the bundle path and Bundler version for later `bundle exec` steps,\nrestores/saves the gem cache, and supports non-frozen installs via `frozen: 'false'` for minimum-dependency jobs.\n\n## Git Workflow\n\n**Branch naming**: `type/descriptive-name` (e.g., `fix/ssr-hydration-mismatch`)\n\n**Commit messages**: Explain why, not what. One logical change per commit.\n\n**Squash merges**: When completing a GitHub squash merge, include the PR number in the squash commit title using the format `<PR title> (#<PR number>)`, for example `Docs: clarify rails new JavaScript skip flag (#3666)`. For CLI merges, pass `--subject \"<PR title> (#<PR number>)\"` to `gh pr merge --squash` and verify the title before confirming the merge.\n\n**PR creation**: Use `gh pr create` with a clear title, self-contained why/rationale summary, implementation summary, and test plan. If an issue exists, link it, but do not make reviewers open the issue to understand why the PR exists; include at least a short rationale in the PR description itself.\n\n**PR processing**: Before pushing a review-fix batch, opening a PR, marking a PR ready, requesting hosted CI, requesting force-full hosted CI, or reporting merge-readiness, run the agent PR processing flow in `.agents/workflows/pr-processing.md`: verify the work is worth doing, self-review the diff, run local validation, use the pre-push AI review and simplify gate when appropriate, batch fixes, and document exact verification evidence plus churn notes. After a PR and its reviews exist, wait for configured review agents and triage actionable review feedback before marking ready, requesting merge, or merging.\n\n**Hosted CI usage**: Do not use hosted CI as the first real validation pass. Prefer local checks first, then optimized hosted CI when the branch is ready for remote confirmation or final validation. Use the `+ci-*` PR comment commands for an auditable decision: `+ci-status` before deciding, `+ci-run-hosted` after the final push for optimized hosted CI, `+ci-force-full` only when a maintainer intentionally wants every hosted suite to bypass optimized selection, `+ci-stop-hosted` to return an iterating PR to the required gate, `+ci-stop-full` to remove only the force-full override, `+ci-skip-hosted [reason]` only with explicit maintainer approval for a low-risk waiver, and `+ci-help` when syntax is unclear. Put one `+ci-*` command per PR comment. Human/user-token label writes through `bin/request-hosted-ci` or `gh pr edit --add-label ready-for-hosted-ci` are valid, but workflow-token label writes are not a current-head trigger; automation must dispatch workflows explicitly or use `+ci-run-hosted`.\n\n**GitHub follow-up issues**: Follow-up issues are the exception. Prefer fixing or declining review feedback in the PR. If deferred work remains valuable, present one bundled deferred-work summary and ask whether to track it. Prefer an existing issue; otherwise create at most one bundled issue per PR unless the user explicitly approves more. New follow-up issue titles must begin with `Follow-up:`. Build multi-line issue bodies as Markdown files and pass them with `gh issue create --body-file`; do not pass escaped newline strings through `--body`.\n\n**GitHub Actions post-merge exercise follow-ups**: Semantic changes to `.github/workflows/**` or `.github/actions/**`\nare a standing exception to the default \"no follow-up issue\" rule. Before merge, link an existing tracking issue or\ncreate one bundled issue titled `Follow-up: Exercise GitHub Actions changes from PR #NNNN`. The issue must name the\nsource PR, changed workflow/action files, exact post-merge event or secondary verification PR to exercise, expected\nevidence, cleanup instructions for any verification-only PR, and owner if known. This is required for trigger,\npermission, job, matrix, condition, concurrency, secret, reusable-action, command-parsing, workflow-dispatch, or\nCI-routing behavior changes. It is not required for comments, docs, typo fixes, formatting-only changes, or\nnon-semantic actionlint cleanup when local validation evidence documents that classification.\n\n**Process gap disposition**: When an audit, review, or batch closeout finds a recurring process miss, do not add a prose-only rule by default. The issue plan or PR evidence must choose one mechanism target: `script`, `schema`, `checklist+replay`, or `park`, and record the motivating miss, replay evidence or park reason, and non-goal. `park` means the miss is plausible but not worth mechanizing now.\n\n### Release Version Ownership\n\n`bundle exec rake release[...]` owns the coordinated React on Rails product-version\nchange. For ordinary RC and final preparation, agents prepare and stamp\n`CHANGELOG.md`, but must not manually bump React on Rails' own gem/npm version\nfields or create the ordinary `Bump version to ...` commit. The release task\nupdates the OSS and Pro gem version files, the `version` field in all five\n`package.json` files, and the Ruby `Gemfile.lock` files in that generated commit.\nIt does not run `pnpm install` or regenerate `pnpm-lock.yaml`; workspace-protocol\ndependency conversion during npm publishing is temporary and is restored afterward.\n\nIf a release-preparation or dependency-pin PR changes dependency ranges or pins,\nregenerate the affected npm/pnpm lockfiles in that PR. Do not defer those lockfile\nupdates to the React on Rails product-version release task.\n\nPins for independently released dependencies are separate changes. For example,\npromoting `react-on-rails-rsc` from an RC to a stable version still requires a\nnormal reviewed and tested PR that updates the generator pin, package metadata,\nand affected lockfiles before cutting the next React on Rails RC. Do not confuse\nthat dependency update with manually bumping React on Rails' own version.\n\n## Maintainer Attention Contract\n\nMaintainer attention is for judgment, not for routine progress pings or\nmachine-checkable work. Agents working PRs, reviews, or batches must apply this\ncontract unless a maintainer explicitly narrows the run.\n\n- **Autonomous nits**: behavior-preserving `OPTIONAL` review nits may be fixed\n  inline without asking when they stay inside the PR scope, are low-risk, and are\n  before the final-candidate debounce point: once a merge-readiness review cycle\n  has started, do not introduce new nit commits that would restart it.\n  Inside the PR scope means the file, section, or workflow copy is already part\n  of the PR diff or directly cited by current review feedback. Cross-copy\n  consistency edits are in scope only when the paired section is already in the\n  PR diff or directly cited by current review feedback; this excludes unrelated\n  cleanup, other machine lanes, reserved files, generated output not already in\n  scope, and separate workflow files that merely discuss the same concept.\n  The final-candidate debounce point begins when the agent explicitly\n  designates the current head as merge-ready or the final candidate in a PR\n  body, PR comment, or handoff, or when the agent pushes after completing the\n  final local validation/review gate and records that push as the candidate.\n  Automatically queued checks from ordinary fix-phase pushes do not count unless\n  that push or check set has been declared as the final readiness gate. Earlier\n  incremental per-file checks during the fix phase do not count.\n  Behavior-preserving means wording, formatting, or mechanical\n  whitespace/punctuation cleanup that does not alter public APIs, generated\n  output, runtime behavior, validation scope, or the semantic meaning of any\n  section that has an unresolved review thread on it. Low-risk means local and\n  mechanically checkable, such as a formatter-confirmed cleanup; a rename that\n  requires searching all callers is not low-risk. Mechanical means deterministic\n  and local, such as rerunning a formatter or fixing whitespace introduced by\n  the nit, without reasoning about runtime behavior, callers, or policy.\n  Qualifying examples: typo/comment punctuation, whitespace or trailing comma\n  cleanup, or unambiguous documentation wording.\n  Disqualifying examples: renaming a public method or constant, changing\n  generated content, altering CI or release policy, adding/removing validation,\n  removing an import or `require` whose module side effects are not proven by a\n  dedicated tool or code inspection, or touching another lane's files. If the nit\n  is not worth fixing, record it as deferred or declined with rationale instead\n  of asking \"OK to fix this nit?\".\n  Autonomous deferred/declined nit replies must include `[auto-deferred]` on its\n  own line plus a one-line rationale, for example:\n  ```text\n  [auto-deferred]\n  Whitespace cleanup deferred to avoid restarting the final-candidate gate.\n  ```\n  Post the tag and rationale before resolving the review thread; do not resolve\n  an auto-deferred thread without that reply.\n  If an autonomous nit fix fails local validation or self-review, repair it in\n  the same batch only when the repair is still mechanical and in scope;\n  otherwise drop or revert that nit, record the failed validation and rationale,\n  and promote the underlying concern to `DISCUSS` only when it is a correctness\n  issue, regression risk, or explicit reviewer request.\n  Never push a failing autonomous nit or ask the maintainer to debug it.\n  Escalate only when the item changes behavior, expands scope, conflicts with\n  policy, or has unclear risk.\n- **CI-wait protocol**: while checks or review bots are running, do bounded\n  useful work such as self-review, local-only cleanup notes, documentation sync\n  that does not require pushing the active PR head, or another independent lane.\n  Do not introduce optional cleanup commits that restart current-head gates after\n  the final-candidate debounce point. Do not interrupt the maintainer for routine\n  \"CI is still running\", \"CI is green\", or \"review arrived\" updates. CI failures\n  and new `MUST-FIX`-tier review findings are not routine; surface them\n  immediately.\n- **One decision point per lane**: batch genuine judgment calls into one decision\n  block at lane completion or hard block. The block must include the question,\n  options, recommendation, evidence links or command output, and the next action\n  after an answer. Avoid \"see above\" decisions that require the maintainer to\n  reconstruct context.\n- **Self-verification before escalation**: anything provable by tests, lint,\n  screenshots, repro scripts, `gh` state, or code inspection must arrive with\n  that evidence attached. Use `UNKNOWN` for facts that could not be verified.\n- **Attention metric**: batch closeouts count human decision points per PR, with\n  a target of at most one for low-risk lanes: lanes with no `MUST-FIX` items,\n  no blocking questions, and only documentation, process, or mechanical changes.\n  Higher counts are reported as FYI process churn, not hidden in narrative\n  handoffs. Counts above target invite a later check on whether smaller lanes,\n  sharper scope, or better batching would reduce future churn; they are not a\n  hard failure by themselves. A human decision point is any question, option\n  selection, or confirmation directed at a maintainer that required direct input,\n  excluding git confirmations that safety rules or explicit local-only /\n  inspect-before-push instructions require after the maintainer already selected\n  the action, such as a required confirmation before a destructive force-push. A\n  standalone \"should I push this ordinary PR-iteration fix?\" question counts.\n  Report it as `Decision points: N` in the FYI section of the batch handoff.\n- **Confidence notes**: `merge_authority` has three states:\n  `auto_merge_when_gates_pass` is the only autonomous merge grant when the\n  current user or batch goal grants it and the release-mode rules permit it;\n  `ask` requires one confirmation before merging; and `none` grants no merge\n  authority. When `auto_merge_when_gates_pass` applies and the gate is met,\n  exercising it is the expected close-out — an authorized, gate-satisfied,\n  confident merge that is downgraded to a \"ready to merge\" recommendation is an\n  unfinished task, not a safe default. Before exercising merge authority,\n  complete the confidence note: validations and evidence are recorded, no\n  unresolved MUST-FIX threads remain, and any remaining `UNKNOWN` facts or\n  residual risk do not affect merge safety. Before a merge under\n  `auto_merge_when_gates_pass` or after an `ask` confirmation, the worker or\n  coordinator documents the merge qualifications in the PR description:\n  - which release-mode gate applied and that it was satisfied\n  - the confidence note: validated commands, evidence links, remaining\n    `UNKNOWN` facts, and residual risk\n  - the finalizer, when accelerated-RC requires one\n\n  This intentionally narrows merge-authority evidence to the PR description so\n  the merge decision is auditable from a single location. Use the issue or batch\n  handoff only for no-merge readiness evidence.\n\n  When merge authority is not granted, use the same confidence-note format for\n  merge-readiness evidence without merging:\n\n  ```text\n  Confidence note:\n  - Validated: <commands or checks run and outcomes>\n  - Evidence: <links to CI, screenshots, logs, or inline output>\n  - UNKNOWN: <facts that could not be verified, or \"none\">\n  - Residual risk: <one-line risk summary, or \"none\">\n  ```\n\n## Tracking Issues And Handoffs\n\nKeep the issue tracker for durable work — product features, real bugs, release\ngates — not for transient agent-process state. Process state accretes into\nclutter because \"open a tracker\" has no matching \"close it\" step.\n\n- **Do not open a new issue for a session handoff or a point-in-time audit.** A\n  handoff is transient coordination and an audit is a snapshot; neither is\n  durable backlog. Record a handoff as a comment on the relevant parent tracking\n  issue (for example the roadmap umbrella), or — if a dedicated agent-coordination\n  repo is in use — there. If the work has no parent umbrella (a standalone PR or a\n  one-off batch), put the handoff in the PR's final comment or description rather\n  than creating an issue to hold it. Append a point-in-time audit to the standing\n  release audit ledger in place. Never spawn a standalone `Handoff: ...` or\n  `Post-rc.N audit` issue.\n- **One durable ledger per recurring concern, updated in place.** Release audits\n  append to the standing release audit ledger; cross-agent coordination state —\n  the heartbeats and leases that signal which agent is live on which lane — lives\n  in the coordination-layer tracker. Do not create a sibling issue each cycle.\n  (At time of writing these are #4010 and #3974, but treat any such number as a\n  movable pointer: confirm it is still the live ledger before relying on it, and\n  update the pointer if it has been superseded — the same staleness this policy\n  guards against applies to the ledgers themselves.)\n- **Closure follows the work, not the opener.** A tracking issue closes when its\n  underlying PR/work lands, done by whoever finishes the work — not by whoever\n  opened the tracker. \"I opened it\" does not mean \"I must close it\": WIP can\n  outlive a session (lost chat, unanswered question, disconnect). The heartbeat —\n  the coordination layer's liveness signal that flags when no agent is active on a\n  lane — detects abandonment, and an unfinished PR is the real signal of remaining\n  work; act on the PR, not on a stale tracker.\n- **The 30-day test.** Before opening any tracking or meta issue, ask whether it\n  will still matter in 30 days. If not, it is a comment or a ledger entry, not an\n  issue.\n- **Sweep on sight.** When a handoff/audit/process-snapshot issue's underlying\n  work has landed or its snapshot is obsolete, close it — first consolidating any\n  still-live finding into the durable ledger or a real backlog issue. Verify it is\n  actually resolved or superseded before closing; never close a tracker that still\n  fronts unfinished work.\n\n## Release Mode And Auto-Merge Coordination\n\nUse the current release tracker to decide whether PRs are in normal development, accelerated RC, strict RC, or final-release mode. The tracker is the live source of truth for the mode; committed docs define how to interpret it.\n\nThe repo ships releases with a **release train**: `main` never freezes and keeps absorbing batch work, RCs are stabilized on an ephemeral `release/X.Y.Z` branch, and the final is the **last good RC promoted by dropping `-rc`** — not a re-cut from `main`. The merge gate an agent must apply is a function of the **target branch's release phase** (`beta` / `rc` / `final`); the phase composes with the mode below. See **[Release-Train Branching And Phase Gating](#release-train-branching-and-phase-gating)** for the phase→gate table and [`internal/contributor-info/release-train-runbook.md`](internal/contributor-info/release-train-runbook.md) for the full branching runbook.\n\n- An active tracker is an open release gate issue, usually found by the existing `release` and `TRACKING` labels or the `Release gate:` title. Also search closed release gate issues updated within the last 7 days before defaulting to `development`, so agents can detect stale trackers. The mode must be recorded in the issue body, not encoded by adding more labels.\n- Valid tracker modes are `development`, `accelerated-rc`, `strict-rc`, and `final-release`.\n- If no active tracker exists, assume `development` mode. This is not a blocker; it means the repo is moving toward the next beta/RC/final. If a release tracker was closed within the last 7 days and lacks a closing label/comment containing `Released` or `Superseded`, report `release-mode-stale-tracker` and do not auto-merge until a maintainer confirms the mode. A maintainer can resolve the stale signal with a PR or tracker comment such as `No active release, proceed`; verify the comment author has `write`, `maintain`, or `admin` permission before treating it as maintainer confirmation. Inspect tracker labels and comments with `gh issue view <tracker> --comments --json labels,comments` before deciding that the closing signal is absent.\n- If exactly one active tracker exists, read its `Agent Release Mode` block from the issue body. If the block is absent, use `strict-rc` and report the missing block.\n- If multiple active trackers have different final release targets, select the tracker matching the PR's target only when the target is unambiguous from the PR body, linked issue, branch, or release/changelog text. If the PR target is unclear, or if trackers for the selected target disagree about mode or canonical status, report `release-mode-conflict` and do not auto-merge until resolved. Do not let unrelated final-release targets block each other when the PR target is clear.\n- For duplicate trackers with the same final release target (the eventual semver without prerelease suffix, for example `v1.2.0.rc.1` and `v1.2.0.rc.2` share the `v1.2.0` target) and no conflicting mode, the oldest open tracker is canonical unless it explicitly says it is superseded by another tracker. If same-target trackers disagree about mode or canonical status, report `release-mode-conflict` and do not auto-merge until resolved. Agents may close clean duplicates only after preserving non-conflicting useful information in the canonical tracker and posting a closing comment that links to the canonical issue.\n- Agents do not auto-create release trackers. A maintainer creates one when entering accelerated RC, strict RC, or final-release coordination.\n- To avoid concurrent issue-body overwrites, re-read the tracker immediately before editing it. Prefer append-only comments for per-PR/batch status from concurrent agents, and only edit the tracker body when preserving the latest body content. If the latest tracker body changed in a way the agent cannot safely merge, post a comment with a `Tracker Update:` header containing the intended update and report the conflict; later agents must fetch tracker comments and consider both the latest body and latest unresolved `Tracker Update:` conflict comment before acting.\n\nReporting `release-mode-stale-tracker`, `release-mode-conflict`, or a missing\nrelease-mode block means posting a PR comment with a `Release Mode Block:`\nheader, the signal name, relevant tracker URLs, and the current decision.\n\nIn `development` and `strict-rc` modes, apply the standard merge qualification in the Review Workflow section; the accelerated-RC confidence block and auto-merge threshold do not apply. In `final-release` mode, do not auto-merge; apply standard merge qualification plus the final-release audit and explicit maintainer release decision below.\n\nDuring `accelerated-rc`, affected areas such as SSR, RSC, hydration, package release, generators, CI, benchmarks, and Pro/core boundaries do not cap confidence by themselves. They choose the validation checklist. Actual uncertainty, missing proof, failed checks, or unresolved findings lower confidence.\n\nAuto-merge during accelerated RC requires a finalized PR-body confidence block. The authoring agent may draft it, but a separate coordinator, finalizer, or review agent must finalize it. The finalizer must be a different GitHub account or named GitHub check/app identity than the PR authoring agent, verifiable from the git log or GitHub review/check record. Two sessions running under the same GitHub acco",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/plugin.json)"},"files":{"llms.txt":"# React on Rails\n\nReact on Rails integrates React with Ruby on Rails. Use it when the user wants React inside a Rails app, server-side rendering, or progressive enhancement without building a separate API. Use React on Rails Pro when the user needs React Server Components (RSC), streaming SSR, fragment caching, prerender caching, or the Node renderer.\n\nUse this file as the short machine-readable route map. Use `./llms-full.txt` for the expanded OSS reference and `./llms-full-pro.txt` for the expanded React on Rails Pro reference. Use `./AGENTS_USER_GUIDE.md` for the repo-oriented guide to the machine-readable layer.\n\n## Canonical entry points\n\n- Human docs overview: https://reactonrails.com/docs/\n- OSS docs hub: https://reactonrails.com/docs/introduction\n- Pro docs hub: https://reactonrails.com/docs/pro\n- RSC docs hub: https://reactonrails.com/docs/pro/react-server-components\n- Expanded machine-readable reference (OSS): `./llms-full.txt`\n- Expanded machine-readable reference (Pro): `./llms-full-pro.txt`\n- Agent usage guide: `./AGENTS_USER_GUIDE.md`\n\n## Package pairing\n\n- OSS: Ruby gem `react_on_rails` plus npm package `react-on-rails`\n- Pro: Ruby gem `react_on_rails_pro` plus npm package `react-on-rails-pro`\n- Optional Pro Node renderer: npm package `react-on-rails-pro-node-renderer`\n- Do not use `react_on_rails_pro` with the base `react-on-rails` npm package\n\n## Start here by task\n\n- New Rails app with React:\n  - Quick Start: https://reactonrails.com/docs/getting-started/quick-start\n  - Create a New App: https://reactonrails.com/docs/getting-started/create-react-on-rails-app\n  - Tutorial: https://reactonrails.com/docs/getting-started/tutorial\n- Existing Rails app:\n  - Install into an Existing Rails App: https://reactonrails.com/docs/getting-started/existing-rails-app\n  - Using React on Rails: https://reactonrails.com/docs/getting-started/using-react-on-rails\n  - Architecture overview: https://reactonrails.com/docs/core-concepts/how-react-on-rails-works\n- Styling:\n  - Tailwind CSS v4 recipe: https://reactonrails.com/docs/building-features/styling-with-tailwind\n- Choosing OSS vs Pro:\n  - OSS vs Pro: https://reactonrails.com/docs/getting-started/oss-vs-pro\n  - Pro hub: https://reactonrails.com/docs/pro\n  - Upgrade to Pro: https://reactonrails.com/docs/pro/upgrading-to-pro\n- React Server Components:\n  - RSC hub: https://reactonrails.com/docs/pro/react-server-components\n  - RSC tutorial: https://reactonrails.com/docs/pro/react-server-components/tutorial\n  - Add RSC to an existing Pro app: https://reactonrails.com/docs/pro/react-server-components/upgrading-existing-pro-app\n- Node renderer:\n  - Pro overview: https://reactonrails.com/docs/pro/node-renderer\n  - Technical basics: https://reactonrails.com/docs/building-features/node-renderer/basics\n  - JS configuration: https://reactonrails.com/docs/building-features/node-renderer/js-configuration\n- View transitions (experimental, unsupported):\n  - View Transitions recipe + Turbo interplay: https://reactonrails.com/docs/building-features/view-transitions\n- Hydration scheduling:\n  - Defer React root hydration/rendering until immediate, visible, or idle: https://reactonrails.com/docs/building-features/hydration-scheduling\n- Configuration and deployment:\n  - Configuration overview: https://reactonrails.com/docs/configuration\n  - Pro configuration: https://reactonrails.com/docs/configuration/configuration-pro\n  - Deployment: https://reactonrails.com/docs/deployment\n  - Security model and hardening: https://reactonrails.com/docs/deployment/security-model-and-hardening\n  - Troubleshooting: https://reactonrails.com/docs/deployment/troubleshooting\n- Upgrading and migration:\n  - Upgrading: https://reactonrails.com/docs/upgrading/upgrading-react-on-rails\n  - Pro coupled upgrade checklist (gem + npm + lockfiles, RC version formats, RSC manifest verification): https://reactonrails.com/docs/pro/updating#coupled-pro-upgrade-checklist\n  - OSS release notes: https://reactonrails.com/docs/upgrading/release-notes\n  - Pro release notes: https://reactonrails.com/docs/pro/release-notes\n  - Migrate from Next.js: https://reactonrails.com/docs/migrating/migrating-from-nextjs\n  - Migrate from react-rails: https://reactonrails.com/docs/migrating/migrating-from-react-rails\n  - Migrate from Inertia Rails: https://reactonrails.com/docs/migrating/migrating-from-inertia-rails\n  - Migrate to RSC: https://reactonrails.com/docs/migrating/migrating-to-rsc\n\n## Routing notes\n\n- Prefer the canonical Pro hub at `https://reactonrails.com/docs/pro`.\n- `https://reactonrails.com/docs/pro/react-on-rails-pro` currently redirects to the canonical Pro hub URL above.\n- Keep the machine-readable layer small: use the hub pages above first, then open only the task-specific docs you need.\n","CLAUDE.md":"# CLAUDE.md\n\nTool-specific guidance for Claude Code in this repository.\n\n## Source of Truth\n\n`AGENTS.md` is the canonical policy for:\n\n- Commands, tests, and lint workflow\n- Formatting and style requirements\n- Git/PR safety boundaries\n- Project directory boundaries\n\nIf this file conflicts with `AGENTS.md`, follow `AGENTS.md`.\n\n## Behavioral Defaults\n\n- When confident in your changes, **commit and push without asking for permission**. Always monitor CI after pushing, and use the `+ci-*` PR comment commands from `AGENTS.md` when asking maintainers to run, stop, or waive hosted CI.\n- **When `merge_authority` is `auto_merge_when_gates_pass` and the release-mode gate is satisfied, merge; do not stop at a recommendation.** `ask` requires one confirmation before merging, and `none` grants no merge authority. See `AGENTS.md` → Confidence notes for the full tri-state rule, confidence threshold, and required PR-description evidence.\n- Check `main` CI status at session start (injected by `.claude/hooks/main-ci-status.sh`) and again before `gh pr create` or pushing to `main`. See `AGENTS.md` → \"Main branch health\" for the decision framework when `main` is red.\n\n## Git Safety\n\n- **Clean rebase → `git push --force-with-lease` without asking.** When `git rebase origin/main` (or `git pull --rebase`) reports no conflicts, every commit is preserved — republishing is the expected workflow. Just push and report the result.\n- **Ask first when force-pushing in these cases:** you resolved rebase conflicts, you dropped/squashed/reordered commits, or the remote branch has commits you don't have locally.\n- **NEVER `git reset --hard`** on a branch with existing commits (yours or others'). This destroys work. Use a worktree or a new branch instead.\n- **NEVER force-push to `main` or `master`.**\n- If a rebase has conflicts you can't resolve cleanly, abort and ask the user how to proceed.\n\n## Claude-Specific Workflow\n\nUse these docs for Claude-oriented operational guidance:\n\n- `.claude/docs/avoiding-ci-failure-cycles.md`\n- `.claude/docs/replicating-ci-failures.md`\n- `.claude/docs/playwright-e2e-testing.md`\n- `.claude/docs/merge-conflict-workflow.md`\n- `.claude/docs/pr-splitting-strategy.md`\n- `.claude/docs/changelog-guidelines.md`\n- `.claude/docs/project-architecture.md`\n- `.claude/docs/rails-engine-nuances.md`\n- `.claude/docs/debugging-webpack.md`\n- `.claude/docs/rbs-type-checking.md`\n- `.claude/docs/conductor-compatibility.md`\n- `.claude/docs/testing-build-scripts.md`\n- `.claude/docs/main-health-monitoring.md`\n- `.claude/docs/managing-file-paths.md`\n- `.claude/docs/docs-competitive-landscape.md`\n- `.claude/docs/docs-templates.md`\n- `.claude/docs/manual-dev-environment-testing.md`\n- `.claude/docs/validating-node-renderer-changes.md`\n\nFor Pro-package specifics, also read `react_on_rails_pro/CLAUDE.md`.\n","AGENTS.md":"# AGENTS.md\n\nInstructions for AI coding agents working on the React on Rails codebase.\n\nReact on Rails is a Ruby gem + npm package that integrates React with Ruby on Rails, providing server-side rendering (SSR) via Node.js or ExecJS. This is a monorepo: the open-source gem lives at `react_on_rails/`, the npm package at `packages/react-on-rails/`, and the Pro package at `react_on_rails_pro/`.\n\n## Reusable Workflows\n\n- `AGENTS.md`: canonical entry point for agent instructions and workflow discovery\n- Shared agent workflow skills may be installed in the user's or agent's normal\n  skill directory and reused across repos; they must resolve repo-specific\n  values through this repo's `AGENTS.md` seam. The canonical shared source is\n  [`shakacode/agent-workflows`](https://github.com/shakacode/agent-workflows).\n  Use that repo's `agent-workflows-status` and `upgrade-agent-workflows`\n  helpers to keep installed Codex or Claude homes current.\n- When updating reusable agent workflows, skills, commands, or prompt\n  templates, first consider whether the change belongs in\n  `shakacode/agent-workflows` rather than this repo; keep local edits focused on\n  React on Rails-specific policy, seams, or overrides.\n- `.agents/skills/`: repo-specific skills, explicit overrides, and\n  repo-pinned helper `bin/` copies for checkout-only agent sessions. Keep shared\n  workflow `SKILL.md` files installed in the user's or agent's normal skill\n  directory; duplicating them here creates duplicate Codex skill picker entries.\n  Current repo-specific skills include `$stress-test`,\n  `$optimize-rsc-performance`, `$react-on-rails-update-changelog`, and\n  `$react-on-rails-release-train-issue-evaluation`.\n- `.claude/skills`: symlink to `.agents/skills` so Claude Code exposes the\n  repo-specific local skills kept by this checkout. Shared skills should come\n  from the installed shared pack, not this symlink.\n- `.agents/workflows/`: repo-local workflow files for Codex, GPT, and other\n  non-Claude tools when this checkout needs copy/paste workflows or overrides.\n- `.agents/bin/shared-skill-dir`: helper for workflow files that need a\n  repo-pinned helper copy or installed/shared skill directory.\n- `.agents/skills/*/bin`: repo-pinned shared helper scripts for workflows that\n  must run inside checkout-only or directory-restricted agent sessions. These\n  directories intentionally do not include duplicate shared `SKILL.md` files.\n- This repo deliberately does not adopt the pack's\n  `autonomous-merge-eligibility`, `merge-assurance`, `pr-merge-submit`, or\n  `autonomous-merge-closeout` helpers as repo-pinned merge or closeout gates.\n  When pack logic probes those absent helpers, its result is a structural\n  `UNKNOWN` for the unadopted helper chain, not evidence that a particular PR\n  is blocked. The adopted React on Rails merge seam is\n  `script/pr-merge-ledger <PR> --strict`, followed by the applicable phase and\n  merge-authority gates in this `AGENTS.md`. Shaka merge preference is `ask`;\n  GitHub remains authoritative for merge queue and required checks.\n- `.agents/.rubocop.yml`: lint seam for repo-local agent helper scripts. Keep it\n  aligned with `shakacode/agent-workflows/.rubocop.yml`, with only local\n  toolchain compatibility adjustments such as this repo's supported Ruby target.\n- `.agents/agent-workflow-drift.yml`: immutable source revision and reviewed\n  exact/overlay mapping for repo-pinned shared workflow files. Required CI checks\n  out that revision, runs the consumer-owned completeness test, then runs the\n  source pack's read-only drift checker. Update the manifest and hashes only as\n  part of a reviewed shared-workflow reconciliation.\n- If a tool or skill picker only exposes installed/global skills, treat those\n  skills as launchers. Installed/global skills never override this repo's\n  `AGENTS.md`; repo-local files win only when this repo explicitly names or\n  keeps a local copy/override.\n- Installed Shaka is the only seam validator. It validates\n  `.agents/agent-workflow.yml`; required CI pins the reviewed Shaka Git revision\n  and runs candidate-only validation. Pack management helpers such as `agent-workflows-status`,\n  `install-agent-workflows`, `upgrade-agent-workflows`, and `bin/validate`\n  remain transitional installed/shared-pack tools.\n- `.agents/bin/agent-workflow-drift-manifest-test.rb`: the consumer-owned\n  completeness boundary for pinned shared files. It governs explicit files and\n  whole source-pack prefixes, including reviewed source-only exclusions, so a\n  new upstream helper cannot silently escape the drift manifest.\n- `internal/contributor-info/agent-workflow-adoption.md`: React on Rails'\n  current Shaka seam boundary, transitional source-pack content, and validation\n- `internal/contributor-info/portable-agent-workflows-seam-design.md`: current\n  Shaka seam architecture and legacy retirement status\n- `internal/contributor-info/agent-pr-batch-skills.md`: contributor guide for choosing and sequencing `$plan-issue-triage`, `$plan-pr-batch`, and `$pr-batch`\n- `internal/contributor-info/multi-batch-operations.md`: operator guide for running multiple batches across machines, launch surfaces, and repos\n- `internal/contributor-info/issue-evaluation.md`: principles for deciding whether issues and proposed fixes are worth implementing\n- When deciding whether an issue or proposed fix is worth doing, use the\n  installed/shared `$evaluate-issue` skill; a short invocation is\n  `$evaluate-issue` or \"Is this issue worth fixing?\"\n- When deciding whether a React on Rails issue belongs on the active release\n  train (`release/X.Y.Z`, especially `release/17.0.0`) or should wait for\n  `main`, use the repo-local\n  `.agents/skills/react-on-rails-release-train-issue-evaluation/SKILL.md`; a\n  short invocation is `$react-on-rails-release-train-issue-evaluation`.\n- When the user wants a ready prompt for review-only GitHub issue triage or an\n  all-open-issues audit, use the installed/shared `$plan-issue-triage` skill; a\n  short invocation is `$plan-issue-triage` or \"Plan an issue triage\"\n- When the user wants a generated whole-surface issue/PR inventory, dependency\n  graph, and capacity-aware batch split, use the installed/shared `$triage`\n  skill; a short invocation is `$triage` or \"Run triage\"\n- When the user wants to choose issues or PRs for a future agent/Codex/Claude\n  batch, use the installed/shared `$plan-pr-batch` skill to produce a ready\n  `$pr-batch` goal; a short invocation is `$plan-pr-batch` or \"Plan a PR batch\"\n- When the user wants a multi-issue or multi-PR agent/Codex/Claude batch, use the\n  installed/shared `$pr-batch` skill; a short invocation is `$pr-batch`,\n  \"Run an agent batch\", \"Run a Codex batch\", or \"Run a Claude batch\"\n- When the user wants to stop or cancel an in-flight Codex/Claude batch (for example to relaunch it with updated skills), follow the **Cancelling Or Stopping A Batch** protocol in `.agents/workflows/pr-processing.md#cancelling-or-stopping-a-batch`; there is no short skill invocation for this coordinator action\n- When the user wants to audit merged batch work, missed reviews,\n  release-candidate risk, or possible bad merges, use the installed/shared\n  `$post-merge-audit` skill; reusable prompts live in\n  `.agents/workflows/post-merge-audit.md`\n- When the user wants an adversarial PR review, red-team review, Claude/Codex\n  comparison review, or a stricter pre-merge gate, use the installed/shared\n  `$adversarial-pr-review` skill; reusable prompts live in\n  `.agents/workflows/adversarial-pr-review.md`\n- When the user assigns an issue, PR, review-fix pass, or merge queue to an agent, follow `.agents/workflows/pr-processing.md`\n- When the user asks to address PR review comments, use the installed/shared\n  `$address-review` skill; `.agents/workflows/address-review.md` remains a\n  copy/paste prompt for assistants without skill support\n- When the user wants to manually verify a bug-fix PR by reproducing the failure\n  before the fix and confirming it is gone after (with captured evidence or\n  screenshots, optionally posted to the PR and issue), use the installed/shared\n  `$verify-pr-fix` skill; a short invocation is `$verify-pr-fix` or\n  \"manually verify this fix\"\n- When the user explicitly asks for destructive React on Rails stress testing,\n  use the repo-local `.agents/skills/stress-test/SKILL.md`; a short invocation is\n  `$stress-test`\n- When the user plans, implements, validates, or reviews RSC page performance\n  optimization in this repo, use the repo-local\n  `.agents/skills/optimize-rsc-performance/SKILL.md`; a short invocation is\n  `$optimize-rsc-performance`\n- When React on Rails release-train changelog work needs `target=release` or a\n  PR targeting `release/X.Y.Z`, use the repo-local\n  `.agents/skills/react-on-rails-update-changelog/SKILL.md`; a short invocation\n  is `$react-on-rails-update-changelog`. For ordinary mainline changelog updates\n  on `main`, use the installed/shared `$update-changelog` skill.\n- When a maintainer wants to run or inspect RC/beta validation across the demo\n  fleet, use the repo-local `.agents/skills/run-fleet-validation/SKILL.md`; a\n  short invocation is `$run-fleet-validation`. Its Ruby generator reads\n  `internal/contributor-info/demo-fleet.yml` and emits a complete lifecycle pack:\n  release/capability preflight, balanced subagent-driven hard-gate prompts,\n  report-only soft-track coverage, a durable result ledger/schema, independent\n  audit, authorized merge, reachability/tree-parity proof, and tracker closeout.\n  The same skill also generates public-only standing-health packs that verify\n  stable artifact currency, exact-default-head CI/smoke, review-app capability,\n  default-branch staleness, and the evaluated Dependabot v1 policy without\n  mutating demo repositories.\n- Default simplify model: `claude-opus-4-8`\n\n## External Flagship Demo Coordination\n\nThe public [`shakacode/react-on-rails-demo-flagship`](https://github.com/shakacode/react-on-rails-demo-flagship)\nrepo is the single clone-and-run flagship example for React on Rails Pro, React Server Components, React 19,\nstreaming SSR, the Node renderer, Shakapacker, and Rspack.\n\nUpdate that demo repo when changes in this monorepo affect the recommended user-facing Pro/RSC path, including:\n\n- React on Rails Pro or RSC generator output (`--pro`, `--rsc`, `react_on_rails:pro`, `react_on_rails:rsc`)\n- Pro installation, licensing, or \"license optional for evaluation/demo/non-production\" messaging\n- React, React DOM, `react-on-rails-rsc`, Shakapacker, Rspack, or Node renderer version pins/defaults\n- Auto-bundling behavior for `.client.` / `.server.` files or the `'use client'` directive\n- Streaming SSR/RSC helper usage, Node renderer configuration, Docker, or deployment defaults, including changes that\n  affect `bin/smoke` or Docker smoke-validation steps the demo repo runs during verification\n\nWhy: the flagship demo is the external proof that the Pro/RSC happy path works in a real Rails app. If this monorepo\nchanges the recommended path but the demo stays stale, agents and users will copy the wrong setup.\n\nKeep one flagship demo for now. Do not create a separate OSS-only flagship unless the user explicitly asks. The demo's\nREADME should document how to turn Pro/RSC off for comparison, but the default app should remain Pro + RSC.\nAdditional examples are valuable when they teach distinct repo-generation patterns, but they should not dilute or\ncompete with the flagship Pro/RSC path.\n\nThe machine-readable catalog of demos, tiers, and packages is `internal/contributor-info/demo-fleet.yml`.\n\nWhen updating the demo, make the change in a separate checkout/branch of `react-on-rails-demo-flagship`, regenerate and\ncommit lockfiles when dependency changes alter them, and do not mix demo repo commits into this monorepo. Use the\nJavaScript package manager declared by the demo repo (`packageManager` field or lockfile), then run focused validation\nsuch as:\n\n- `bundle install`\n- the lockfile install command for the declared package manager (`npm ci` for the current flagship)\n- `bin/shakapacker` or the equivalent asset build command documented by the demo repo\n- `bin/smoke` or Docker smoke validation\n\n## Canonical Agent Policy\n\n`AGENTS.md` is the canonical source for repository-wide agent rules:\n\n- Commands and test/lint workflow\n- Code style and formatting expectations\n- Git/PR boundaries and safety rules\n- Directory and documentation boundaries\n\nOther agent-facing docs (for example `CLAUDE.md`) should contain only tool-specific workflow notes and link back here.\nIf there is a conflict, `AGENTS.md` wins.\n\n## React on Rails Pro Guardrails\n\nReact on Rails Pro includes the Ruby Pro tree and the Pro npm packages:\n\n- `react_on_rails_pro/`\n- `packages/react-on-rails-pro/`\n- `packages/react-on-rails-pro-node-renderer/`\n\nBefore modifying, copying, vendoring, porting, or reimplementing Pro code from\nany of those paths, read and follow the Pro-specific guardrails in\n[`react_on_rails_pro/AGENTS.md`](react_on_rails_pro/AGENTS.md). Those guardrails\ndo not replace the Pro license or EULA; they tell agents when to stop and ask\nfor explicit licensing confirmation.\n\n## Freshness And Skill Resolution\n\nBefore planning issue/PR work, creating a new branch, or creating a new\nworktree, run:\n\n```bash\ngit fetch --prune origin main\n```\n\nBase new issue branches and new worktrees on the freshly fetched `origin/main`\nunless the user explicitly asks to reproduce an old SHA, continue an existing PR\nbranch, bisect, or work offline. Creating a new worktree does not fetch from\nGitHub by itself.\n\nAfter fetching, verify the `## Agent Workflow Configuration` seam before relying\non installed/shared skills for issue, PR, or batch work:\n\n```bash\nshaka seam check --root \"$(pwd)\" --ref \"$(git rev-parse origin/main)\"\n```\n\nThis trusted-ref check establishes workflow policy. Candidate CI validation uses\nthe separately pinned Shaka checkout with `--local`, which grants neither policy\nnor merge authority.\n\nIf a workflow explicitly needs a repo-local `.agents/skills/...` file, it should\nbe a repo-specific local skill such as `stress-test` or\n`optimize-rsc-performance`, release-branch changelog handling such as\n`react-on-rails-update-changelog`, a pinned helper `bin/` copy without\n`SKILL.md`, or a deliberate override. Shared workflow skills normally resolve\nfrom the installed/shared pack for picker-visible instructions. Helper commands\nmay resolve to repo-pinned `.agents/skills/<skill>/bin` copies so checkout-only\nor directory-restricted agents can still run repo workflows. If a required\nrepo-local skill or `.agents/workflows/...` file is missing in the checkout but\npresent on `origin/main`, update the worktree before continuing; if it is still\nmissing, report the repo workflow state as `UNKNOWN`.\n\nFor user-installed shared skills, check the installed pack with:\n\n```bash\nagent-workflows-status --host codex\n```\n\nUse `--host claude` for Claude Code installs. Upgrade the transitional shared\npack, then validate this repository with trusted Shaka:\n\n```bash\nupgrade-agent-workflows --host codex\nshaka seam check --root \"$(pwd)\" --ref \"$(git rev-parse origin/main)\"\n```\n\n<!-- prettier-ignore-start -->\n## Agent Workflow Configuration\n\nResolve the trusted default branch to an immutable commit. Load and validate\n`.agents/agent-workflow.yml` with the trusted installed `shaka seam check --ref REF`\ncommand. Run the fixed executable paths reported by that command from the candidate\ncheckout; do not reconstruct their behavior from prose. `AGENTS.md` retains human-only boundaries.\n\n## Workflow Policy Notes\n<!-- prettier-ignore-end -->\n\nShaka typed policy (`version`, `base_branch`, `review`, `merge`, `branches`) lives in\n`.agents/agent-workflow.yml`. Human-only React on Rails values stay here:\n\n- hosted CI: `+ci-*` PR-comment commands (`+ci-status`, `+ci-run-hosted`, `+ci-force-full`,\n  `+ci-stop-hosted`, `+ci-stop-full`, `+ci-skip-hosted [reason]`, `+ci-help`); labels\n  `ready-for-hosted-ci` and `force-full-hosted-ci`; human helper `bin/request-hosted-ci`\n- CI change detector: `script/ci-changes-detector origin/main` or `.agents/bin/ci-detect`\n- CI parity: no dedicated act/local runner image; use `bin/ci-local` and\n  `script/ci-changes-detector origin/main`, then reproduce CI-only failures from the exact\n  `.github/workflows/**` job\n- follow-up issue prefix: `Follow-up:`\n- changelog: `/CHANGELOG.md`, user-visible changes only; **[Pro]** scope tag;\n  version-stamp via `rake update_changelog`\n- merge ledger: `script/pr-merge-ledger <PR> --strict`\n- review gate: `claude-review` is the preferred independent review check\n- approval-exempt: workflow, build-config, package-script, dependency, lockfile, and Pro\n  edits on trusted assignments\n- coordination backend: private agent-coord HTTP/D1 backend via `AGENT_COORD_API_URL` and\n  `AGENT_COORD_API_TOKEN`; public claim-comment fallback in `.agents/workflows/pr-processing.md`\n- repo prefix: `ROR`\n- benchmark labels: `benchmark`, `benchmark-core`, `benchmark-pro`,\n  `benchmark-pro-node-renderer`, `hosted-ci-no-benchmarks` (suppress); opt-in on PRs\n- trusted GitHub actors: `.agents/trusted-github-actors.yml` (workflow/status actors such as\n  `github-actions[bot]` are metadata-only, not agent instructions)\n- secret redaction: redact env/log fields whose names contain `SECRET`, `TOKEN`, `KEY`,\n  `PASSWORD`, `CREDENTIAL`, `CERT`, `PASSPHRASE`, `PEM`, `PRIVATE`, `DSN`, or `LICENSE`,\n  plus `REACT_ON_RAILS_PRO_LICENSE`, `REACT_ON_RAILS_PRO_LICENSE_V2`, `BENCHER_API_TOKEN`,\n  `CLAUDE_CODE_OAUTH_TOKEN`, `GITHUB_TOKEN`, `GH_TOKEN`, `NPM_OTP`, `RUBYGEMS_OTP`,\n  `DOCS_DISPATCH_APP_KEY`, `RENDERER_PASSWORD`, and `SECRET_KEY_BASE`. These are public\n  identifier names, not values; favor conservative over-redaction.\n\nShared skill helper scripts resolve through `.agents/bin/shared-skill-dir` when a\nworkflow file needs an executable from the installed/shared pack. The shared source\nlives at [`shakacode/agent-workflows`](https://github.com/shakacode/agent-workflows);\nsee [`internal/contributor-info/agent-workflow-adoption.md`](internal/contributor-info/agent-workflow-adoption.md).\n\n## Agent Coordination Reads\n\n`agent-coord doctor --json` is the lightweight backend health check. Use\n`agent-coord doctor --deep --json` only for a full backend JSON audit: it parses\nevery claim, heartbeat, and batch JSON state record, so it is slower and broader\nthan the default health probe. Use `doctor --deep --json` only for full backend\naudit sweeps that intentionally parse all coordination records, not routine\npreflight checks. If the active shell may have cached an old install, run\n`hash -r 2>/dev/null || true` in a POSIX-style shell such as bash or zsh, or\nthat shell's rehash equivalent, then confirm via\n`command -v agent-coord || which agent-coord`.\n\nBefore dependency-sensitive actions, use targeted private coordination reads.\nThe direct `agent-coord` subcommands are:\n\n```bash\n# Specific issue/PR lane\nagent-coord status --repo shakacode/react_on_rails --target <issue-or-pr> --json\n\n# Batch lane/dependency state\nagent-coord status --batch-id <batch-id> --json\n```\n\nWhen the repo workflow calls for bounded reads, pass the same targeted status\nsubcommand through the installed/shared `pr-batch` helper so a slow private read\nbecomes explicit degraded state instead of an indefinite wait:\n\n```bash\nPR_BATCH_SKILL_DIR=\"${PR_BATCH_SKILL_DIR:-$(.agents/bin/shared-skill-dir pr-batch)}\"\n\n# Specific issue/PR lane\n\"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded\" --timeout 20 status --repo shakacode/react_on_rails --target <issue-or-pr> --json\n\n# Batch lane/dependency state\n\"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded\" --timeout 20 status --batch-id <batch-id> --json\n```\n\nDo not use broad `agent-coord status` for routine lane checks. Broad private\ncoordination reads are audit-only; if they time out, exit 1 (unexpected error),\nor exit 2, report private coordination as `UNKNOWN`/degraded and use structured\npublic claim comments only as advisory evidence. Any non-zero exit other than\n`CLAIM_REFUSED` (exit 3) is treated as `UNKNOWN`/degraded. If targeted status\nexits 0, private coordination state is authoritative. Refused claims\n(`CLAIM_REFUSED` / exit 3) remain hard stops for machine agents.\n\n## Commands\n\n```bash\n# Install dependencies\n# The committed root Gemfile.lock is generated with Bundler 4.0.10; use Bundler\n# 4.0.10 or newer before running root bundle commands.\nbundle && (cd react_on_rails && bundle) && pnpm install\n\n# The root Gemfile is intentionally limited to repo-wide lint, hook, release,\n# and benchmark script spec tooling. After changing package Gemfiles, run bundle\n# install in that package directory; after changing the root Gemfile, run bundle\n# install at the repo root to sync the tooling lock.\n\n# Build TypeScript → JavaScript\npnpm run build\n\n# Lint (MANDATORY before every commit)\n(cd react_on_rails && BUNDLE_GEMFILE=../Gemfile bundle exec rubocop) # OSS Ruby lint — CI-equivalent\n# Pro Ruby lint — CI-equivalent when Pro files or RuboCop config change\n(cd react_on_rails_pro && BUNDLE_GEMFILE=../Gemfile bundle exec rubocop --ignore-parent-exclusion)\npnpm run lint                                                    # JS/TS via ESLint\npnpm start format.listDifferent                                  # Check Prettier formatting\n(cd react_on_rails && bundle exec rake lint)                     # Package lint task (Ruby + JS + formatting)\n\n# Optional Ruby diagnostic from the repo root (not the CI contract)\nBUNDLE_GEMFILE=\"$(git rev-parse --show-toplevel)/Gemfile\" bundle exec rubocop\n\n# Auto-fix formatting\n(cd react_on_rails && bundle exec rake autofix) # Preferred for all formatting\n\n# Run tests\n(cd react_on_rails && bundle exec rake run_rspec:gem)   # Ruby unit tests (gem code)\n(cd react_on_rails && bundle exec rake run_rspec:dummy) # Ruby integration tests (dummy Rails app)\npnpm run test                        # JavaScript/TypeScript tests\n(cd react_on_rails && bundle exec rake)                 # Full package suite (lint + tests except examples)\n\n# Type checking\npnpm run type-check                  # TypeScript\n(cd react_on_rails && bundle exec rake rbs:validate) # RBS signatures\n\n# Additional test subsets\n(cd react_on_rails && bundle exec rake run_rspec) # All Ruby tests\n(cd react_on_rails && bundle exec rake all_but_examples) # All tests except generated examples\n(cd react_on_rails && bundle exec rake run_rspec:shakapacker_examples_basic) # Single example test\n\n# Documentation checks\nscript/check-docs-sidebar            # Validate docs sidebar coverage\nbin/check-links                      # Markdown link checks (requires lychee)\n\n# Full initial setup\nbundle && (cd react_on_rails && bundle) && pnpm install && \\\n  (cd react_on_rails && bundle exec rake shakapacker_examples:gen_all node_package && bundle exec rake)\n\n# CI/workflow linting\nactionlint                           # GitHub Actions lint\nyamllint .github/                    # YAML lint (do NOT run RuboCop on .yml files)\n\n# Dependency version updates\nrake shakapacker:update_version[9.6.1]  # Update shakapacker across the monorepo\n```\n\n### Updating Shakapacker\n\nUse `rake shakapacker:update_version[VERSION]` to update shakapacker across the entire monorepo. This single command updates all Gemfiles, package.json files, Gemfile.lock files, and pnpm-lock.yaml. Do **not** manually edit individual version references — always use the rake task to keep everything in sync.\n\nThe task handles Ruby version switching for apps that require a different Ruby version (set `RUBY_VERSION_MANAGER` to `rvm`, `rbenv`, `asdf`, or `mise` if needed; defaults to `rvm`). It continues gracefully if a single lock file update fails (e.g., due to a missing Ruby version).\n\nAfter Shakapacker version or default updates, check the External Flagship Demo Coordination section to decide whether the\nflagship demo needs the same change.\n\n## Testing\n\n- **Prefer local testing over CI iteration** — don't push \"hopeful\" fixes. Apply the **15-minute rule**: if 15 more minutes of local testing would catch the issue before CI does, spend the 15 minutes.\n- **Never claim a test is \"fixed\" without running it locally first.** Use \"This SHOULD fix...\" or \"Proposed fix (UNTESTED)\" for unverified changes.\n- **Automated tests passing is necessary but not sufficient.** If your changes affect how the app starts, builds, or serves, you must also verify the dev environment manually. See [Manual Dev Environment Testing](.claude/docs/manual-dev-environment-testing.md) for the full checklist.\n- **Ruby**: RSpec. Unit tests in `react_on_rails/spec/react_on_rails/`, integration tests via a dummy Rails app in `react_on_rails/spec/dummy/`.\n- **JavaScript/TypeScript**: Jest. Tests in `packages/react-on-rails/tests/`.\n- **E2E**: Playwright. Tests in `react_on_rails/spec/dummy/e2e/playwright/e2e/`. Run with `cd react_on_rails/spec/dummy && pnpm test:e2e`.\n- **The dummy app** (`react_on_rails/spec/dummy/`) is a full Rails application used for integration testing. Many tests require it.\n\nRun specific test files:\n\n```bash\n(cd react_on_rails && bundle exec rspec spec/react_on_rails/path/to/spec.rb)\ncd react_on_rails/spec/dummy && bundle exec rspec spec/path/to/spec.rb\n```\n\n## Project Structure\n\n| Directory                                        | Purpose                                                                                  |\n| ------------------------------------------------ | ---------------------------------------------------------------------------------------- |\n| `react_on_rails/lib/react_on_rails/`             | Ruby gem source — helpers, configuration, SSR pool, engine                               |\n| `react_on_rails/lib/generators/`                 | Rails generators for `react_on_rails:install`                                            |\n| `react_on_rails/spec/`                           | RSpec tests (unit + integration via dummy app)                                           |\n| `react_on_rails/spec/dummy/`                     | Full Rails app for integration testing and E2E                                           |\n| `packages/react-on-rails/src/`                   | TypeScript source — client-side React integration                                        |\n| `packages/react-on-rails/tests/`                 | Jest tests for the npm package                                                           |\n| `react_on_rails_pro/`                            | Pro package (separate gem + npm)                                                         |\n| `rakelib/`                                       | Rake task definitions                                                                    |\n| `docs/oss/`                                      | OSS documentation — published to the [ShakaCode website](https://reactonrails.com/docs/) |\n| `docs/pro/`                                      | Pro documentation — installation, configuration, RSC, node renderer, caching             |\n| `internal/contributor-info/`                     | Internal contributor docs (not published to the website)                                 |\n| `internal/planning/`                             | Internal planning docs, designs, and drafts                                              |\n| `internal/react_on_rails_pro/contributors-info/` | Internal Pro contributor docs (not published to the website)                             |\n| `internal/analysis/`                             | Investigation and analysis documents (kebab-case `.md` files)                            |\n\n## Code Style\n\n### Ruby (RuboCop)\n\nLine length max 120 characters. Run `bundle exec rubocop [file]` to check.\n\n**Line length — break long chains:**\n\n```ruby\n# Bad\ncontent = pack_content.gsub(/import.*from.*['\"];/, \"\").gsub(/ReactOnRails\\.register.*/, \"\")\n\n# Good\ncontent = pack_content.gsub(/import.*from.*['\"];/, \"\")\n                      .gsub(/ReactOnRails\\.register.*/, \"\")\n```\n\n**Named subjects in RSpec:**\n\n```ruby\n# Bad\nsubject { instance.method_name(arg) }\n\n# Good\nsubject(:method_result) { instance.method_name(arg) }\n```\n\n**Security violations — scope disable comments tightly:**\n\n```ruby\n# rubocop:disable Security/Eval\nexpect { evaluate(sanitized_content) }.not_to raise_error\n# rubocop:enable Security/Eval\n```\n\n### JavaScript/TypeScript\n\nPrettier handles all formatting. Never manually format — run `rake autofix` instead.\n\n### GitHub Actions\n\nFor GitHub Actions jobs that install Ruby gems, prefer `.github/actions/setup-bundle` over hand-written `actions/cache` plus `bundle install` steps.\nThe action validates a committed `Gemfile.lock`, configures the bundle path and Bundler version for later `bundle exec` steps,\nrestores/saves the gem cache, and supports non-frozen installs via `frozen: 'false'` for minimum-dependency jobs.\n\n## Git Workflow\n\n**Branch naming**: `type/descriptive-name` (e.g., `fix/ssr-hydration-mismatch`)\n\n**Commit messages**: Explain why, not what. One logical change per commit.\n\n**Squash merges**: When completing a GitHub squash merge, include the PR number in the squash commit title using the format `<PR title> (#<PR number>)`, for example `Docs: clarify rails new JavaScript skip flag (#3666)`. For CLI merges, pass `--subject \"<PR title> (#<PR number>)\"` to `gh pr merge --squash` and verify the title before confirming the merge.\n\n**PR creation**: Use `gh pr create` with a clear title, self-contained why/rationale summary, implementation summary, and test plan. If an issue exists, link it, but do not make reviewers open the issue to understand why the PR exists; include at least a short rationale in the PR description itself.\n\n**PR processing**: Before pushing a review-fix batch, opening a PR, marking a PR ready, requesting hosted CI, requesting force-full hosted CI, or reporting merge-readiness, run the agent PR processing flow in `.agents/workflows/pr-processing.md`: verify the work is worth doing, self-review the diff, run local validation, use the pre-push AI review and simplify gate when appropriate, batch fixes, and document exact verification evidence plus churn notes. After a PR and its reviews exist, wait for configured review agents and triage actionable review feedback before marking ready, requesting merge, or merging.\n\n**Hosted CI usage**: Do not use hosted CI as the first real validation pass. Prefer local checks first, then optimized hosted CI when the branch is ready for remote confirmation or final validation. Use the `+ci-*` PR comment commands for an auditable decision: `+ci-status` before deciding, `+ci-run-hosted` after the final push for optimized hosted CI, `+ci-force-full` only when a maintainer intentionally wants every hosted suite to bypass optimized selection, `+ci-stop-hosted` to return an iterating PR to the required gate, `+ci-stop-full` to remove only the force-full override, `+ci-skip-hosted [reason]` only with explicit maintainer approval for a low-risk waiver, and `+ci-help` when syntax is unclear. Put one `+ci-*` command per PR comment. Human/user-token label writes through `bin/request-hosted-ci` or `gh pr edit --add-label ready-for-hosted-ci` are valid, but workflow-token label writes are not a current-head trigger; automation must dispatch workflows explicitly or use `+ci-run-hosted`.\n\n**GitHub follow-up issues**: Follow-up issues are the exception. Prefer fixing or declining review feedback in the PR. If deferred work remains valuable, present one bundled deferred-work summary and ask whether to track it. Prefer an existing issue; otherwise create at most one bundled issue per PR unless the user explicitly approves more. New follow-up issue titles must begin with `Follow-up:`. Build multi-line issue bodies as Markdown files and pass them with `gh issue create --body-file`; do not pass escaped newline strings through `--body`.\n\n**GitHub Actions post-merge exercise follow-ups**: Semantic changes to `.github/workflows/**` or `.github/actions/**`\nare a standing exception to the default \"no follow-up issue\" rule. Before merge, link an existing tracking issue or\ncreate one bundled issue titled `Follow-up: Exercise GitHub Actions changes from PR #NNNN`. The issue must name the\nsource PR, changed workflow/action files, exact post-merge event or secondary verification PR to exercise, expected\nevidence, cleanup instructions for any verification-only PR, and owner if known. This is required for trigger,\npermission, job, matrix, condition, concurrency, secret, reusable-action, command-parsing, workflow-dispatch, or\nCI-routing behavior changes. It is not required for comments, docs, typo fixes, formatting-only changes, or\nnon-semantic actionlint cleanup when local validation evidence documents that classification.\n\n**Process gap disposition**: When an audit, review, or batch closeout finds a recurring process miss, do not add a prose-only rule by default. The issue plan or PR evidence must choose one mechanism target: `script`, `schema`, `checklist+replay`, or `park`, and record the motivating miss, replay evidence or park reason, and non-goal. `park` means the miss is plausible but not worth mechanizing now.\n\n### Release Version Ownership\n\n`bundle exec rake release[...]` owns the coordinated React on Rails product-version\nchange. For ordinary RC and final preparation, agents prepare and stamp\n`CHANGELOG.md`, but must not manually bump React on Rails' own gem/npm version\nfields or create the ordinary `Bump version to ...` commit. The release task\nupdates the OSS and Pro gem version files, the `version` field in all five\n`package.json` files, and the Ruby `Gemfile.lock` files in that generated commit.\nIt does not run `pnpm install` or regenerate `pnpm-lock.yaml`; workspace-protocol\ndependency conversion during npm publishing is temporary and is restored afterward.\n\nIf a release-preparation or dependency-pin PR changes dependency ranges or pins,\nregenerate the affected npm/pnpm lockfiles in that PR. Do not defer those lockfile\nupdates to the React on Rails product-version release task.\n\nPins for independently released dependencies are separate changes. For example,\npromoting `react-on-rails-rsc` from an RC to a stable version still requires a\nnormal reviewed and tested PR that updates the generator pin, package metadata,\nand affected lockfiles before cutting the next React on Rails RC. Do not confuse\nthat dependency update with manually bumping React on Rails' own version.\n\n## Maintainer Attention Contract\n\nMaintainer attention is for judgment, not for routine progress pings or\nmachine-checkable work. Agents working PRs, reviews, or batches must apply this\ncontract unless a maintainer explicitly narrows the run.\n\n- **Autonomous nits**: behavior-preserving `OPTIONAL` review nits may be fixed\n  inline without asking when they stay inside the PR scope, are low-risk, and are\n  before the final-candidate debounce point: once a merge-readiness review cycle\n  has started, do not introduce new nit commits that would restart it.\n  Inside the PR scope means the file, section, or workflow copy is already part\n  of the PR diff or directly cited by current review feedback. Cross-copy\n  consistency edits are in scope only when the paired section is already in the\n  PR diff or directly cited by current review feedback; this excludes unrelated\n  cleanup, other machine lanes, reserved files, generated output not already in\n  scope, and separate workflow files that merely discuss the same concept.\n  The final-candidate debounce point begins when the agent explicitly\n  designates the current head as merge-ready or the final candidate in a PR\n  body, PR comment, or handoff, or when the agent pushes after completing the\n  final local validation/review gate and records that push as the candidate.\n  Automatically queued checks from ordinary fix-phase pushes do not count unless\n  that push or check set has been declared as the final readiness gate. Earlier\n  incremental per-file checks during the fix phase do not count.\n  Behavior-preserving means wording, formatting, or mechanical\n  whitespace/punctuation cleanup that does not alter public APIs, generated\n  output, runtime behavior, validation scope, or the semantic meaning of any\n  section that has an unresolved review thread on it. Low-risk means local and\n  mechanically checkable, such as a formatter-confirmed cleanup; a rename that\n  requires searching all callers is not low-risk. Mechanical means deterministic\n  and local, such as rerunning a formatter or fixing whitespace introduced by\n  the nit, without reasoning about runtime behavior, callers, or policy.\n  Qualifying examples: typo/comment punctuation, whitespace or trailing comma\n  cleanup, or unambiguous documentation wording.\n  Disqualifying examples: renaming a public method or constant, changing\n  generated content, altering CI or release policy, adding/removing validation,\n  removing an import or `require` whose module side effects are not proven by a\n  dedicated tool or code inspection, or touching another lane's files. If the nit\n  is not worth fixing, record it as deferred or declined with rationale instead\n  of asking \"OK to fix this nit?\".\n  Autonomous deferred/declined nit replies must include `[auto-deferred]` on its\n  own line plus a one-line rationale, for example:\n  ```text\n  [auto-deferred]\n  Whitespace cleanup deferred to avoid restarting the final-candidate gate.\n  ```\n  Post the tag and rationale before resolving the review thread; do not resolve\n  an auto-deferred thread without that reply.\n  If an autonomous nit fix fails local validation or self-review, repair it in\n  the same batch only when the repair is still mechanical and in scope;\n  otherwise drop or revert that nit, record the failed validation and rationale,\n  and promote the underlying concern to `DISCUSS` only when it is a correctness\n  issue, regression risk, or explicit reviewer request.\n  Never push a failing autonomous nit or ask the maintainer to debug it.\n  Escalate only when the item changes behavior, expands scope, conflicts with\n  policy, or has unclear risk.\n- **CI-wait protocol**: while checks or review bots are running, do bounded\n  useful work such as self-review, local-only cleanup notes, documentation sync\n  that does not require pushing the active PR head, or another independent lane.\n  Do not introduce optional cleanup commits that restart current-head gates after\n  the final-candidate debounce point. Do not interrupt the maintainer for routine\n  \"CI is still running\", \"CI is green\", or \"review arrived\" updates. CI failures\n  and new `MUST-FIX`-tier review findings are not routine; surface them\n  immediately.\n- **One decision point per lane**: batch genuine judgment calls into one decision\n  block at lane completion or hard block. The block must include the question,\n  options, recommendation, evidence links or command output, and the next action\n  after an answer. Avoid \"see above\" decisions that require the maintainer to\n  reconstruct context.\n- **Self-verification before escalation**: anything provable by tests, lint,\n  screenshots, repro scripts, `gh` state, or code inspection must arrive with\n  that evidence attached. Use `UNKNOWN` for facts that could not be verified.\n- **Attention metric**: batch closeouts count human decision points per PR, with\n  a target of at most one for low-risk lanes: lanes with no `MUST-FIX` items,\n  no blocking questions, and only documentation, process, or mechanical changes.\n  Higher counts are reported as FYI process churn, not hidden in narrative\n  handoffs. Counts above target invite a later check on whether smaller lanes,\n  sharper scope, or better batching would reduce future churn; they are not a\n  hard failure by themselves. A human decision point is any question, option\n  selection, or confirmation directed at a maintainer that required direct input,\n  excluding git confirmations that safety rules or explicit local-only /\n  inspect-before-push instructions require after the maintainer already selected\n  the action, such as a required confirmation before a destructive force-push. A\n  standalone \"should I push this ordinary PR-iteration fix?\" question counts.\n  Report it as `Decision points: N` in the FYI section of the batch handoff.\n- **Confidence notes**: `merge_authority` has three states:\n  `auto_merge_when_gates_pass` is the only autonomous merge grant when the\n  current user or batch goal grants it and the release-mode rules permit it;\n  `ask` requires one confirmation before merging; and `none` grants no merge\n  authority. When `auto_merge_when_gates_pass` applies and the gate is met,\n  exercising it is the expected close-out — an authorized, gate-satisfied,\n  confident merge that is downgraded to a \"ready to merge\" recommendation is an\n  unfinished task, not a safe default. Before exercising merge authority,\n  complete the confidence note: validations and evidence are recorded, no\n  unresolved MUST-FIX threads remain, and any remaining `UNKNOWN` facts or\n  residual risk do not affect merge safety. Before a merge under\n  `auto_merge_when_gates_pass` or after an `ask` confirmation, the worker or\n  coordinator documents the merge qualifications in the PR description:\n  - which release-mode gate applied and that it was satisfied\n  - the confidence note: validated commands, evidence links, remaining\n    `UNKNOWN` facts, and residual risk\n  - the finalizer, when accelerated-RC requires one\n\n  This intentionally narrows merge-authority evidence to the PR description so\n  the merge decision is auditable from a single location. Use the issue or batch\n  handoff only for no-merge readiness evidence.\n\n  When merge authority is not granted, use the same confidence-note format for\n  merge-readiness evidence without merging:\n\n  ```text\n  Confidence note:\n  - Validated: <commands or checks run and outcomes>\n  - Evidence: <links to CI, screenshots, logs, or inline output>\n  - UNKNOWN: <facts that could not be verified, or \"none\">\n  - Residual risk: <one-line risk summary, or \"none\">\n  ```\n\n## Tracking Issues And Handoffs\n\nKeep the issue tracker for durable work — product features, real bugs, release\ngates — not for transient agent-process state. Process state accretes into\nclutter because \"open a tracker\" has no matching \"close it\" step.\n\n- **Do not open a new issue for a session handoff or a point-in-time audit.** A\n  handoff is transient coordination and an audit is a snapshot; neither is\n  durable backlog. Record a handoff as a comment on the relevant parent tracking\n  issue (for example the roadmap umbrella), or — if a dedicated agent-coordination\n  repo is in use — there. If the work has no parent umbrella (a standalone PR or a\n  one-off batch), put the handoff in the PR's final comment or description rather\n  than creating an issue to hold it. Append a point-in-time audit to the standing\n  release audit ledger in place. Never spawn a standalone `Handoff: ...` or\n  `Post-rc.N audit` issue.\n- **One durable ledger per recurring concern, updated in place.** Release audits\n  append to the standing release audit ledger; cross-agent coordination state —\n  the heartbeats and leases that signal which agent is live on which lane — lives\n  in the coordination-layer tracker. Do not create a sibling issue each cycle.\n  (At time of writing these are #4010 and #3974, but treat any such number as a\n  movable pointer: confirm it is still the live ledger before relying on it, and\n  update the pointer if it has been superseded — the same staleness this policy\n  guards against applies to the ledgers themselves.)\n- **Closure follows the work, not the opener.** A tracking issue closes when its\n  underlying PR/work lands, done by whoever finishes the work — not by whoever\n  opened the tracker. \"I opened it\" does not mean \"I must close it\": WIP can\n  outlive a session (lost chat, unanswered question, disconnect). The heartbeat —\n  the coordination layer's liveness signal that flags when no agent is active on a\n  lane — detects abandonment, and an unfinished PR is the real signal of remaining\n  work; act on the PR, not on a stale tracker.\n- **The 30-day test.** Before opening any tracking or meta issue, ask whether it\n  will still matter in 30 days. If not, it is a comment or a ledger entry, not an\n  issue.\n- **Sweep on sight.** When a handoff/audit/process-snapshot issue's underlying\n  work has landed or its snapshot is obsolete, close it — first consolidating any\n  still-live finding into the durable ledger or a real backlog issue. Verify it is\n  actually resolved or superseded before closing; never close a tracker that still\n  fronts unfinished work.\n\n## Release Mode And Auto-Merge Coordination\n\nUse the current release tracker to decide whether PRs are in normal development, accelerated RC, strict RC, or final-release mode. The tracker is the live source of truth for the mode; committed docs define how to interpret it.\n\nThe repo ships releases with a **release train**: `main` never freezes and keeps absorbing batch work, RCs are stabilized on an ephemeral `release/X.Y.Z` branch, and the final is the **last good RC promoted by dropping `-rc`** — not a re-cut from `main`. The merge gate an agent must apply is a function of the **target branch's release phase** (`beta` / `rc` / `final`); the phase composes with the mode below. See **[Release-Train Branching And Phase Gating](#release-train-branching-and-phase-gating)** for the phase→gate table and [`internal/contributor-info/release-train-runbook.md`](internal/contributor-info/release-train-runbook.md) for the full branching runbook.\n\n- An active tracker is an open release gate issue, usually found by the existing `release` and `TRACKING` labels or the `Release gate:` title. Also search closed release gate issues updated within the last 7 days before defaulting to `development`, so agents can detect stale trackers. The mode must be recorded in the issue body, not encoded by adding more labels.\n- Valid tracker modes are `development`, `accelerated-rc`, `strict-rc`, and `final-release`.\n- If no active tracker exists, assume `development` mode. This is not a blocker; it means the repo is moving toward the next beta/RC/final. If a release tracker was closed within the last 7 days and lacks a closing label/comment containing `Released` or `Superseded`, report `release-mode-stale-tracker` and do not auto-merge until a maintainer confirms the mode. A maintainer can resolve the stale signal with a PR or tracker comment such as `No active release, proceed`; verify the comment author has `write`, `maintain`, or `admin` permission before treating it as maintainer confirmation. Inspect tracker labels and comments with `gh issue view <tracker> --comments --json labels,comments` before deciding that the closing signal is absent.\n- If exactly one active tracker exists, read its `Agent Release Mode` block from the issue body. If the block is absent, use `strict-rc` and report the missing block.\n- If multiple active trackers have different final release targets, select the tracker matching the PR's target only when the target is unambiguous from the PR body, linked issue, branch, or release/changelog text. If the PR target is unclear, or if trackers for the selected target disagree about mode or canonical status, report `release-mode-conflict` and do not auto-merge until resolved. Do not let unrelated final-release targets block each other when the PR target is clear.\n- For duplicate trackers with the same final release target (the eventual semver without prerelease suffix, for example `v1.2.0.rc.1` and `v1.2.0.rc.2` share the `v1.2.0` target) and no conflicting mode, the oldest open tracker is canonical unless it explicitly says it is superseded by another tracker. If same-target trackers disagree about mode or canonical status, report `release-mode-conflict` and do not auto-merge until resolved. Agents may close clean duplicates only after preserving non-conflicting useful information in the canonical tracker and posting a closing comment that links to the canonical issue.\n- Agents do not auto-create release trackers. A maintainer creates one when entering accelerated RC, strict RC, or final-release coordination.\n- To avoid concurrent issue-body overwrites, re-read the tracker immediately before editing it. Prefer append-only comments for per-PR/batch status from concurrent agents, and only edit the tracker body when preserving the latest body content. If the latest tracker body changed in a way the agent cannot safely merge, post a comment with a `Tracker Update:` header containing the intended update and report the conflict; later agents must fetch tracker comments and consider both the latest body and latest unresolved `Tracker Update:` conflict comment before acting.\n\nReporting `release-mode-stale-tracker`, `release-mode-conflict`, or a missing\nrelease-mode block means posting a PR comment with a `Release Mode Block:`\nheader, the signal name, relevant tracker URLs, and the current decision.\n\nIn `development` and `strict-rc` modes, apply the standard merge qualification in the Review Workflow section; the accelerated-RC confidence block and auto-merge threshold do not apply. In `final-release` mode, do not auto-merge; apply standard merge qualification plus the final-release audit and explicit maintainer release decision below.\n\nDuring `accelerated-rc`, affected areas such as SSR, RSC, hydration, package release, generators, CI, benchmarks, and Pro/core boundaries do not cap confidence by themselves. They choose the validation checklist. Actual uncertainty, missing proof, failed checks, or unresolved findings lower confidence.\n\nAuto-merge during accelerated RC requires a finalized PR-body confidence block. The authoring agent may draft it, but a separate coordinator, finalizer, or review agent must finalize it. The finalizer must be a different GitHub account or named GitHub check/app identity than the PR authoring agent, verifiable from the git log or GitHub review/check record. Two sessions running under the same GitHub acco",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/plugin.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nInstructions for AI coding agents working on the React on Rails codebase.\n\nReact on Rails is a Ruby gem + npm package that integrates React with Ruby on Rails, providing server-side rendering (SSR) via Node.js or ExecJS. This is a monorepo: the open-source gem lives at `react_on_rails/`, the npm package at `packages/react-on-rails/`, and the Pro package at `react_on_rails_pro/`.\n\n## Reusable Workflows\n\n- `AGENTS.md`: canonical entry point for agent instructions and workflow discovery\n- Shared agent workflow skills may be installed in the user's or agent's normal\n  skill directory and reused across repos; they must resolve repo-specific\n  values through this repo's `AGENTS.md` seam. The canonical shared source is\n  [`shakacode/agent-workflows`](https://github.com/shakacode/agent-workflows).\n  Use that repo's `agent-workflows-status` and `upgrade-agent-workflows`\n  helpers to keep installed Codex or Claude homes current.\n- When updating reusable agent workflows, skills, commands, or prompt\n  templates, first consider whether the change belongs in\n  `shakacode/agent-workflows` rather than this repo; keep local edits focused on\n  React on Rails-specific policy, seams, or overrides.\n- `.agents/skills/`: repo-specific skills, explicit overrides, and\n  repo-pinned helper `bin/` copies for checkout-only agent sessions. Keep shared\n  workflow `SKILL.md` files installed in the user's or agent's normal skill\n  directory; duplicating them here creates duplicate Codex skill picker entries.\n  Current repo-specific skills include `$stress-test`,\n  `$optimize-rsc-performance`, `$react-on-rails-update-changelog`, and\n  `$react-on-rails-release-train-issue-evaluation`.\n- `.claude/skills`: symlink to `.agents/skills` so Claude Code exposes the\n  repo-specific local skills kept by this checkout. Shared skills should come\n  from the installed shared pack, not this symlink.\n- `.agents/workflows/`: repo-local workflow files for Codex, GPT, and other\n  non-Claude tools when this checkout needs copy/paste workflows or overrides.\n- `.agents/bin/shared-skill-dir`: helper for workflow files that need a\n  repo-pinned helper copy or installed/shared skill directory.\n- `.agents/skills/*/bin`: repo-pinned shared helper scripts for workflows that\n  must run inside checkout-only or directory-restricted agent sessions. These\n  directories intentionally do not include duplicate shared `SKILL.md` files.\n- This repo deliberately does not adopt the pack's\n  `autonomous-merge-eligibility`, `merge-assurance`, `pr-merge-submit`, or\n  `autonomous-merge-closeout` helpers as repo-pinned merge or closeout gates.\n  When pack logic probes those absent helpers, its result is a structural\n  `UNKNOWN` for the unadopted helper chain, not evidence that a particular PR\n  is blocked. The adopted React on Rails merge seam is\n  `script/pr-merge-ledger <PR> --strict`, followed by the applicable phase and\n  merge-authority gates in this `AGENTS.md`. Shaka merge preference is `ask`;\n  GitHub remains authoritative for merge queue and required checks.\n- `.agents/.rubocop.yml`: lint seam for repo-local agent helper scripts. Keep it\n  aligned with `shakacode/agent-workflows/.rubocop.yml`, with only local\n  toolchain compatibility adjustments such as this repo's supported Ruby target.\n- `.agents/agent-workflow-drift.yml`: immutable source revision and reviewed\n  exact/overlay mapping for repo-pinned shared workflow files. Required CI checks\n  out that revision, runs the consumer-owned completeness test, then runs the\n  source pack's read-only drift checker. Update the manifest and hashes only as\n  part of a reviewed shared-workflow reconciliation.\n- If a tool or skill picker only exposes installed/global skills, treat those\n  skills as launchers. Installed/global skills never override this repo's\n  `AGENTS.md`; repo-local files win only when this repo explicitly names or\n  keeps a local copy/override.\n- Installed Shaka is the only seam validator. It validates\n  `.agents/agent-workflow.yml`; required CI pins the reviewed Shaka Git revision\n  and runs candidate-only validation. Pack management helpers such as `agent-workflows-status`,\n  `install-agent-workflows`, `upgrade-agent-workflows`, and `bin/validate`\n  remain transitional installed/shared-pack tools.\n- `.agents/bin/agent-workflow-drift-manifest-test.rb`: the consumer-owned\n  completeness boundary for pinned shared files. It governs explicit files and\n  whole source-pack prefixes, including reviewed source-only exclusions, so a\n  new upstream helper cannot silently escape the drift manifest.\n- `internal/contributor-info/agent-workflow-adoption.md`: React on Rails'\n  current Shaka seam boundary, transitional source-pack content, and validation\n- `internal/contributor-info/portable-agent-workflows-seam-design.md`: current\n  Shaka seam architecture and legacy retirement status\n- `internal/contributor-info/agent-pr-batch-skills.md`: contributor guide for choosing and sequencing `$plan-issue-triage`, `$plan-pr-batch`, and `$pr-batch`\n- `internal/contributor-info/multi-batch-operations.md`: operator guide for running multiple batches across machines, launch surfaces, and repos\n- `internal/contributor-info/issue-evaluation.md`: principles for deciding whether issues and proposed fixes are worth implementing\n- When deciding whether an issue or proposed fix is worth doing, use the\n  installed/shared `$evaluate-issue` skill; a short invocation is\n  `$evaluate-issue` or \"Is this issue worth fixing?\"\n- When deciding whether a React on Rails issue belongs on the active release\n  train (`release/X.Y.Z`, especially `release/17.0.0`) or should wait for\n  `main`, use the repo-local\n  `.agents/skills/react-on-rails-release-train-issue-evaluation/SKILL.md`; a\n  short invocation is `$react-on-rails-release-train-issue-evaluation`.\n- When the user wants a ready prompt for review-only GitHub issue triage or an\n  all-open-issues audit, use the installed/shared `$plan-issue-triage` skill; a\n  short invocation is `$plan-issue-triage` or \"Plan an issue triage\"\n- When the user wants a generated whole-surface issue/PR inventory, dependency\n  graph, and capacity-aware batch split, use the installed/shared `$triage`\n  skill; a short invocation is `$triage` or \"Run triage\"\n- When the user wants to choose issues or PRs for a future agent/Codex/Claude\n  batch, use the installed/shared `$plan-pr-batch` skill to produce a ready\n  `$pr-batch` goal; a short invocation is `$plan-pr-batch` or \"Plan a PR batch\"\n- When the user wants a multi-issue or multi-PR agent/Codex/Claude batch, use the\n  installed/shared `$pr-batch` skill; a short invocation is `$pr-batch`,\n  \"Run an agent batch\", \"Run a Codex batch\", or \"Run a Claude batch\"\n- When the user wants to stop or cancel an in-flight Codex/Claude batch (for example to relaunch it with updated skills), follow the **Cancelling Or Stopping A Batch** protocol in `.agents/workflows/pr-processing.md#cancelling-or-stopping-a-batch`; there is no short skill invocation for this coordinator action\n- When the user wants to audit merged batch work, missed reviews,\n  release-candidate risk, or possible bad merges, use the installed/shared\n  `$post-merge-audit` skill; reusable prompts live in\n  `.agents/workflows/post-merge-audit.md`\n- When the user wants an adversarial PR review, red-team review, Claude/Codex\n  comparison review, or a stricter pre-merge gate, use the installed/shared\n  `$adversarial-pr-review` skill; reusable prompts live in\n  `.agents/workflows/adversarial-pr-review.md`\n- When the user assigns an issue, PR, review-fix pass, or merge queue to an agent, follow `.agents/workflows/pr-processing.md`\n- When the user asks to address PR review comments, use the installed/shared\n  `$address-review` skill; `.agents/workflows/address-review.md` remains a\n  copy/paste prompt for assistants without skill support\n- When the user wants to manually verify a bug-fix PR by reproducing the failure\n  before the fix and confirming it is gone after (with captured evidence or\n  screenshots, optionally posted to the PR and issue), use the installed/shared\n  `$verify-pr-fix` skill; a short invocation is `$verify-pr-fix` or\n  \"manually verify this fix\"\n- When the user explicitly asks for destructive React on Rails stress testing,\n  use the repo-local `.agents/skills/stress-test/SKILL.md`; a short invocation is\n  `$stress-test`\n- When the user plans, implements, validates, or reviews RSC page performance\n  optimization in this repo, use the repo-local\n  `.agents/skills/optimize-rsc-performance/SKILL.md`; a short invocation is\n  `$optimize-rsc-performance`\n- When React on Rails release-train changelog work needs `target=release` or a\n  PR targeting `release/X.Y.Z`, use the repo-local\n  `.agents/skills/react-on-rails-update-changelog/SKILL.md`; a short invocation\n  is `$react-on-rails-update-changelog`. For ordinary mainline changelog updates\n  on `main`, use the installed/shared `$update-changelog` skill.\n- When a maintainer wants to run or inspect RC/beta validation across the demo\n  fleet, use the repo-local `.agents/skills/run-fleet-validation/SKILL.md`; a\n  short invocation is `$run-fleet-validation`. Its Ruby generator reads\n  `internal/contributor-info/demo-fleet.yml` and emits a complete lifecycle pack:\n  release/capability preflight, balanced subagent-driven hard-gate prompts,\n  report-only soft-track coverage, a durable result ledger/schema, independent\n  audit, authorized merge, reachability/tree-parity proof, and tracker closeout.\n  The same skill also generates public-only standing-health packs that verify\n  stable artifact currency, exact-default-head CI/smoke, review-app capability,\n  default-branch staleness, and the evaluated Dependabot v1 policy without\n  mutating demo repositories.\n- Default simplify model: `claude-opus-4-8`\n\n## External Flagship Demo Coordination\n\nThe public [`shakacode/react-on-rails-demo-flagship`](https://github.com/shakacode/react-on-rails-demo-flagship)\nrepo is the single clone-and-run flagship example for React on Rails Pro, React Server Components, React 19,\nstreaming SSR, the Node renderer, Shakapacker, and Rspack.\n\nUpdate that demo repo when changes in this monorepo affect the recommended user-facing Pro/RSC path, including:\n\n- React on Rails Pro or RSC generator output (`--pro`, `--rsc`, `react_on_rails:pro`, `react_on_rails:rsc`)\n- Pro installation, licensing, or \"license optional for evaluation/demo/non-production\" messaging\n- React, React DOM, `react-on-rails-rsc`, Shakapacker, Rspack, or Node renderer version pins/defaults\n- Auto-bundling behavior for `.client.` / `.server.` files or the `'use client'` directive\n- Streaming SSR/RSC helper usage, Node renderer configuration, Docker, or deployment defaults, including changes that\n  affect `bin/smoke` or Docker smoke-validation steps the demo repo runs during verification\n\nWhy: the flagship demo is the external proof that the Pro/RSC happy path works in a real Rails app. If this monorepo\nchanges the recommended path but the demo stays stale, agents and users will copy the wrong setup.\n\nKeep one flagship demo for now. Do not create a separate OSS-only flagship unless the user explicitly asks. The demo's\nREADME should document how to turn Pro/RSC off for comparison, but the default app should remain Pro + RSC.\nAdditional examples are valuable when they teach distinct repo-generation patterns, but they should not dilute or\ncompete with the flagship Pro/RSC path.\n\nThe machine-readable catalog of demos, tiers, and packages is `internal/contributor-info/demo-fleet.yml`.\n\nWhen updating the demo, make the change in a separate checkout/branch of `react-on-rails-demo-flagship`, regenerate and\ncommit lockfiles when dependency changes alter them, and do not mix demo repo commits into this monorepo. Use the\nJavaScript package manager declared by the demo repo (`packageManager` field or lockfile), then run focused validation\nsuch as:\n\n- `bundle install`\n- the lockfile install command for the declared package manager (`npm ci` for the current flagship)\n- `bin/shakapacker` or the equivalent asset build command documented by the demo repo\n- `bin/smoke` or Docker smoke validation\n\n## Canonical Agent Policy\n\n`AGENTS.md` is the canonical source for repository-wide agent rules:\n\n- Commands and test/lint workflow\n- Code style and formatting expectations\n- Git/PR boundaries and safety rules\n- Directory and documentation boundaries\n\nOther agent-facing docs (for example `CLAUDE.md`) should contain only tool-specific workflow notes and link back here.\nIf there is a conflict, `AGENTS.md` wins.\n\n## React on Rails Pro Guardrails\n\nReact on Rails Pro includes the Ruby Pro tree and the Pro npm packages:\n\n- `react_on_rails_pro/`\n- `packages/react-on-rails-pro/`\n- `packages/react-on-rails-pro-node-renderer/`\n\nBefore modifying, copying, vendoring, porting, or reimplementing Pro code from\nany of those paths, read and follow the Pro-specific guardrails in\n[`react_on_rails_pro/AGENTS.md`](react_on_rails_pro/AGENTS.md). Those guardrails\ndo not replace the Pro license or EULA; they tell agents when to stop and ask\nfor explicit licensing confirmation.\n\n## Freshness And Skill Resolution\n\nBefore planning issue/PR work, creating a new branch, or creating a new\nworktree, run:\n\n```bash\ngit fetch --prune origin main\n```\n\nBase new issue branches and new worktrees on the freshly fetched `origin/main`\nunless the user explicitly asks to reproduce an old SHA, continue an existing PR\nbranch, bisect, or work offline. Creating a new worktree does not fetch from\nGitHub by itself.\n\nAfter fetching, verify the `## Agent Workflow Configuration` seam before relying\non installed/shared skills for issue, PR, or batch work:\n\n```bash\nshaka seam check --root \"$(pwd)\" --ref \"$(git rev-parse origin/main)\"\n```\n\nThis trusted-ref check establishes workflow policy. Candidate CI validation uses\nthe separately pinned Shaka checkout with `--local`, which grants neither policy\nnor merge authority.\n\nIf a workflow explicitly needs a repo-local `.agents/skills/...` file, it should\nbe a repo-specific local skill such as `stress-test` or\n`optimize-rsc-performance`, release-branch changelog handling such as\n`react-on-rails-update-changelog`, a pinned helper `bin/` copy without\n`SKILL.md`, or a deliberate override. Shared workflow skills normally resolve\nfrom the installed/shared pack for picker-visible instructions. Helper commands\nmay resolve to repo-pinned `.agents/skills/<skill>/bin` copies so checkout-only\nor directory-restricted agents can still run repo workflows. If a required\nrepo-local skill or `.agents/workflows/...` file is missing in the checkout but\npresent on `origin/main`, update the worktree before continuing; if it is still\nmissing, report the repo workflow state as `UNKNOWN`.\n\nFor user-installed shared skills, check the installed pack with:\n\n```bash\nagent-workflows-status --host codex\n```\n\nUse `--host claude` for Claude Code installs. Upgrade the transitional shared\npack, then validate this repository with trusted Shaka:\n\n```bash\nupgrade-agent-workflows --host codex\nshaka seam check --root \"$(pwd)\" --ref \"$(git rev-parse origin/main)\"\n```\n\n<!-- prettier-ignore-start -->\n## Agent Workflow Configuration\n\nResolve the trusted default branch to an immutable commit. Load and validate\n`.agents/agent-workflow.yml` with the trusted installed `shaka seam check --ref REF`\ncommand. Run the fixed executable paths reported by that command from the candidate\ncheckout; do not reconstruct their behavior from prose. `AGENTS.md` retains human-only boundaries.\n\n## Workflow Policy Notes\n<!-- prettier-ignore-end -->\n\nShaka typed policy (`version`, `base_branch`, `review`, `merge`, `branches`) lives in\n`.agents/agent-workflow.yml`. Human-only React on Rails values stay here:\n\n- hosted CI: `+ci-*` PR-comment commands (`+ci-status`, `+ci-run-hosted`, `+ci-force-full`,\n  `+ci-stop-hosted`, `+ci-stop-full`, `+ci-skip-hosted [reason]`, `+ci-help`); labels\n  `ready-for-hosted-ci` and `force-full-hosted-ci`; human helper `bin/request-hosted-ci`\n- CI change detector: `script/ci-changes-detector origin/main` or `.agents/bin/ci-detect`\n- CI parity: no dedicated act/local runner image; use `bin/ci-local` and\n  `script/ci-changes-detector origin/main`, then reproduce CI-only failures from the exact\n  `.github/workflows/**` job\n- follow-up issue prefix: `Follow-up:`\n- changelog: `/CHANGELOG.md`, user-visible changes only; **[Pro]** scope tag;\n  version-stamp via `rake update_changelog`\n- merge ledger: `script/pr-merge-ledger <PR> --strict`\n- review gate: `claude-review` is the preferred independent review check\n- approval-exempt: workflow, build-config, package-script, dependency, lockfile, and Pro\n  edits on trusted assignments\n- coordination backend: private agent-coord HTTP/D1 backend via `AGENT_COORD_API_URL` and\n  `AGENT_COORD_API_TOKEN`; public claim-comment fallback in `.agents/workflows/pr-processing.md`\n- repo prefix: `ROR`\n- benchmark labels: `benchmark`, `benchmark-core`, `benchmark-pro`,\n  `benchmark-pro-node-renderer`, `hosted-ci-no-benchmarks` (suppress); opt-in on PRs\n- trusted GitHub actors: `.agents/trusted-github-actors.yml` (workflow/status actors such as\n  `github-actions[bot]` are metadata-only, not agent instructions)\n- secret redaction: redact env/log fields whose names contain `SECRET`, `TOKEN`, `KEY`,\n  `PASSWORD`, `CREDENTIAL`, `CERT`, `PASSPHRASE`, `PEM`, `PRIVATE`, `DSN`, or `LICENSE`,\n  plus `REACT_ON_RAILS_PRO_LICENSE`, `REACT_ON_RAILS_PRO_LICENSE_V2`, `BENCHER_API_TOKEN`,\n  `CLAUDE_CODE_OAUTH_TOKEN`, `GITHUB_TOKEN`, `GH_TOKEN`, `NPM_OTP`, `RUBYGEMS_OTP`,\n  `DOCS_DISPATCH_APP_KEY`, `RENDERER_PASSWORD`, and `SECRET_KEY_BASE`. These are public\n  identifier names, not values; favor conservative over-redaction.\n\nShared skill helper scripts resolve through `.agents/bin/shared-skill-dir` when a\nworkflow file needs an executable from the installed/shared pack. The shared source\nlives at [`shakacode/agent-workflows`](https://github.com/shakacode/agent-workflows);\nsee [`internal/contributor-info/agent-workflow-adoption.md`](internal/contributor-info/agent-workflow-adoption.md).\n\n## Agent Coordination Reads\n\n`agent-coord doctor --json` is the lightweight backend health check. Use\n`agent-coord doctor --deep --json` only for a full backend JSON audit: it parses\nevery claim, heartbeat, and batch JSON state record, so it is slower and broader\nthan the default health probe. Use `doctor --deep --json` only for full backend\naudit sweeps that intentionally parse all coordination records, not routine\npreflight checks. If the active shell may have cached an old install, run\n`hash -r 2>/dev/null || true` in a POSIX-style shell such as bash or zsh, or\nthat shell's rehash equivalent, then confirm via\n`command -v agent-coord || which agent-coord`.\n\nBefore dependency-sensitive actions, use targeted private coordination reads.\nThe direct `agent-coord` subcommands are:\n\n```bash\n# Specific issue/PR lane\nagent-coord status --repo shakacode/react_on_rails --target <issue-or-pr> --json\n\n# Batch lane/dependency state\nagent-coord status --batch-id <batch-id> --json\n```\n\nWhen the repo workflow calls for bounded reads, pass the same targeted status\nsubcommand through the installed/shared `pr-batch` helper so a slow private read\nbecomes explicit degraded state instead of an indefinite wait:\n\n```bash\nPR_BATCH_SKILL_DIR=\"${PR_BATCH_SKILL_DIR:-$(.agents/bin/shared-skill-dir pr-batch)}\"\n\n# Specific issue/PR lane\n\"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded\" --timeout 20 status --repo shakacode/react_on_rails --target <issue-or-pr> --json\n\n# Batch lane/dependency state\n\"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded\" --timeout 20 status --batch-id <batch-id> --json\n```\n\nDo not use broad `agent-coord status` for routine lane checks. Broad private\ncoordination reads are audit-only; if they time out, exit 1 (unexpected error),\nor exit 2, report private coordination as `UNKNOWN`/degraded and use structured\npublic claim comments only as advisory evidence. Any non-zero exit other than\n`CLAIM_REFUSED` (exit 3) is treated as `UNKNOWN`/degraded. If targeted status\nexits 0, private coordination state is authoritative. Refused claims\n(`CLAIM_REFUSED` / exit 3) remain hard stops for machine agents.\n\n## Commands\n\n```bash\n# Install dependencies\n# The committed root Gemfile.lock is generated with Bundler 4.0.10; use Bundler\n# 4.0.10 or newer before running root bundle commands.\nbundle && (cd react_on_rails && bundle) && pnpm install\n\n# The root Gemfile is intentionally limited to repo-wide lint, hook, release,\n# and benchmark script spec tooling. After changing package Gemfiles, run bundle\n# install in that package directory; after changing the root Gemfile, run bundle\n# install at the repo root to sync the tooling lock.\n\n# Build TypeScript → JavaScript\npnpm run build\n\n# Lint (MANDATORY before every commit)\n(cd react_on_rails && BUNDLE_GEMFILE=../Gemfile bundle exec rubocop) # OSS Ruby lint — CI-equivalent\n# Pro Ruby lint — CI-equivalent when Pro files or RuboCop config change\n(cd react_on_rails_pro && BUNDLE_GEMFILE=../Gemfile bundle exec rubocop --ignore-parent-exclusion)\npnpm run lint                                                    # JS/TS via ESLint\npnpm start format.listDifferent                                  # Check Prettier formatting\n(cd react_on_rails && bundle exec rake lint)                     # Package lint task (Ruby + JS + formatting)\n\n# Optional Ruby diagnostic from the repo root (not the CI contract)\nBUNDLE_GEMFILE=\"$(git rev-parse --show-toplevel)/Gemfile\" bundle exec rubocop\n\n# Auto-fix formatting\n(cd react_on_rails && bundle exec rake autofix) # Preferred for all formatting\n\n# Run tests\n(cd react_on_rails && bundle exec rake run_rspec:gem)   # Ruby unit tests (gem code)\n(cd react_on_rails && bundle exec rake run_rspec:dummy) # Ruby integration tests (dummy Rails app)\npnpm run test                        # JavaScript/TypeScript tests\n(cd react_on_rails && bundle exec rake)                 # Full package suite (lint + tests except examples)\n\n# Type checking\npnpm run type-check                  # TypeScript\n(cd react_on_rails && bundle exec rake rbs:validate) # RBS signatures\n\n# Additional test subsets\n(cd react_on_rails && bundle exec rake run_rspec) # All Ruby tests\n(cd react_on_rails && bundle exec rake all_but_examples) # All tests except generated examples\n(cd react_on_rails && bundle exec rake run_rspec:shakapacker_examples_basic) # Single example test\n\n# Documentation checks\nscript/check-docs-sidebar            # Validate docs sidebar coverage\nbin/check-links                      # Markdown link checks (requires lychee)\n\n# Full initial setup\nbundle && (cd react_on_rails && bundle) && pnpm install && \\\n  (cd react_on_rails && bundle exec rake shakapacker_examples:gen_all node_package && bundle exec rake)\n\n# CI/workflow linting\nactionlint                           # GitHub Actions lint\nyamllint .github/                    # YAML lint (do NOT run RuboCop on .yml files)\n\n# Dependency version updates\nrake shakapacker:update_version[9.6.1]  # Update shakapacker across the monorepo\n```\n\n### Updating Shakapacker\n\nUse `rake shakapacker:update_version[VERSION]` to update shakapacker across the entire monorepo. This single command updates all Gemfiles, package.json files, Gemfile.lock files, and pnpm-lock.yaml. Do **not** manually edit individual version references — always use the rake task to keep everything in sync.\n\nThe task handles Ruby version switching for apps that require a different Ruby version (set `RUBY_VERSION_MANAGER` to `rvm`, `rbenv`, `asdf`, or `mise` if needed; defaults to `rvm`). It continues gracefully if a single lock file update fails (e.g., due to a missing Ruby version).\n\nAfter Shakapacker version or default updates, check the External Flagship Demo Coordination section to decide whether the\nflagship demo needs the same change.\n\n## Testing\n\n- **Prefer local testing over CI iteration** — don't push \"hopeful\" fixes. Apply the **15-minute rule**: if 15 more minutes of local testing would catch the issue before CI does, spend the 15 minutes.\n- **Never claim a test is \"fixed\" without running it locally first.** Use \"This SHOULD fix...\" or \"Proposed fix (UNTESTED)\" for unverified changes.\n- **Automated tests passing is necessary but not sufficient.** If your changes affect how the app starts, builds, or serves, you must also verify the dev environment manually. See [Manual Dev Environment Testing](.claude/docs/manual-dev-environment-testing.md) for the full checklist.\n- **Ruby**: RSpec. Unit tests in `react_on_rails/spec/react_on_rails/`, integration tests via a dummy Rails app in `react_on_rails/spec/dummy/`.\n- **JavaScript/TypeScript**: Jest. Tests in `packages/react-on-rails/tests/`.\n- **E2E**: Playwright. Tests in `react_on_rails/spec/dummy/e2e/playwright/e2e/`. Run with `cd react_on_rails/spec/dummy && pnpm test:e2e`.\n- **The dummy app** (`react_on_rails/spec/dummy/`) is a full Rails application used for integration testing. Many tests require it.\n\nRun specific test files:\n\n```bash\n(cd react_on_rails && bundle exec rspec spec/react_on_rails/path/to/spec.rb)\ncd react_on_rails/spec/dummy && bundle exec rspec spec/path/to/spec.rb\n```\n\n## Project Structure\n\n| Directory                                        | Purpose                                                                                  |\n| ------------------------------------------------ | ---------------------------------------------------------------------------------------- |\n| `react_on_rails/lib/react_on_rails/`             | Ruby gem source — helpers, configuration, SSR pool, engine                               |\n| `react_on_rails/lib/generators/`                 | Rails generators for `react_on_rails:install`                                            |\n| `react_on_rails/spec/`                           | RSpec tests (unit + integration via dummy app)                                           |\n| `react_on_rails/spec/dummy/`                     | Full Rails app for integration testing and E2E                                           |\n| `packages/react-on-rails/src/`                   | TypeScript source — client-side React integration                                        |\n| `packages/react-on-rails/tests/`                 | Jest tests for the npm package                                                           |\n| `react_on_rails_pro/`                            | Pro package (separate gem + npm)                                                         |\n| `rakelib/`                                       | Rake task definitions                                                                    |\n| `docs/oss/`                                      | OSS documentation — published to the [ShakaCode website](https://reactonrails.com/docs/) |\n| `docs/pro/`                                      | Pro documentation — installation, configuration, RSC, node renderer, caching             |\n| `internal/contributor-info/`                     | Internal contributor docs (not published to the website)                                 |\n| `internal/planning/`                             | Internal planning docs, designs, and drafts                                              |\n| `internal/react_on_rails_pro/contributors-info/` | Internal Pro contributor docs (not published to the website)                             |\n| `internal/analysis/`                             | Investigation and analysis documents (kebab-case `.md` files)                            |\n\n## Code Style\n\n### Ruby (RuboCop)\n\nLine length max 120 characters. Run `bundle exec rubocop [file]` to check.\n\n**Line length — break long chains:**\n\n```ruby\n# Bad\ncontent = pack_content.gsub(/import.*from.*['\"];/, \"\").gsub(/ReactOnRails\\.register.*/, \"\")\n\n# Good\ncontent = pack_content.gsub(/import.*from.*['\"];/, \"\")\n                      .gsub(/ReactOnRails\\.register.*/, \"\")\n```\n\n**Named subjects in RSpec:**\n\n```ruby\n# Bad\nsubject { instance.method_name(arg) }\n\n# Good\nsubject(:method_result) { instance.method_name(arg) }\n```\n\n**Security violations — scope disable comments tightly:**\n\n```ruby\n# rubocop:disable Security/Eval\nexpect { evaluate(sanitized_content) }.not_to raise_error\n# rubocop:enable Security/Eval\n```\n\n### JavaScript/TypeScript\n\nPrettier handles all formatting. Never manually format — run `rake autofix` instead.\n\n### GitHub Actions\n\nFor GitHub Actions jobs that install Ruby gems, prefer `.github/actions/setup-bundle` over hand-written `actions/cache` plus `bundle install` steps.\nThe action validates a committed `Gemfile.lock`, configures the bundle path and Bundler version for later `bundle exec` steps,\nrestores/saves the gem cache, and supports non-frozen installs via `frozen: 'false'` for minimum-dependency jobs.\n\n## Git Workflow\n\n**Branch naming**: `type/descriptive-name` (e.g., `fix/ssr-hydration-mismatch`)\n\n**Commit messages**: Explain why, not what. One logical change per commit.\n\n**Squash merges**: When completing a GitHub squash merge, include the PR number in the squash commit title using the format `<PR title> (#<PR number>)`, for example `Docs: clarify rails new JavaScript skip flag (#3666)`. For CLI merges, pass `--subject \"<PR title> (#<PR number>)\"` to `gh pr merge --squash` and verify the title before confirming the merge.\n\n**PR creation**: Use `gh pr create` with a clear title, self-contained why/rationale summary, implementation summary, and test plan. If an issue exists, link it, but do not make reviewers open the issue to understand why the PR exists; include at least a short rationale in the PR description itself.\n\n**PR processing**: Before pushing a review-fix batch, opening a PR, marking a PR ready, requesting hosted CI, requesting force-full hosted CI, or reporting merge-readiness, run the agent PR processing flow in `.agents/workflows/pr-processing.md`: verify the work is worth doing, self-review the diff, run local validation, use the pre-push AI review and simplify gate when appropriate, batch fixes, and document exact verification evidence plus churn notes. After a PR and its reviews exist, wait for configured review agents and triage actionable review feedback before marking ready, requesting merge, or merging.\n\n**Hosted CI usage**: Do not use hosted CI as the first real validation pass. Prefer local checks first, then optimized hosted CI when the branch is ready for remote confirmation or final validation. Use the `+ci-*` PR comment commands for an auditable decision: `+ci-status` before deciding, `+ci-run-hosted` after the final push for optimized hosted CI, `+ci-force-full` only when a maintainer intentionally wants every hosted suite to bypass optimized selection, `+ci-stop-hosted` to return an iterating PR to the required gate, `+ci-stop-full` to remove only the force-full override, `+ci-skip-hosted [reason]` only with explicit maintainer approval for a low-risk waiver, and `+ci-help` when syntax is unclear. Put one `+ci-*` command per PR comment. Human/user-token label writes through `bin/request-hosted-ci` or `gh pr edit --add-label ready-for-hosted-ci` are valid, but workflow-token label writes are not a current-head trigger; automation must dispatch workflows explicitly or use `+ci-run-hosted`.\n\n**GitHub follow-up issues**: Follow-up issues are the exception. Prefer fixing or declining review feedback in the PR. If deferred work remains valuable, present one bundled deferred-work summary and ask whether to track it. Prefer an existing issue; otherwise create at most one bundled issue per PR unless the user explicitly approves more. New follow-up issue titles must begin with `Follow-up:`. Build multi-line issue bodies as Markdown files and pass them with `gh issue create --body-file`; do not pass escaped newline strings through `--body`.\n\n**GitHub Actions post-merge exercise follow-ups**: Semantic changes to `.github/workflows/**` or `.github/actions/**`\nare a standing exception to the default \"no follow-up issue\" rule. Before merge, link an existing tracking issue or\ncreate one bundled issue titled `Follow-up: Exercise GitHub Actions changes from PR #NNNN`. The issue must name the\nsource PR, changed workflow/action files, exact post-merge event or secondary verification PR to exercise, expected\nevidence, cleanup instructions for any verification-only PR, and owner if known. This is required for trigger,\npermission, job, matrix, condition, concurrency, secret, reusable-action, command-parsing, workflow-dispatch, or\nCI-routing behavior changes. It is not required for comments, docs, typo fixes, formatting-only changes, or\nnon-semantic actionlint cleanup when local validation evidence documents that classification.\n\n**Process gap disposition**: When an audit, review, or batch closeout finds a recurring process miss, do not add a prose-only rule by default. The issue plan or PR evidence must choose one mechanism target: `script`, `schema`, `checklist+replay`, or `park`, and record the motivating miss, replay evidence or park reason, and non-goal. `park` means the miss is plausible but not worth mechanizing now.\n\n### Release Version Ownership\n\n`bundle exec rake release[...]` owns the coordinated React on Rails product-version\nchange. For ordinary RC and final preparation, agents prepare and stamp\n`CHANGELOG.md`, but must not manually bump React on Rails' own gem/npm version\nfields or create the ordinary `Bump version to ...` commit. The release task\nupdates the OSS and Pro gem version files, the `version` field in all five\n`package.json` files, and the Ruby `Gemfile.lock` files in that generated commit.\nIt does not run `pnpm install` or regenerate `pnpm-lock.yaml`; workspace-protocol\ndependency conversion during npm publishing is temporary and is restored afterward.\n\nIf a release-preparation or dependency-pin PR changes dependency ranges or pins,\nregenerate the affected npm/pnpm lockfiles in that PR. Do not defer those lockfile\nupdates to the React on Rails product-version release task.\n\nPins for independently released dependencies are separate changes. For example,\npromoting `react-on-rails-rsc` from an RC to a stable version still requires a\nnormal reviewed and tested PR that updates the generator pin, package metadata,\nand affected lockfiles before cutting the next React on Rails RC. Do not confuse\nthat dependency update with manually bumping React on Rails' own version.\n\n## Maintainer Attention Contract\n\nMaintainer attention is for judgment, not for routine progress pings or\nmachine-checkable work. Agents working PRs, reviews, or batches must apply this\ncontract unless a maintainer explicitly narrows the run.\n\n- **Autonomous nits**: behavior-preserving `OPTIONAL` review nits may be fixed\n  inline without asking when they stay inside the PR scope, are low-risk, and are\n  before the final-candidate debounce point: once a merge-readiness review cycle\n  has started, do not introduce new nit commits that would restart it.\n  Inside the PR scope means the file, section, or workflow copy is already part\n  of the PR diff or directly cited by current review feedback. Cross-copy\n  consistency edits are in scope only when the paired section is already in the\n  PR diff or directly cited by current review feedback; this excludes unrelated\n  cleanup, other machine lanes, reserved files, generated output not already in\n  scope, and separate workflow files that merely discuss the same concept.\n  The final-candidate debounce point begins when the agent explicitly\n  designates the current head as merge-ready or the final candidate in a PR\n  body, PR comment, or handoff, or when the agent pushes after completing the\n  final local validation/review gate and records that push as the candidate.\n  Automatically queued checks from ordinary fix-phase pushes do not count unless\n  that push or check set has been declared as the final readiness gate. Earlier\n  incremental per-file checks during the fix phase do not count.\n  Behavior-preserving means wording, formatting, or mechanical\n  whitespace/punctuation cleanup that does not alter public APIs, generated\n  output, runtime behavior, validation scope, or the semantic meaning of any\n  section that has an unresolved review thread on it. Low-risk means local and\n  mechanically checkable, such as a formatter-confirmed cleanup; a rename that\n  requires searching all callers is not low-risk. Mechanical means deterministic\n  and local, such as rerunning a formatter or fixing whitespace introduced by\n  the nit, without reasoning about runtime behavior, callers, or policy.\n  Qualifying examples: typo/comment punctuation, whitespace or trailing comma\n  cleanup, or unambiguous documentation wording.\n  Disqualifying examples: renaming a public method or constant, changing\n  generated content, altering CI or release policy, adding/removing validation,\n  removing an import or `require` whose module side effects are not proven by a\n  dedicated tool or code inspection, or touching another lane's files. If the nit\n  is not worth fixing, record it as deferred or declined with rationale instead\n  of asking \"OK to fix this nit?\".\n  Autonomous deferred/declined nit replies must include `[auto-deferred]` on its\n  own line plus a one-line rationale, for example:\n  ```text\n  [auto-deferred]\n  Whitespace cleanup deferred to avoid restarting the final-candidate gate.\n  ```\n  Post the tag and rationale before resolving the review thread; do not resolve\n  an auto-deferred thread without that reply.\n  If an autonomous nit fix fails local validation or self-review, repair it in\n  the same batch only when the repair is still mechanical and in scope;\n  otherwise drop or revert that nit, record the failed validation and rationale,\n  and promote the underlying concern to `DISCUSS` only when it is a correctness\n  issue, regression risk, or explicit reviewer request.\n  Never push a failing autonomous nit or ask the maintainer to debug it.\n  Escalate only when the item changes behavior, expands scope, conflicts with\n  policy, or has unclear risk.\n- **CI-wait protocol**: while checks or review bots are running, do bounded\n  useful work such as self-review, local-only cleanup notes, documentation sync\n  that does not require pushing the active PR head, or another independent lane.\n  Do not introduce optional cleanup commits that restart current-head gates after\n  the final-candidate debounce point. Do not interrupt the maintainer for routine\n  \"CI is still running\", \"CI is green\", or \"review arrived\" updates. CI failures\n  and new `MUST-FIX`-tier review findings are not routine; surface them\n  immediately.\n- **One decision point per lane**: batch genuine judgment calls into one decision\n  block at lane completion or hard block. The block must include the question,\n  options, recommendation, evidence links or command output, and the next action\n  after an answer. Avoid \"see above\" decisions that require the maintainer to\n  reconstruct context.\n- **Self-verification before escalation**: anything provable by tests, lint,\n  screenshots, repro scripts, `gh` state, or code inspection must arrive with\n  that evidence attached. Use `UNKNOWN` for facts that could not be verified.\n- **Attention metric**: batch closeouts count human decision points per PR, with\n  a target of at most one for low-risk lanes: lanes with no `MUST-FIX` items,\n  no blocking questions, and only documentation, process, or mechanical changes.\n  Higher counts are reported as FYI process churn, not hidden in narrative\n  handoffs. Counts above target invite a later check on whether smaller lanes,\n  sharper scope, or better batching would reduce future churn; they are not a\n  hard failure by themselves. A human decision point is any question, option\n  selection, or confirmation directed at a maintainer that required direct input,\n  excluding git confirmations that safety rules or explicit local-only /\n  inspect-before-push instructions require after the maintainer already selected\n  the action, such as a required confirmation before a destructive force-push. A\n  standalone \"should I push this ordinary PR-iteration fix?\" question counts.\n  Report it as `Decision points: N` in the FYI section of the batch handoff.\n- **Confidence notes**: `merge_authority` has three states:\n  `auto_merge_when_gates_pass` is the only autonomous merge grant when the\n  current user or batch goal grants it and the release-mode rules permit it;\n  `ask` requires one confirmation before merging; and `none` grants no merge\n  authority. When `auto_merge_when_gates_pass` applies and the gate is met,\n  exercising it is the expected close-out — an authorized, gate-satisfied,\n  confident merge that is downgraded to a \"ready to merge\" recommendation is an\n  unfinished task, not a safe default. Before exercising merge authority,\n  complete the confidence note: validations and evidence are recorded, no\n  unresolved MUST-FIX threads remain, and any remaining `UNKNOWN` facts or\n  residual risk do not affect merge safety. Before a merge under\n  `auto_merge_when_gates_pass` or after an `ask` confirmation, the worker or\n  coordinator documents the merge qualifications in the PR description:\n  - which release-mode gate applied and that it was satisfied\n  - the confidence note: validated commands, evidence links, remaining\n    `UNKNOWN` facts, and residual risk\n  - the finalizer, when accelerated-RC requires one\n\n  This intentionally narrows merge-authority evidence to the PR description so\n  the merge decision is auditable from a single location. Use the issue or batch\n  handoff only for no-merge readiness evidence.\n\n  When merge authority is not granted, use the same confidence-note format for\n  merge-readiness evidence without merging:\n\n  ```text\n  Confidence note:\n  - Validated: <commands or checks run and outcomes>\n  - Evidence: <links to CI, screenshots, logs, or inline output>\n  - UNKNOWN: <facts that could not be verified, or \"none\">\n  - Residual risk: <one-line risk summary, or \"none\">\n  ```\n\n## Tracking Issues And Handoffs\n\nKeep the issue tracker for durable work — product features, real bugs, release\ngates — not for transient agent-process state. Process state accretes into\nclutter because \"open a tracker\" has no matching \"close it\" step.\n\n- **Do not open a new issue for a session handoff or a point-in-time audit.** A\n  handoff is transient coordination and an audit is a snapshot; neither is\n  durable backlog. Record a handoff as a comment on the relevant parent tracking\n  issue (for example the roadmap umbrella), or — if a dedicated agent-coordination\n  repo is in use — there. If the work has no parent umbrella (a standalone PR or a\n  one-off batch), put the handoff in the PR's final comment or description rather\n  than creating an issue to hold it. Append a point-in-time audit to the standing\n  release audit ledger in place. Never spawn a standalone `Handoff: ...` or\n  `Post-rc.N audit` issue.\n- **One durable ledger per recurring concern, updated in place.** Release audits\n  append to the standing release audit ledger; cross-agent coordination state —\n  the heartbeats and leases that signal which agent is live on which lane — lives\n  in the coordination-layer tracker. Do not create a sibling issue each cycle.\n  (At time of writing these are #4010 and #3974, but treat any such number as a\n  movable pointer: confirm it is still the live ledger before relying on it, and\n  update the pointer if it has been superseded — the same staleness this policy\n  guards against applies to the ledgers themselves.)\n- **Closure follows the work, not the opener.** A tracking issue closes when its\n  underlying PR/work lands, done by whoever finishes the work — not by whoever\n  opened the tracker. \"I opened it\" does not mean \"I must close it\": WIP can\n  outlive a session (lost chat, unanswered question, disconnect). The heartbeat —\n  the coordination layer's liveness signal that flags when no agent is active on a\n  lane — detects abandonment, and an unfinished PR is the real signal of remaining\n  work; act on the PR, not on a stale tracker.\n- **The 30-day test.** Before opening any tracking or meta issue, ask whether it\n  will still matter in 30 days. If not, it is a comment or a ledger entry, not an\n  issue.\n- **Sweep on sight.** When a handoff/audit/process-snapshot issue's underlying\n  work has landed or its snapshot is obsolete, close it — first consolidating any\n  still-live finding into the durable ledger or a real backlog issue. Verify it is\n  actually resolved or superseded before closing; never close a tracker that still\n  fronts unfinished work.\n\n## Release Mode And Auto-Merge Coordination\n\nUse the current release tracker to decide whether PRs are in normal development, accelerated RC, strict RC, or final-release mode. The tracker is the live source of truth for the mode; committed docs define how to interpret it.\n\nThe repo ships releases with a **release train**: `main` never freezes and keeps absorbing batch work, RCs are stabilized on an ephemeral `release/X.Y.Z` branch, and the final is the **last good RC promoted by dropping `-rc`** — not a re-cut from `main`. The merge gate an agent must apply is a function of the **target branch's release phase** (`beta` / `rc` / `final`); the phase composes with the mode below. See **[Release-Train Branching And Phase Gating](#release-train-branching-and-phase-gating)** for the phase→gate table and [`internal/contributor-info/release-train-runbook.md`](internal/contributor-info/release-train-runbook.md) for the full branching runbook.\n\n- An active tracker is an open release gate issue, usually found by the existing `release` and `TRACKING` labels or the `Release gate:` title. Also search closed release gate issues updated within the last 7 days before defaulting to `development`, so agents can detect stale trackers. The mode must be recorded in the issue body, not encoded by adding more labels.\n- Valid tracker modes are `development`, `accelerated-rc`, `strict-rc`, and `final-release`.\n- If no active tracker exists, assume `development` mode. This is not a blocker; it means the repo is moving toward the next beta/RC/final. If a release tracker was closed within the last 7 days and lacks a closing label/comment containing `Released` or `Superseded`, report `release-mode-stale-tracker` and do not auto-merge until a maintainer confirms the mode. A maintainer can resolve the stale signal with a PR or tracker comment such as `No active release, proceed`; verify the comment author has `write`, `maintain`, or `admin` permission before treating it as maintainer confirmation. Inspect tracker labels and comments with `gh issue view <tracker> --comments --json labels,comments` before deciding that the closing signal is absent.\n- If exactly one active tracker exists, read its `Agent Release Mode` block from the issue body. If the block is absent, use `strict-rc` and report the missing block.\n- If multiple active trackers have different final release targets, select the tracker matching the PR's target only when the target is unambiguous from the PR body, linked issue, branch, or release/changelog text. If the PR target is unclear, or if trackers for the selected target disagree about mode or canonical status, report `release-mode-conflict` and do not auto-merge until resolved. Do not let unrelated final-release targets block each other when the PR target is clear.\n- For duplicate trackers with the same final release target (the eventual semver without prerelease suffix, for example `v1.2.0.rc.1` and `v1.2.0.rc.2` share the `v1.2.0` target) and no conflicting mode, the oldest open tracker is canonical unless it explicitly says it is superseded by another tracker. If same-target trackers disagree about mode or canonical status, report `release-mode-conflict` and do not auto-merge until resolved. Agents may close clean duplicates only after preserving non-conflicting useful information in the canonical tracker and posting a closing comment that links to the canonical issue.\n- Agents do not auto-create release trackers. A maintainer creates one when entering accelerated RC, strict RC, or final-release coordination.\n- To avoid concurrent issue-body overwrites, re-read the tracker immediately before editing it. Prefer append-only comments for per-PR/batch status from concurrent agents, and only edit the tracker body when preserving the latest body content. If the latest tracker body changed in a way the agent cannot safely merge, post a comment with a `Tracker Update:` header containing the intended update and report the conflict; later agents must fetch tracker comments and consider both the latest body and latest unresolved `Tracker Update:` conflict comment before acting.\n\nReporting `release-mode-stale-tracker`, `release-mode-conflict`, or a missing\nrelease-mode block means posting a PR comment with a `Release Mode Block:`\nheader, the signal name, relevant tracker URLs, and the current decision.\n\nIn `development` and `strict-rc` modes, apply the standard merge qualification in the Review Workflow section; the accelerated-RC confidence block and auto-merge threshold do not apply. In `final-release` mode, do not auto-merge; apply standard merge qualification plus the final-release audit and explicit maintainer release decision below.\n\nDuring `accelerated-rc`, affected areas such as SSR, RSC, hydration, package release, generators, CI, benchmarks, and Pro/core boundaries do not cap confidence by themselves. They choose the validation checklist. Actual uncertainty, missing proof, failed checks, or unresolved findings lower confidence.\n\nAuto-merge during accelerated RC requires a finalized PR-body confidence block. The authoring agent may draft it, but a separate coordinator, finalizer, or review agent must finalize it. The finalizer must be a different GitHub account or named GitHub check/app identity than the PR authoring agent, verifiable from the git log or GitHub review/check record. Two sessions running under the same GitHub acco","isInternal":false,"tokens":11197,"sizeBytes":50052},{"name":"llms.txt","path":"llms.txt","rawUrl":"https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/llms.txt","title":"LLM Index & Context Digest","category":"root-instruction","format":"text","content":"# React on Rails\n\nReact on Rails integrates React with Ruby on Rails. Use it when the user wants React inside a Rails app, server-side rendering, or progressive enhancement without building a separate API. Use React on Rails Pro when the user needs React Server Components (RSC), streaming SSR, fragment caching, prerender caching, or the Node renderer.\n\nUse this file as the short machine-readable route map. Use `./llms-full.txt` for the expanded OSS reference and `./llms-full-pro.txt` for the expanded React on Rails Pro reference. Use `./AGENTS_USER_GUIDE.md` for the repo-oriented guide to the machine-readable layer.\n\n## Canonical entry points\n\n- Human docs overview: https://reactonrails.com/docs/\n- OSS docs hub: https://reactonrails.com/docs/introduction\n- Pro docs hub: https://reactonrails.com/docs/pro\n- RSC docs hub: https://reactonrails.com/docs/pro/react-server-components\n- Expanded machine-readable reference (OSS): `./llms-full.txt`\n- Expanded machine-readable reference (Pro): `./llms-full-pro.txt`\n- Agent usage guide: `./AGENTS_USER_GUIDE.md`\n\n## Package pairing\n\n- OSS: Ruby gem `react_on_rails` plus npm package `react-on-rails`\n- Pro: Ruby gem `react_on_rails_pro` plus npm package `react-on-rails-pro`\n- Optional Pro Node renderer: npm package `react-on-rails-pro-node-renderer`\n- Do not use `react_on_rails_pro` with the base `react-on-rails` npm package\n\n## Start here by task\n\n- New Rails app with React:\n  - Quick Start: https://reactonrails.com/docs/getting-started/quick-start\n  - Create a New App: https://reactonrails.com/docs/getting-started/create-react-on-rails-app\n  - Tutorial: https://reactonrails.com/docs/getting-started/tutorial\n- Existing Rails app:\n  - Install into an Existing Rails App: https://reactonrails.com/docs/getting-started/existing-rails-app\n  - Using React on Rails: https://reactonrails.com/docs/getting-started/using-react-on-rails\n  - Architecture overview: https://reactonrails.com/docs/core-concepts/how-react-on-rails-works\n- Styling:\n  - Tailwind CSS v4 recipe: https://reactonrails.com/docs/building-features/styling-with-tailwind\n- Choosing OSS vs Pro:\n  - OSS vs Pro: https://reactonrails.com/docs/getting-started/oss-vs-pro\n  - Pro hub: https://reactonrails.com/docs/pro\n  - Upgrade to Pro: https://reactonrails.com/docs/pro/upgrading-to-pro\n- React Server Components:\n  - RSC hub: https://reactonrails.com/docs/pro/react-server-components\n  - RSC tutorial: https://reactonrails.com/docs/pro/react-server-components/tutorial\n  - Add RSC to an existing Pro app: https://reactonrails.com/docs/pro/react-server-components/upgrading-existing-pro-app\n- Node renderer:\n  - Pro overview: https://reactonrails.com/docs/pro/node-renderer\n  - Technical basics: https://reactonrails.com/docs/building-features/node-renderer/basics\n  - JS configuration: https://reactonrails.com/docs/building-features/node-renderer/js-configuration\n- View transitions (experimental, unsupported):\n  - View Transitions recipe + Turbo interplay: https://reactonrails.com/docs/building-features/view-transitions\n- Hydration scheduling:\n  - Defer React root hydration/rendering until immediate, visible, or idle: https://reactonrails.com/docs/building-features/hydration-scheduling\n- Configuration and deployment:\n  - Configuration overview: https://reactonrails.com/docs/configuration\n  - Pro configuration: https://reactonrails.com/docs/configuration/configuration-pro\n  - Deployment: https://reactonrails.com/docs/deployment\n  - Security model and hardening: https://reactonrails.com/docs/deployment/security-model-and-hardening\n  - Troubleshooting: https://reactonrails.com/docs/deployment/troubleshooting\n- Upgrading and migration:\n  - Upgrading: https://reactonrails.com/docs/upgrading/upgrading-react-on-rails\n  - Pro coupled upgrade checklist (gem + npm + lockfiles, RC version formats, RSC manifest verification): https://reactonrails.com/docs/pro/updating#coupled-pro-upgrade-checklist\n  - OSS release notes: https://reactonrails.com/docs/upgrading/release-notes\n  - Pro release notes: https://reactonrails.com/docs/pro/release-notes\n  - Migrate from Next.js: https://reactonrails.com/docs/migrating/migrating-from-nextjs\n  - Migrate from react-rails: https://reactonrails.com/docs/migrating/migrating-from-react-rails\n  - Migrate from Inertia Rails: https://reactonrails.com/docs/migrating/migrating-from-inertia-rails\n  - Migrate to RSC: https://reactonrails.com/docs/migrating/migrating-to-rsc\n\n## Routing notes\n\n- Prefer the canonical Pro hub at `https://reactonrails.com/docs/pro`.\n- `https://reactonrails.com/docs/pro/react-on-rails-pro` currently redirects to the canonical Pro hub URL above.\n- Keep the machine-readable layer small: use the hub pages above first, then open only the task-specific docs you need.\n","isInternal":false,"tokens":1159,"sizeBytes":4767},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nTool-specific guidance for Claude Code in this repository.\n\n## Source of Truth\n\n`AGENTS.md` is the canonical policy for:\n\n- Commands, tests, and lint workflow\n- Formatting and style requirements\n- Git/PR safety boundaries\n- Project directory boundaries\n\nIf this file conflicts with `AGENTS.md`, follow `AGENTS.md`.\n\n## Behavioral Defaults\n\n- When confident in your changes, **commit and push without asking for permission**. Always monitor CI after pushing, and use the `+ci-*` PR comment commands from `AGENTS.md` when asking maintainers to run, stop, or waive hosted CI.\n- **When `merge_authority` is `auto_merge_when_gates_pass` and the release-mode gate is satisfied, merge; do not stop at a recommendation.** `ask` requires one confirmation before merging, and `none` grants no merge authority. See `AGENTS.md` → Confidence notes for the full tri-state rule, confidence threshold, and required PR-description evidence.\n- Check `main` CI status at session start (injected by `.claude/hooks/main-ci-status.sh`) and again before `gh pr create` or pushing to `main`. See `AGENTS.md` → \"Main branch health\" for the decision framework when `main` is red.\n\n## Git Safety\n\n- **Clean rebase → `git push --force-with-lease` without asking.** When `git rebase origin/main` (or `git pull --rebase`) reports no conflicts, every commit is preserved — republishing is the expected workflow. Just push and report the result.\n- **Ask first when force-pushing in these cases:** you resolved rebase conflicts, you dropped/squashed/reordered commits, or the remote branch has commits you don't have locally.\n- **NEVER `git reset --hard`** on a branch with existing commits (yours or others'). This destroys work. Use a worktree or a new branch instead.\n- **NEVER force-push to `main` or `master`.**\n- If a rebase has conflicts you can't resolve cleanly, abort and ask the user how to proceed.\n\n## Claude-Specific Workflow\n\nUse these docs for Claude-oriented operational guidance:\n\n- `.claude/docs/avoiding-ci-failure-cycles.md`\n- `.claude/docs/replicating-ci-failures.md`\n- `.claude/docs/playwright-e2e-testing.md`\n- `.claude/docs/merge-conflict-workflow.md`\n- `.claude/docs/pr-splitting-strategy.md`\n- `.claude/docs/changelog-guidelines.md`\n- `.claude/docs/project-architecture.md`\n- `.claude/docs/rails-engine-nuances.md`\n- `.claude/docs/debugging-webpack.md`\n- `.claude/docs/rbs-type-checking.md`\n- `.claude/docs/conductor-compatibility.md`\n- `.claude/docs/testing-build-scripts.md`\n- `.claude/docs/main-health-monitoring.md`\n- `.claude/docs/managing-file-paths.md`\n- `.claude/docs/docs-competitive-landscape.md`\n- `.claude/docs/docs-templates.md`\n- `.claude/docs/manual-dev-environment-testing.md`\n- `.claude/docs/validating-node-renderer-changes.md`\n\nFor Pro-package specifics, also read `react_on_rails_pro/CLAUDE.md`.\n","isInternal":false,"tokens":699,"sizeBytes":2831},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":203},{"name":"plugin.json","path":".claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":189},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.cursor/mcp.json)","tokens":300,"sizeBytes":182}],"systemPromptSnippet":"<yakaai_skills repo=\"shakacode/react_on_rails\">\n<!-- File: AGENTS.md (Tokens: ~11197 | Category: root-instruction) -->\n# AGENTS.md\n\nInstructions for AI coding agents working on the React on Rails codebase.\n\nReact on Rails is a Ruby gem + npm package that integrates React with Ruby on Rails, providing server-side rendering (SSR) via Node.js or ExecJS. This is a monorepo: the open-source gem lives at `react_on_rails/`, the npm package at `packages/react-on-rails/`, and the Pro package at `react_on_rails_pro/`.\n\n## Reusable Workflows\n\n- `AGENTS.md`: canonical entry point for agent instructions and workflow discovery\n- Shared agent workflow skills may be installed in the user's or agent's normal\n  skill directory and reused across repos; they must resolve repo-specific\n  values through this repo's `AGENTS.md` seam. The canonical shared source is\n  [`shakacode/agent-workflows`](https://github.com/shakacode/agent-workflows).\n  Use that repo's `agent-workflows-status` and `upgrade-agent-workflows`\n  helpers to keep installed Codex or Claude homes current.\n- When updating reusable agent workflows, skills, commands, or prompt\n  templates, first consider whether the change belongs in\n  `shakacode/agent-workflows` rather than this repo; keep local edits focused on\n  React on Rails-specific policy, seams, or overrides.\n- `.agents/skills/`: repo-specific skills, explicit overrides, and\n  repo-pinned helper `bin/` copies for checkout-only agent sessions. Keep shared\n  workflow `SKILL.md` files installed in the user's or agent's normal skill\n  directory; duplicating them here creates duplicate Codex skill picker entries.\n  Current repo-specific skills include `$stress-test`,\n  `$optimize-rsc-performance`, `$react-on-rails-update-changelog`, and\n  `$react-on-rails-release-train-issue-evaluation`.\n- `.claude/skills`: symlink to `.agents/skills` so Claude Code exposes the\n  repo-specific local skills kept by this checkout. Shared skills should come\n  from the installed shared pack, not this symlink.\n- `.agents/workflows/`: repo-local workflow files for Codex, GPT, and other\n  non-Claude tools when this checkout needs copy/paste workflows or overrides.\n- `.agents/bin/shared-skill-dir`: helper for workflow files that need a\n  repo-pinned helper copy or installed/shared skill directory.\n- `.agents/skills/*/bin`: repo-pinned shared helper scripts for workflows that\n  must run inside checkout-only or directory-restricted agent sessions. These\n  directories intentionally do not include duplicate shared `SKILL.md` files.\n- This repo deliberately does not adopt the pack's\n  `autonomous-merge-eligibility`, `merge-assurance`, `pr-merge-submit`, or\n  `autonomous-merge-closeout` helpers as repo-pinned merge or closeout gates.\n  When pack logic probes those absent helpers, its result is a structural\n  `UNKNOWN` for the unadopted helper chain, not evidence that a particular PR\n  is blocked. The adopted React on Rails merge seam is\n  `script/pr-merge-ledger <PR> --strict`, followed by the applicable phase and\n  merge-authority gates in this `AGENTS.md`. Shaka merge preference is `ask`;\n  GitHub remains authoritative for merge queue and required checks.\n- `.agents/.rubocop.yml`: lint seam for repo-local agent helper scripts. Keep it\n  aligned with `shakacode/agent-workflows/.rubocop.yml`, with only local\n  toolchain compatibility adjustments such as this repo's supported Ruby target.\n- `.agents/agent-workflow-drift.yml`: immutable source revision and reviewed\n  exact/overlay mapping for repo-pinned shared workflow files. Required CI checks\n  out that revision, runs the consumer-owned completeness test, then runs the\n  source pack's read-only drift checker. Update the manifest and hashes only as\n  part of a reviewed shared-workflow reconciliation.\n- If a tool or skill picker only exposes installed/global skills, treat those\n  skills as launchers. Installed/global skills never override this repo's\n  `AGENTS.md`; repo-local files win only when this repo explicitly names or\n  keeps a local copy/override.\n- Installed Shaka is the only seam validator. It validates\n  `.agents/agent-workflow.yml`; required CI pins the reviewed Shaka Git revision\n  and runs candidate-only validation. Pack management helpers such as `agent-workflows-status`,\n  `install-agent-workflows`, `upgrade-agent-workflows`, and `bin/validate`\n  remain transitional installed/shared-pack tools.\n- `.agents/bin/agent-workflow-drift-manifest-test.rb`: the consumer-owned\n  completeness boundary for pinned shared files. It governs explicit files and\n  whole source-pack prefixes, including reviewed source-only exclusions, so a\n  new upstream helper cannot silently escape the drift manifest.\n- `internal/contributor-info/agent-workflow-adoption.md`: React on Rails'\n  current Shaka seam boundary, transitional source-pack content, and validation\n- `internal/contributor-info/portable-agent-workflows-seam-design.md`: current\n  Shaka seam architecture and legacy retirement status\n- `internal/contributor-info/agent-pr-batch-skills.md`: contributor guide for choosing and sequencing `$plan-issue-triage`, `$plan-pr-batch`, and `$pr-batch`\n- `internal/contributor-info/multi-batch-operations.md`: operator guide for running multiple batches across machines, launch surfaces, and repos\n- `internal/contributor-info/issue-evaluation.md`: principles for deciding whether issues and proposed fixes are worth implementing\n- When deciding whether an issue or proposed fix is worth doing, use the\n  installed/shared `$evaluate-issue` skill; a short invocation is\n  `$evaluate-issue` or \"Is this issue worth fixing?\"\n- When deciding whether a React on Rails issue belongs on the active release\n  train (`release/X.Y.Z`, especially `release/17.0.0`) or should wait for\n  `main`, use the repo-local\n  `.agents/skills/react-on-rails-release-train-issue-evaluation/SKILL.md`; a\n  short invocation is `$react-on-rails-release-train-issue-evaluation`.\n- When the user wants a ready prompt for review-only GitHub issue triage or an\n  all-open-issues audit, use the installed/shared `$plan-issue-triage` skill; a\n  short invocation is `$plan-issue-triage` or \"Plan an issue triage\"\n- When the user wants a generated whole-surface issue/PR inventory, dependency\n  graph, and capacity-aware batch split, use the installed/shared `$triage`\n  skill; a short invocation is `$triage` or \"Run triage\"\n- When the user wants to choose issues or PRs for a future agent/Codex/Claude\n  batch, use the installed/shared `$plan-pr-batch` skill to produce a ready\n  `$pr-batch` goal; a short invocation is `$plan-pr-batch` or \"Plan a PR batch\"\n- When the user wants a multi-issue or multi-PR agent/Codex/Claude batch, use the\n  installed/shared `$pr-batch` skill; a short invocation is `$pr-batch`,\n  \"Run an agent batch\", \"Run a Codex batch\", or \"Run a Claude batch\"\n- When the user wants to stop or cancel an in-flight Codex/Claude batch (for example to relaunch it with updated skills), follow the **Cancelling Or Stopping A Batch** protocol in `.agents/workflows/pr-processing.md#cancelling-or-stopping-a-batch`; there is no short skill invocation for this coordinator action\n- When the user wants to audit merged batch work, missed reviews,\n  release-candidate risk, or possible bad merges, use the installed/shared\n  `$post-merge-audit` skill; reusable prompts live in\n  `.agents/workflows/post-merge-audit.md`\n- When the user wants an adversarial PR review, red-team review, Claude/Codex\n  comparison review, or a stricter pre-merge gate, use the installed/shared\n  `$adversarial-pr-review` skill; reusable prompts live in\n  `.agents/workflows/adversarial-pr-review.md`\n- When the user assigns an issue, PR, review-fix pass, or merge queue to an agent, follow `.agents/workflows/pr-processing.md`\n- When the user asks to address PR review comments, use the installed/shared\n  `$address-review` skill; `.agents/workflows/address-review.md` remains a\n  copy/paste prompt for assistants without skill support\n- When the user wants to manually verify a bug-fix PR by reproducing the failure\n  before the fix and confirming it is gone after (with captured evidence or\n  screenshots, optionally posted to the PR and issue), use the installed/shared\n  `$verify-pr-fix` skill; a short invocation is `$verify-pr-fix` or\n  \"manually verify this fix\"\n- When the user explicitly asks for destructive React on Rails stress testing,\n  use the repo-local `.agents/skills/stress-test/SKILL.md`; a short invocation is\n  `$stress-test`\n- When the user plans, implements, validates, or reviews RSC page performance\n  optimization in this repo, use the repo-local\n  `.agents/skills/optimize-rsc-performance/SKILL.md`; a short invocation is\n  `$optimize-rsc-performance`\n- When React on Rails release-train changelog work needs `target=release` or a\n  PR targeting `release/X.Y.Z`, use the repo-local\n  `.agents/skills/react-on-rails-update-changelog/SKILL.md`; a short invocation\n  is `$react-on-rails-update-changelog`. For ordinary mainline changelog updates\n  on `main`, use the installed/shared `$update-changelog` skill.\n- When a maintainer wants to run or inspect RC/beta validation across the demo\n  fleet, use the repo-local `.agents/skills/run-fleet-validation/SKILL.md`; a\n  short invocation is `$run-fleet-validation`. Its Ruby generator reads\n  `internal/contributor-info/demo-fleet.yml` and emits a complete lifecycle pack:\n  release/capability preflight, balanced subagent-driven hard-gate prompts,\n  report-only soft-track coverage, a durable result ledger/schema, independent\n  audit, authorized merge, reachability/tree-parity proof, and tracker closeout.\n  The same skill also generates public-only standing-health packs that verify\n  stable artifact currency, exact-default-head CI/smoke, review-app capability,\n  default-branch staleness, and the evaluated Dependabot v1 policy without\n  mutating demo repositories.\n- Default simplify model: `claude-opus-4-8`\n\n## External Flagship Demo Coordination\n\nThe public [`shakacode/react-on-rails-demo-flagship`](https://github.com/shakacode/react-on-rails-demo-flagship)\nrepo is the single clone-and-run flagship example for React on Rails Pro, React Server Components, React 19,\nstreaming SSR, the Node renderer, Shakapacker, and Rspack.\n\nUpdate that demo repo when changes in this monorepo affect the recommended user-facing Pro/RSC path, including:\n\n- React on Rails Pro or RSC generator output (`--pro`, `--rsc`, `react_on_rails:pro`, `react_on_rails:rsc`)\n- Pro installation, licensing, or \"license optional for evaluation/demo/non-production\" messaging\n- React, React DOM, `react-on-rails-rsc`, Shakapacker, Rspack, or Node renderer version pins/defaults\n- Auto-bundling behavior for `.client.` / `.server.` files or the `'use client'` directive\n- Streaming SSR/RSC helper usage, Node renderer configuration, Docker, or deployment defaults, including changes that\n  affect `bin/smoke` or Docker smoke-validation steps the demo repo runs during verification\n\nWhy: the flagship demo is the external proof that the Pro/RSC happy path works in a real Rails app. If this monorepo\nchanges the recommended path but the demo stays stale, agents and users will copy the wrong setup.\n\nKeep one flagship demo for now. Do not create a separate OSS-only flagship unless the user explicitly asks. The demo's\nREADME should document how to turn Pro/RSC off for comparison, but the default app should remain Pro + RSC.\nAdditional examples are valuable when they teach distinct repo-generation patterns, but they should not dilute or\ncompete with the flagship Pro/RSC path.\n\nThe machine-readable catalog of demos, tiers, and packages is `internal/contributor-info/demo-fleet.yml`.\n\nWhen updating the demo, make the change in a separate checkout/branch of `react-on-rails-demo-flagship`, regenerate and\ncommit lockfiles when dependency changes alter them, and do not mix demo repo commits into this monorepo. Use the\nJavaScript package manager declared by the demo repo (`packageManager` field or lockfile), then run focused validation\nsuch as:\n\n- `bundle install`\n- the lockfile install command for the declared package manager (`npm ci` for the current flagship)\n- `bin/shakapacker` or the equivalent asset build command documented by the demo repo\n- `bin/smoke` or Docker smoke validation\n\n## Canonical Agent Policy\n\n`AGENTS.md` is the canonical source for repository-wide agent rules:\n\n- Commands and test/lint workflow\n- Code style and formatting expectations\n- Git/PR boundaries and safety rules\n- Directory and documentation boundaries\n\nOther agent-facing docs (for example `CLAUDE.md`) should contain only tool-specific workflow notes and link back here.\nIf there is a conflict, `AGENTS.md` wins.\n\n## React on Rails Pro Guardrails\n\nReact on Rails Pro includes the Ruby Pro tree and the Pro npm packages:\n\n- `react_on_rails_pro/`\n- `packages/react-on-rails-pro/`\n- `packages/react-on-rails-pro-node-renderer/`\n\nBefore modifying, copying, vendoring, porting, or reimplementing Pro code from\nany of those paths, read and follow the Pro-specific guardrails in\n[`react_on_rails_pro/AGENTS.md`](react_on_rails_pro/AGENTS.md). Those guardrails\ndo not replace the Pro license or EULA; they tell agents when to stop and ask\nfor explicit licensing confirmation.\n\n## Freshness And Skill Resolution\n\nBefore planning issue/PR work, creating a new branch, or creating a new\nworktree, run:\n\n```bash\ngit fetch --prune origin main\n```\n\nBase new issue branches and new worktrees on the freshly fetched `origin/main`\nunless the user explicitly asks to reproduce an old SHA, continue an existing PR\nbranch, bisect, or work offline. Creating a new worktree does not fetch from\nGitHub by itself.\n\nAfter fetching, verify the `## Agent Workflow Configuration` seam before relying\non installed/shared skills for issue, PR, or batch work:\n\n```bash\nshaka seam check --root \"$(pwd)\" --ref \"$(git rev-parse origin/main)\"\n```\n\nThis trusted-ref check establishes workflow policy. Candidate CI validation uses\nthe separately pinned Shaka checkout with `--local`, which grants neither policy\nnor merge authority.\n\nIf a workflow explicitly needs a repo-local `.agents/skills/...` file, it should\nbe a repo-specific local skill such as `stress-test` or\n`optimize-rsc-performance`, release-branch changelog handling such as\n`react-on-rails-update-changelog`, a pinned helper `bin/` copy without\n`SKILL.md`, or a deliberate override. Shared workflow skills normally resolve\nfrom the installed/shared pack for picker-visible instructions. Helper commands\nmay resolve to repo-pinned `.agents/skills/<skill>/bin` copies so checkout-only\nor directory-restricted agents can still run repo workflows. If a required\nrepo-local skill or `.agents/workflows/...` file is missing in the checkout but\npresent on `origin/main`, update the worktree before continuing; if it is still\nmissing, report the repo workflow state as `UNKNOWN`.\n\nFor user-installed shared skills, check the installed pack with:\n\n```bash\nagent-workflows-status --host codex\n```\n\nUse `--host claude` for Claude Code installs. Upgrade the transitional shared\npack, then validate this repository with trusted Shaka:\n\n```bash\nupgrade-agent-workflows --host codex\nshaka seam check --root \"$(pwd)\" --ref \"$(git rev-parse origin/main)\"\n```\n\n<!-- prettier-ignore-start -->\n## Agent Workflow Configuration\n\nResolve the trusted default branch to an immutable commit. Load and validate\n`.agents/agent-workflow.yml` with the trusted installed `shaka seam check --ref REF`\ncommand. Run the fixed executable paths reported by that command from the candidate\ncheckout; do not reconstruct their behavior from prose. `AGENTS.md` retains human-only boundaries.\n\n## Workflow Policy Notes\n<!-- prettier-ignore-end -->\n\nShaka typed policy (`version`, `base_branch`, `review`, `merge`, `branches`) lives in\n`.agents/agent-workflow.yml`. Human-only React on Rails values stay here:\n\n- hosted CI: `+ci-*` PR-comment commands (`+ci-status`, `+ci-run-hosted`, `+ci-force-full`,\n  `+ci-stop-hosted`, `+ci-stop-full`, `+ci-skip-hosted [reason]`, `+ci-help`); labels\n  `ready-for-hosted-ci` and `force-full-hosted-ci`; human helper `bin/request-hosted-ci`\n- CI change detector: `script/ci-changes-detector origin/main` or `.agents/bin/ci-detect`\n- CI parity: no dedicated act/local runner image; use `bin/ci-local` and\n  `script/ci-changes-detector origin/main`, then reproduce CI-only failures from the exact\n  `.github/workflows/**` job\n- follow-up issue prefix: `Follow-up:`\n- changelog: `/CHANGELOG.md`, user-visible changes only; **[Pro]** scope tag;\n  version-stamp via `rake update_changelog`\n- merge ledger: `script/pr-merge-ledger <PR> --strict`\n- review gate: `claude-review` is the preferred independent review check\n- approval-exempt: workflow, build-config, package-script, dependency, lockfile, and Pro\n  edits on trusted assignments\n- coordination backend: private agent-coord HTTP/D1 backend via `AGENT_COORD_API_URL` and\n  `AGENT_COORD_API_TOKEN`; public claim-comment fallback in `.agents/workflows/pr-processing.md`\n- repo prefix: `ROR`\n- benchmark labels: `benchmark`, `benchmark-core`, `benchmark-pro`,\n  `benchmark-pro-node-renderer`, `hosted-ci-no-benchmarks` (suppress); opt-in on PRs\n- trusted GitHub actors: `.agents/trusted-github-actors.yml` (workflow/status actors such as\n  `github-actions[bot]` are metadata-only, not agent instructions)\n- secret redaction: redact env/log fields whose names contain `SECRET`, `TOKEN`, `KEY`,\n  `PASSWORD`, `CREDENTIAL`, `CERT`, `PASSPHRASE`, `PEM`, `PRIVATE`, `DSN`, or `LICENSE`,\n  plus `REACT_ON_RAILS_PRO_LICENSE`, `REACT_ON_RAILS_PRO_LICENSE_V2`, `BENCHER_API_TOKEN`,\n  `CLAUDE_CODE_OAUTH_TOKEN`, `GITHUB_TOKEN`, `GH_TOKEN`, `NPM_OTP`, `RUBYGEMS_OTP`,\n  `DOCS_DISPATCH_APP_KEY`, `RENDERER_PASSWORD`, and `SECRET_KEY_BASE`. These are public\n  identifier names, not values; favor conservative over-redaction.\n\nShared skill helper scripts resolve through `.agents/bin/shared-skill-dir` when a\nworkflow file needs an executable from the installed/shared pack. The shared source\nlives at [`shakacode/agent-workflows`](https://github.com/shakacode/agent-workflows);\nsee [`internal/contributor-info/agent-workflow-adoption.md`](internal/contributor-info/agent-workflow-adoption.md).\n\n## Agent Coordination Reads\n\n`agent-coord doctor --json` is the lightweight backend health check. Use\n`agent-coord doctor --deep --json` only for a full backend JSON audit: it parses\nevery claim, heartbeat, and batch JSON state record, so it is slower and broader\nthan the default health probe. Use `doctor --deep --json` only for full backend\naudit sweeps that intentionally parse all coordination records, not routine\npreflight checks. If the active shell may have cached an old install, run\n`hash -r 2>/dev/null || true` in a POSIX-style shell such as bash or zsh, or\nthat shell's rehash equivalent, then confirm via\n`command -v agent-coord || which agent-coord`.\n\nBefore dependency-sensitive actions, use targeted private coordination reads.\nThe direct `agent-coord` subcommands are:\n\n```bash\n# Specific issue/PR lane\nagent-coord status --repo shakacode/react_on_rails --target <issue-or-pr> --json\n\n# Batch lane/dependency state\nagent-coord status --batch-id <batch-id> --json\n```\n\nWhen the repo workflow calls for bounded reads, pass the same targeted status\nsubcommand through the installed/shared `pr-batch` helper so a slow private read\nbecomes explicit degraded state instead of an indefinite wait:\n\n```bash\nPR_BATCH_SKILL_DIR=\"${PR_BATCH_SKILL_DIR:-$(.agents/bin/shared-skill-dir pr-batch)}\"\n\n# Specific issue/PR lane\n\"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded\" --timeout 20 status --repo shakacode/react_on_rails --target <issue-or-pr> --json\n\n# Batch lane/dependency state\n\"${PR_BATCH_SKILL_DIR}/bin/agent-coord-bounded\" --timeout 20 status --batch-id <batch-id> --json\n```\n\nDo not use broad `agent-coord status` for routine lane checks. Broad private\ncoordination reads are audit-only; if they time out, exit 1 (unexpected error),\nor exit 2, report private coordination as `UNKNOWN`/degraded and use structured\npublic claim comments only as advisory evidence. Any non-zero exit other than\n`CLAIM_REFUSED` (exit 3) is treated as `UNKNOWN`/degraded. If targeted status\nexits 0, private coordination state is authoritative. Refused claims\n(`CLAIM_REFUSED` / exit 3) remain hard stops for machine agents.\n\n## Commands\n\n```bash\n# Install dependencies\n# The committed root Gemfile.lock is generated with Bundler 4.0.10; use Bundler\n# 4.0.10 or newer before running root bundle commands.\nbundle && (cd react_on_rails && bundle) && pnpm install\n\n# The root Gemfile is intentionally limited to repo-wide lint, hook, release,\n# and benchmark script spec tooling. After changing package Gemfiles, run bundle\n# install in that package directory; after changing the root Gemfile, run bundle\n# install at the repo root to sync the tooling lock.\n\n# Build TypeScript → JavaScript\npnpm run build\n\n# Lint (MANDATORY before every commit)\n(cd react_on_rails && BUNDLE_GEMFILE=../Gemfile bundle exec rubocop) # OSS Ruby lint — CI-equivalent\n# Pro Ruby lint — CI-equivalent when Pro files or RuboCop config change\n(cd react_on_rails_pro && BUNDLE_GEMFILE=../Gemfile bundle exec rubocop --ignore-parent-exclusion)\npnpm run lint                                                    # JS/TS via ESLint\npnpm start format.listDifferent                                  # Check Prettier formatting\n(cd react_on_rails && bundle exec rake lint)                     # Package lint task (Ruby + JS + formatting)\n\n# Optional Ruby diagnostic from the repo root (not the CI contract)\nBUNDLE_GEMFILE=\"$(git rev-parse --show-toplevel)/Gemfile\" bundle exec rubocop\n\n# Auto-fix formatting\n(cd react_on_rails && bundle exec rake autofix) # Preferred for all formatting\n\n# Run tests\n(cd react_on_rails && bundle exec rake run_rspec:gem)   # Ruby unit tests (gem code)\n(cd react_on_rails && bundle exec rake run_rspec:dummy) # Ruby integration tests (dummy Rails app)\npnpm run test                        # JavaScript/TypeScript tests\n(cd react_on_rails && bundle exec rake)                 # Full package suite (lint + tests except examples)\n\n# Type checking\npnpm run type-check                  # TypeScript\n(cd react_on_rails && bundle exec rake rbs:validate) # RBS signatures\n\n# Additional test subsets\n(cd react_on_rails && bundle exec rake run_rspec) # All Ruby tests\n(cd react_on_rails && bundle exec rake all_but_examples) # All tests except generated examples\n(cd react_on_rails && bundle exec rake run_rspec:shakapacker_examples_basic) # Single example test\n\n# Documentation checks\nscript/check-docs-sidebar            # Validate docs sidebar coverage\nbin/check-links                      # Markdown link checks (requires lychee)\n\n# Full initial setup\nbundle && (cd react_on_rails && bundle) && pnpm install && \\\n  (cd react_on_rails && bundle exec rake shakapacker_examples:gen_all node_package && bundle exec rake)\n\n# CI/workflow linting\nactionlint                           # GitHub Actions lint\nyamllint .github/                    # YAML lint (do NOT run RuboCop on .yml files)\n\n# Dependency version updates\nrake shakapacker:update_version[9.6.1]  # Update shakapacker across the monorepo\n```\n\n### Updating Shakapacker\n\nUse `rake shakapacker:update_version[VERSION]` to update shakapacker across the entire monorepo. This single command updates all Gemfiles, package.json files, Gemfile.lock files, and pnpm-lock.yaml. Do **not** manually edit individual version references — always use the rake task to keep everything in sync.\n\nThe task handles Ruby version switching for apps that require a different Ruby version (set `RUBY_VERSION_MANAGER` to `rvm`, `rbenv`, `asdf`, or `mise` if needed; defaults to `rvm`). It continues gracefully if a single lock file update fails (e.g., due to a missing Ruby version).\n\nAfter Shakapacker version or default updates, check the External Flagship Demo Coordination section to decide whether the\nflagship demo needs the same change.\n\n## Testing\n\n- **Prefer local testing over CI iteration** — don't push \"hopeful\" fixes. Apply the **15-minute rule**: if 15 more minutes of local testing would catch the issue before CI does, spend the 15 minutes.\n- **Never claim a test is \"fixed\" without running it locally first.** Use \"This SHOULD fix...\" or \"Proposed fix (UNTESTED)\" for unverified changes.\n- **Automated tests passing is necessary but not sufficient.** If your changes affect how the app starts, builds, or serves, you must also verify the dev environment manually. See [Manual Dev Environment Testing](.claude/docs/manual-dev-environment-testing.md) for the full checklist.\n- **Ruby**: RSpec. Unit tests in `react_on_rails/spec/react_on_rails/`, integration tests via a dummy Rails app in `react_on_rails/spec/dummy/`.\n- **JavaScript/TypeScript**: Jest. Tests in `packages/react-on-rails/tests/`.\n- **E2E**: Playwright. Tests in `react_on_rails/spec/dummy/e2e/playwright/e2e/`. Run with `cd react_on_rails/spec/dummy && pnpm test:e2e`.\n- **The dummy app** (`react_on_rails/spec/dummy/`) is a full Rails application used for integration testing. Many tests require it.\n\nRun specific test files:\n\n```bash\n(cd react_on_rails && bundle exec rspec spec/react_on_rails/path/to/spec.rb)\ncd react_on_rails/spec/dummy && bundle exec rspec spec/path/to/spec.rb\n```\n\n## Project Structure\n\n| Directory                                        | Purpose                                                                                  |\n| ------------------------------------------------ | ---------------------------------------------------------------------------------------- |\n| `react_on_rails/lib/react_on_rails/`             | Ruby gem source — helpers, configuration, SSR pool, engine                               |\n| `react_on_rails/lib/generators/`                 | Rails generators for `react_on_rails:install`                                            |\n| `react_on_rails/spec/`                           | RSpec tests (unit + integration via dummy app)                                           |\n| `react_on_rails/spec/dummy/`                     | Full Rails app for integration testing and E2E                                           |\n| `packages/react-on-rails/src/`                   | TypeScript source — client-side React integration                                        |\n| `packages/react-on-rails/tests/`                 | Jest tests for the npm package                                                           |\n| `react_on_rails_pro/`                            | Pro package (separate gem + npm)                                                         |\n| `rakelib/`                                       | Rake task definitions                                                                    |\n| `docs/oss/`                                      | OSS documentation — published to the [ShakaCode website](https://reactonrails.com/docs/) |\n| `docs/pro/`                                      | Pro documentation — installation, configuration, RSC, node renderer, caching             |\n| `internal/contributor-info/`                     | Internal contributor docs (not published to the website)                                 |\n| `internal/planning/`                             | Internal planning docs, designs, and drafts                                              |\n| `internal/react_on_rails_pro/contributors-info/` | Internal Pro contributor docs (not published to the website)                             |\n| `internal/analysis/`                             | Investigation and analysis documents (kebab-case `.md` files)                            |\n\n## Code Style\n\n### Ruby (RuboCop)\n\nLine length max 120 characters. Run `bundle exec rubocop [file]` to check.\n\n**Line length — break long chains:**\n\n```ruby\n# Bad\ncontent = pack_content.gsub(/import.*from.*['\"];/, \"\").gsub(/ReactOnRails\\.register.*/, \"\")\n\n# Good\ncontent = pack_content.gsub(/import.*from.*['\"];/, \"\")\n                      .gsub(/ReactOnRails\\.register.*/, \"\")\n```\n\n**Named subjects in RSpec:**\n\n```ruby\n# Bad\nsubject { instance.method_name(arg) }\n\n# Good\nsubject(:method_result) { instance.method_name(arg) }\n```\n\n**Security violations — scope disable comments tightly:**\n\n```ruby\n# rubocop:disable Security/Eval\nexpect { evaluate(sanitized_content) }.not_to raise_error\n# rubocop:enable Security/Eval\n```\n\n### JavaScript/TypeScript\n\nPrettier handles all formatting. Never manually format — run `rake autofix` instead.\n\n### GitHub Actions\n\nFor GitHub Actions jobs that install Ruby gems, prefer `.github/actions/setup-bundle` over hand-written `actions/cache` plus `bundle install` steps.\nThe action validates a committed `Gemfile.lock`, configures the bundle path and Bundler version for later `bundle exec` steps,\nrestores/saves the gem cache, and supports non-frozen installs via `frozen: 'false'` for minimum-dependency jobs.\n\n## Git Workflow\n\n**Branch naming**: `type/descriptive-name` (e.g., `fix/ssr-hydration-mismatch`)\n\n**Commit messages**: Explain why, not what. One logical change per commit.\n\n**Squash merges**: When completing a GitHub squash merge, include the PR number in the squash commit title using the format `<PR title> (#<PR number>)`, for example `Docs: clarify rails new JavaScript skip flag (#3666)`. For CLI merges, pass `--subject \"<PR title> (#<PR number>)\"` to `gh pr merge --squash` and verify the title before confirming the merge.\n\n**PR creation**: Use `gh pr create` with a clear title, self-contained why/rationale summary, implementation summary, and test plan. If an issue exists, link it, but do not make reviewers open the issue to understand why the PR exists; include at least a short rationale in the PR description itself.\n\n**PR processing**: Before pushing a review-fix batch, opening a PR, marking a PR ready, requesting hosted CI, requesting force-full hosted CI, or reporting merge-readiness, run the agent PR processing flow in `.agents/workflows/pr-processing.md`: verify the work is worth doing, self-review the diff, run local validation, use the pre-push AI review and simplify gate when appropriate, batch fixes, and document exact verification evidence plus churn notes. After a PR and its reviews exist, wait for configured review agents and triage actionable review feedback before marking ready, requesting merge, or merging.\n\n**Hosted CI usage**: Do not use hosted CI as the first real validation pass. Prefer local checks first, then optimized hosted CI when the branch is ready for remote confirmation or final validation. Use the `+ci-*` PR comment commands for an auditable decision: `+ci-status` before deciding, `+ci-run-hosted` after the final push for optimized hosted CI, `+ci-force-full` only when a maintainer intentionally wants every hosted suite to bypass optimized selection, `+ci-stop-hosted` to return an iterating PR to the required gate, `+ci-stop-full` to remove only the force-full override, `+ci-skip-hosted [reason]` only with explicit maintainer approval for a low-risk waiver, and `+ci-help` when syntax is unclear. Put one `+ci-*` command per PR comment. Human/user-token label writes through `bin/request-hosted-ci` or `gh pr edit --add-label ready-for-hosted-ci` are valid, but workflow-token label writes are not a current-head trigger; automation must dispatch workflows explicitly or use `+ci-run-hosted`.\n\n**GitHub follow-up issues**: Follow-up issues are the exception. Prefer fixing or declining review feedback in the PR. If deferred work remains valuable, present one bundled deferred-work summary and ask whether to track it. Prefer an existing issue; otherwise create at most one bundled issue per PR unless the user explicitly approves more. New follow-up issue titles must begin with `Follow-up:`. Build multi-line issue bodies as Markdown files and pass them with `gh issue create --body-file`; do not pass escaped newline strings through `--body`.\n\n**GitHub Actions post-merge exercise follow-ups**: Semantic changes to `.github/workflows/**` or `.github/actions/**`\nare a standing exception to the default \"no follow-up issue\" rule. Before merge, link an existing tracking issue or\ncreate one bundled issue titled `Follow-up: Exercise GitHub Actions changes from PR #NNNN`. The issue must name the\nsource PR, changed workflow/action files, exact post-merge event or secondary verification PR to exercise, expected\nevidence, cleanup instructions for any verification-only PR, and owner if known. This is required for trigger,\npermission, job, matrix, condition, concurrency, secret, reusable-action, command-parsing, workflow-dispatch, or\nCI-routing behavior changes. It is not required for comments, docs, typo fixes, formatting-only changes, or\nnon-semantic actionlint cleanup when local validation evidence documents that classification.\n\n**Process gap disposition**: When an audit, review, or batch closeout finds a recurring process miss, do not add a prose-only rule by default. The issue plan or PR evidence must choose one mechanism target: `script`, `schema`, `checklist+replay`, or `park`, and record the motivating miss, replay evidence or park reason, and non-goal. `park` means the miss is plausible but not worth mechanizing now.\n\n### Release Version Ownership\n\n`bundle exec rake release[...]` owns the coordinated React on Rails product-version\nchange. For ordinary RC and final preparation, agents prepare and stamp\n`CHANGELOG.md`, but must not manually bump React on Rails' own gem/npm version\nfields or create the ordinary `Bump version to ...` commit. The release task\nupdates the OSS and Pro gem version files, the `version` field in all five\n`package.json` files, and the Ruby `Gemfile.lock` files in that generated commit.\nIt does not run `pnpm install` or regenerate `pnpm-lock.yaml`; workspace-protocol\ndependency conversion during npm publishing is temporary and is restored afterward.\n\nIf a release-preparation or dependency-pin PR changes dependency ranges or pins,\nregenerate the affected npm/pnpm lockfiles in that PR. Do not defer those lockfile\nupdates to the React on Rails product-version release task.\n\nPins for independently released dependencies are separate changes. For example,\npromoting `react-on-rails-rsc` from an RC to a stable version still requires a\nnormal reviewed and tested PR that updates the generator pin, package metadata,\nand affected lockfiles before cutting the next React on Rails RC. Do not confuse\nthat dependency update with manually bumping React on Rails' own version.\n\n## Maintainer Attention Contract\n\nMaintainer attention is for judgment, not for routine progress pings or\nmachine-checkable work. Agents working PRs, reviews, or batches must apply this\ncontract unless a maintainer explicitly narrows the run.\n\n- **Autonomous nits**: behavior-preserving `OPTIONAL` review nits may be fixed\n  inline without asking when they stay inside the PR scope, are low-risk, and are\n  before the final-candidate debounce point: once a merge-readiness review cycle\n  has started, do not introduce new nit commits that would restart it.\n  Inside the PR scope means the file, section, or workflow copy is already part\n  of the PR diff or directly cited by current review feedback. Cross-copy\n  consistency edits are in scope only when the paired section is already in the\n  PR diff or directly cited by current review feedback; this excludes unrelated\n  cleanup, other machine lanes, reserved files, generated output not already in\n  scope, and separate workflow files that merely discuss the same concept.\n  The final-candidate debounce point begins when the agent explicitly\n  designates the current head as merge-ready or the final candidate in a PR\n  body, PR comment, or handoff, or when the agent pushes after completing the\n  final local validation/review gate and records that push as the candidate.\n  Automatically queued checks from ordinary fix-phase pushes do not count unless\n  that push or check set has been declared as the final readiness gate. Earlier\n  incremental per-file checks during the fix phase do not count.\n  Behavior-preserving means wording, formatting, or mechanical\n  whitespace/punctuation cleanup that does not alter public APIs, generated\n  output, runtime behavior, validation scope, or the semantic meaning of any\n  section that has an unresolved review thread on it. Low-risk means local and\n  mechanically checkable, such as a formatter-confirmed cleanup; a rename that\n  requires searching all callers is not low-risk. Mechanical means deterministic\n  and local, such as rerunning a formatter or fixing whitespace introduced by\n  the nit, without reasoning about runtime behavior, callers, or policy.\n  Qualifying examples: typo/comment punctuation, whitespace or trailing comma\n  cleanup, or unambiguous documentation wording.\n  Disqualifying examples: renaming a public method or constant, changing\n  generated content, altering CI or release policy, adding/removing validation,\n  removing an import or `require` whose module side effects are not proven by a\n  dedicated tool or code inspection, or touching another lane's files. If the nit\n  is not worth fixing, record it as deferred or declined with rationale instead\n  of asking \"OK to fix this nit?\".\n  Autonomous deferred/declined nit replies must include `[auto-deferred]` on its\n  own line plus a one-line rationale, for example:\n  ```text\n  [auto-deferred]\n  Whitespace cleanup deferred to avoid restarting the final-candidate gate.\n  ```\n  Post the tag and rationale before resolving the review thread; do not resolve\n  an auto-deferred thread without that reply.\n  If an autonomous nit fix fails local validation or self-review, repair it in\n  the same batch only when the repair is still mechanical and in scope;\n  otherwise drop or revert that nit, record the failed validation and rationale,\n  and promote the underlying concern to `DISCUSS` only when it is a correctness\n  issue, regression risk, or explicit reviewer request.\n  Never push a failing autonomous nit or ask the maintainer to debug it.\n  Escalate only when the item changes behavior, expands scope, conflicts with\n  policy, or has unclear risk.\n- **CI-wait protocol**: while checks or review bots are running, do bounded\n  useful work such as self-review, local-only cleanup notes, documentation sync\n  that does not require pushing the active PR head, or another independent lane.\n  Do not introduce optional cleanup commits that restart current-head gates after\n  the final-candidate debounce point. Do not interrupt the maintainer for routine\n  \"CI is still running\", \"CI is green\", or \"review arrived\" updates. CI failures\n  and new `MUST-FIX`-tier review findings are not routine; surface them\n  immediately.\n- **One decision point per lane**: batch genuine judgment calls into one decision\n  block at lane completion or hard block. The block must include the question,\n  options, recommendation, evidence links or command output, and the next action\n  after an answer. Avoid \"see above\" decisions that require the maintainer to\n  reconstruct context.\n- **Self-verification before escalation**: anything provable by tests, lint,\n  screenshots, repro scripts, `gh` state, or code inspection must arrive with\n  that evidence attached. Use `UNKNOWN` for facts that could not be verified.\n- **Attention metric**: batch closeouts count human decision points per PR, with\n  a target of at most one for low-risk lanes: lanes with no `MUST-FIX` items,\n  no blocking questions, and only documentation, process, or mechanical changes.\n  Higher counts are reported as FYI process churn, not hidden in narrative\n  handoffs. Counts above target invite a later check on whether smaller lanes,\n  sharper scope, or better batching would reduce future churn; they are not a\n  hard failure by themselves. A human decision point is any question, option\n  selection, or confirmation directed at a maintainer that required direct input,\n  excluding git confirmations that safety rules or explicit local-only /\n  inspect-before-push instructions require after the maintainer already selected\n  the action, such as a required confirmation before a destructive force-push. A\n  standalone \"should I push this ordinary PR-iteration fix?\" question counts.\n  Report it as `Decision points: N` in the FYI section of the batch handoff.\n- **Confidence notes**: `merge_authority` has three states:\n  `auto_merge_when_gates_pass` is the only autonomous merge grant when the\n  current user or batch goal grants it and the release-mode rules permit it;\n  `ask` requires one confirmation before merging; and `none` grants no merge\n  authority. When `auto_merge_when_gates_pass` applies and the gate is met,\n  exercising it is the expected close-out — an authorized, gate-satisfied,\n  confident merge that is downgraded to a \"ready to merge\" recommendation is an\n  unfinished task, not a safe default. Before exercising merge authority,\n  complete the confidence note: validations and evidence are recorded, no\n  unresolved MUST-FIX threads remain, and any remaining `UNKNOWN` facts or\n  residual risk do not affect merge safety. Before a merge under\n  `auto_merge_when_gates_pass` or after an `ask` confirmation, the worker or\n  coordinator documents the merge qualifications in the PR description:\n  - which release-mode gate applied and that it was satisfied\n  - the confidence note: validated commands, evidence links, remaining\n    `UNKNOWN` facts, and residual risk\n  - the finalizer, when accelerated-RC requires one\n\n  This intentionally narrows merge-authority evidence to the PR description so\n  the merge decision is auditable from a single location. Use the issue or batch\n  handoff only for no-merge readiness evidence.\n\n  When merge authority is not granted, use the same confidence-note format for\n  merge-readiness evidence without merging:\n\n  ```text\n  Confidence note:\n  - Validated: <commands or checks run and outcomes>\n  - Evidence: <links to CI, screenshots, logs, or inline output>\n  - UNKNOWN: <facts that could not be verified, or \"none\">\n  - Residual risk: <one-line risk summary, or \"none\">\n  ```\n\n## Tracking Issues And Handoffs\n\nKeep the issue tracker for durable work — product features, real bugs, release\ngates — not for transient agent-process state. Process state accretes into\nclutter because \"open a tracker\" has no matching \"close it\" step.\n\n- **Do not open a new issue for a session handoff or a point-in-time audit.** A\n  handoff is transient coordination and an audit is a snapshot; neither is\n  durable backlog. Record a handoff as a comment on the relevant parent tracking\n  issue (for example the roadmap umbrella), or — if a dedicated agent-coordination\n  repo is in use — there. If the work has no parent umbrella (a standalone PR or a\n  one-off batch), put the handoff in the PR's final comment or description rather\n  than creating an issue to hold it. Append a point-in-time audit to the standing\n  release audit ledger in place. Never spawn a standalone `Handoff: ...` or\n  `Post-rc.N audit` issue.\n- **One durable ledger per recurring concern, updated in place.** Release audits\n  append to the standing release audit ledger; cross-agent coordination state —\n  the heartbeats and leases that signal which agent is live on which lane — lives\n  in the coordination-layer tracker. Do not create a sibling issue each cycle.\n  (At time of writing these are #4010 and #3974, but treat any such number as a\n  movable pointer: confirm it is still the live ledger before relying on it, and\n  update the pointer if it has been superseded — the same staleness this policy\n  guards against applies to the ledgers themselves.)\n- **Closure follows the work, not the opener.** A tracking issue closes when its\n  underlying PR/work lands, done by whoever finishes the work — not by whoever\n  opened the tracker. \"I opened it\" does not mean \"I must close it\": WIP can\n  outlive a session (lost chat, unanswered question, disconnect). The heartbeat —\n  the coordination layer's liveness signal that flags when no agent is active on a\n  lane — detects abandonment, and an unfinished PR is the real signal of remaining\n  work; act on the PR, not on a stale tracker.\n- **The 30-day test.** Before opening any tracking or meta issue, ask whether it\n  will still matter in 30 days. If not, it is a comment or a ledger entry, not an\n  issue.\n- **Sweep on sight.** When a handoff/audit/process-snapshot issue's underlying\n  work has landed or its snapshot is obsolete, close it — first consolidating any\n  still-live finding into the durable ledger or a real backlog issue. Verify it is\n  actually resolved or superseded before closing; never close a tracker that still\n  fronts unfinished work.\n\n## Release Mode And Auto-Merge Coordination\n\nUse the current release tracker to decide whether PRs are in normal development, accelerated RC, strict RC, or final-release mode. The tracker is the live source of truth for the mode; committed docs define how to interpret it.\n\nThe repo ships releases with a **release train**: `main` never freezes and keeps absorbing batch work, RCs are stabilized on an ephemeral `release/X.Y.Z` branch, and the final is the **last good RC promoted by dropping `-rc`** — not a re-cut from `main`. The merge gate an agent must apply is a function of the **target branch's release phase** (`beta` / `rc` / `final`); the phase composes with the mode below. See **[Release-Train Branching And Phase Gating](#release-train-branching-and-phase-gating)** for the phase→gate table and [`internal/contributor-info/release-train-runbook.md`](internal/contributor-info/release-train-runbook.md) for the full branching runbook.\n\n- An active tracker is an open release gate issue, usually found by the existing `release` and `TRACKING` labels or the `Release gate:` title. Also search closed release gate issues updated within the last 7 days before defaulting to `development`, so agents can detect stale trackers. The mode must be recorded in the issue body, not encoded by adding more labels.\n- Valid tracker modes are `development`, `accelerated-rc`, `strict-rc`, and `final-release`.\n- If no active tracker exists, assume `development` mode. This is not a blocker; it means the repo is moving toward the next beta/RC/final. If a release tracker was closed within the last 7 days and lacks a closing label/comment containing `Released` or `Superseded`, report `release-mode-stale-tracker` and do not auto-merge until a maintainer confirms the mode. A maintainer can resolve the stale signal with a PR or tracker comment such as `No active release, proceed`; verify the comment author has `write`, `maintain`, or `admin` permission before treating it as maintainer confirmation. Inspect tracker labels and comments with `gh issue view <tracker> --comments --json labels,comments` before deciding that the closing signal is absent.\n- If exactly one active tracker exists, read its `Agent Release Mode` block from the issue body. If the block is absent, use `strict-rc` and report the missing block.\n- If multiple active trackers have different final release targets, select the tracker matching the PR's target only when the target is unambiguous from the PR body, linked issue, branch, or release/changelog text. If the PR target is unclear, or if trackers for the selected target disagree about mode or canonical status, report `release-mode-conflict` and do not auto-merge until resolved. Do not let unrelated final-release targets block each other when the PR target is clear.\n- For duplicate trackers with the same final release target (the eventual semver without prerelease suffix, for example `v1.2.0.rc.1` and `v1.2.0.rc.2` share the `v1.2.0` target) and no conflicting mode, the oldest open tracker is canonical unless it explicitly says it is superseded by another tracker. If same-target trackers disagree about mode or canonical status, report `release-mode-conflict` and do not auto-merge until resolved. Agents may close clean duplicates only after preserving non-conflicting useful information in the canonical tracker and posting a closing comment that links to the canonical issue.\n- Agents do not auto-create release trackers. A maintainer creates one when entering accelerated RC, strict RC, or final-release coordination.\n- To avoid concurrent issue-body overwrites, re-read the tracker immediately before editing it. Prefer append-only comments for per-PR/batch status from concurrent agents, and only edit the tracker body when preserving the latest body content. If the latest tracker body changed in a way the agent cannot safely merge, post a comment with a `Tracker Update:` header containing the intended update and report the conflict; later agents must fetch tracker comments and consider both the latest body and latest unresolved `Tracker Update:` conflict comment before acting.\n\nReporting `release-mode-stale-tracker`, `release-mode-conflict`, or a missing\nrelease-mode block means posting a PR comment with a `Release Mode Block:`\nheader, the signal name, relevant tracker URLs, and the current decision.\n\nIn `development` and `strict-rc` modes, apply the standard merge qualification in the Review Workflow section; the accelerated-RC confidence block and auto-merge threshold do not apply. In `final-release` mode, do not auto-merge; apply standard merge qualification plus the final-release audit and explicit maintainer release decision below.\n\nDuring `accelerated-rc`, affected areas such as SSR, RSC, hydration, package release, generators, CI, benchmarks, and Pro/core boundaries do not cap confidence by themselves. They choose the validation checklist. Actual uncertainty, missing proof, failed checks, or unresolved findings lower confidence.\n\nAuto-merge during accelerated RC requires a finalized PR-body confidence block. The authoring agent may draft it, but a separate coordinator, finalizer, or review agent must finalize it. The finalizer must be a different GitHub account or named GitHub check/app identity than the PR authoring agent, verifiable from the git log or GitHub review/check record. Two sessions running under the same GitHub acco\n\n<!-- File: llms.txt (Tokens: ~1159 | Category: root-instruction) -->\n# React on Rails\n\nReact on Rails integrates React with Ruby on Rails. Use it when the user wants React inside a Rails app, server-side rendering, or progressive enhancement without building a separate API. Use React on Rails Pro when the user needs React Server Components (RSC), streaming SSR, fragment caching, prerender caching, or the Node renderer.\n\nUse this file as the short machine-readable route map. Use `./llms-full.txt` for the expanded OSS reference and `./llms-full-pro.txt` for the expanded React on Rails Pro reference. Use `./AGENTS_USER_GUIDE.md` for the repo-oriented guide to the machine-readable layer.\n\n## Canonical entry points\n\n- Human docs overview: https://reactonrails.com/docs/\n- OSS docs hub: https://reactonrails.com/docs/introduction\n- Pro docs hub: https://reactonrails.com/docs/pro\n- RSC docs hub: https://reactonrails.com/docs/pro/react-server-components\n- Expanded machine-readable reference (OSS): `./llms-full.txt`\n- Expanded machine-readable reference (Pro): `./llms-full-pro.txt`\n- Agent usage guide: `./AGENTS_USER_GUIDE.md`\n\n## Package pairing\n\n- OSS: Ruby gem `react_on_rails` plus npm package `react-on-rails`\n- Pro: Ruby gem `react_on_rails_pro` plus npm package `react-on-rails-pro`\n- Optional Pro Node renderer: npm package `react-on-rails-pro-node-renderer`\n- Do not use `react_on_rails_pro` with the base `react-on-rails` npm package\n\n## Start here by task\n\n- New Rails app with React:\n  - Quick Start: https://reactonrails.com/docs/getting-started/quick-start\n  - Create a New App: https://reactonrails.com/docs/getting-started/create-react-on-rails-app\n  - Tutorial: https://reactonrails.com/docs/getting-started/tutorial\n- Existing Rails app:\n  - Install into an Existing Rails App: https://reactonrails.com/docs/getting-started/existing-rails-app\n  - Using React on Rails: https://reactonrails.com/docs/getting-started/using-react-on-rails\n  - Architecture overview: https://reactonrails.com/docs/core-concepts/how-react-on-rails-works\n- Styling:\n  - Tailwind CSS v4 recipe: https://reactonrails.com/docs/building-features/styling-with-tailwind\n- Choosing OSS vs Pro:\n  - OSS vs Pro: https://reactonrails.com/docs/getting-started/oss-vs-pro\n  - Pro hub: https://reactonrails.com/docs/pro\n  - Upgrade to Pro: https://reactonrails.com/docs/pro/upgrading-to-pro\n- React Server Components:\n  - RSC hub: https://reactonrails.com/docs/pro/react-server-components\n  - RSC tutorial: https://reactonrails.com/docs/pro/react-server-components/tutorial\n  - Add RSC to an existing Pro app: https://reactonrails.com/docs/pro/react-server-components/upgrading-existing-pro-app\n- Node renderer:\n  - Pro overview: https://reactonrails.com/docs/pro/node-renderer\n  - Technical basics: https://reactonrails.com/docs/building-features/node-renderer/basics\n  - JS configuration: https://reactonrails.com/docs/building-features/node-renderer/js-configuration\n- View transitions (experimental, unsupported):\n  - View Transitions recipe + Turbo interplay: https://reactonrails.com/docs/building-features/view-transitions\n- Hydration scheduling:\n  - Defer React root hydration/rendering until immediate, visible, or idle: https://reactonrails.com/docs/building-features/hydration-scheduling\n- Configuration and deployment:\n  - Configuration overview: https://reactonrails.com/docs/configuration\n  - Pro configuration: https://reactonrails.com/docs/configuration/configuration-pro\n  - Deployment: https://reactonrails.com/docs/deployment\n  - Security model and hardening: https://reactonrails.com/docs/deployment/security-model-and-hardening\n  - Troubleshooting: https://reactonrails.com/docs/deployment/troubleshooting\n- Upgrading and migration:\n  - Upgrading: https://reactonrails.com/docs/upgrading/upgrading-react-on-rails\n  - Pro coupled upgrade checklist (gem + npm + lockfiles, RC version formats, RSC manifest verification): https://reactonrails.com/docs/pro/updating#coupled-pro-upgrade-checklist\n  - OSS release notes: https://reactonrails.com/docs/upgrading/release-notes\n  - Pro release notes: https://reactonrails.com/docs/pro/release-notes\n  - Migrate from Next.js: https://reactonrails.com/docs/migrating/migrating-from-nextjs\n  - Migrate from react-rails: https://reactonrails.com/docs/migrating/migrating-from-react-rails\n  - Migrate from Inertia Rails: https://reactonrails.com/docs/migrating/migrating-from-inertia-rails\n  - Migrate to RSC: https://reactonrails.com/docs/migrating/migrating-to-rsc\n\n## Routing notes\n\n- Prefer the canonical Pro hub at `https://reactonrails.com/docs/pro`.\n- `https://reactonrails.com/docs/pro/react-on-rails-pro` currently redirects to the canonical Pro hub URL above.\n- Keep the machine-readable layer small: use the hub pages above first, then open only the task-specific docs you need.\n\n<!-- File: CLAUDE.md (Tokens: ~699 | Category: claude-rule) -->\n# CLAUDE.md\n\nTool-specific guidance for Claude Code in this repository.\n\n## Source of Truth\n\n`AGENTS.md` is the canonical policy for:\n\n- Commands, tests, and lint workflow\n- Formatting and style requirements\n- Git/PR safety boundaries\n- Project directory boundaries\n\nIf this file conflicts with `AGENTS.md`, follow `AGENTS.md`.\n\n## Behavioral Defaults\n\n- When confident in your changes, **commit and push without asking for permission**. Always monitor CI after pushing, and use the `+ci-*` PR comment commands from `AGENTS.md` when asking maintainers to run, stop, or waive hosted CI.\n- **When `merge_authority` is `auto_merge_when_gates_pass` and the release-mode gate is satisfied, merge; do not stop at a recommendation.** `ask` requires one confirmation before merging, and `none` grants no merge authority. See `AGENTS.md` → Confidence notes for the full tri-state rule, confidence threshold, and required PR-description evidence.\n- Check `main` CI status at session start (injected by `.claude/hooks/main-ci-status.sh`) and again before `gh pr create` or pushing to `main`. See `AGENTS.md` → \"Main branch health\" for the decision framework when `main` is red.\n\n## Git Safety\n\n- **Clean rebase → `git push --force-with-lease` without asking.** When `git rebase origin/main` (or `git pull --rebase`) reports no conflicts, every commit is preserved — republishing is the expected workflow. Just push and report the result.\n- **Ask first when force-pushing in these cases:** you resolved rebase conflicts, you dropped/squashed/reordered commits, or the remote branch has commits you don't have locally.\n- **NEVER `git reset --hard`** on a branch with existing commits (yours or others'). This destroys work. Use a worktree or a new branch instead.\n- **NEVER force-push to `main` or `master`.**\n- If a rebase has conflicts you can't resolve cleanly, abort and ask the user how to proceed.\n\n## Claude-Specific Workflow\n\nUse these docs for Claude-oriented operational guidance:\n\n- `.claude/docs/avoiding-ci-failure-cycles.md`\n- `.claude/docs/replicating-ci-failures.md`\n- `.claude/docs/playwright-e2e-testing.md`\n- `.claude/docs/merge-conflict-workflow.md`\n- `.claude/docs/pr-splitting-strategy.md`\n- `.claude/docs/changelog-guidelines.md`\n- `.claude/docs/project-architecture.md`\n- `.claude/docs/rails-engine-nuances.md`\n- `.claude/docs/debugging-webpack.md`\n- `.claude/docs/rbs-type-checking.md`\n- `.claude/docs/conductor-compatibility.md`\n- `.claude/docs/testing-build-scripts.md`\n- `.claude/docs/main-health-monitoring.md`\n- `.claude/docs/managing-file-paths.md`\n- `.claude/docs/docs-competitive-landscape.md`\n- `.claude/docs/docs-templates.md`\n- `.claude/docs/manual-dev-environment-testing.md`\n- `.claude/docs/validating-node-renderer-changes.md`\n\nFor Pro-package specifics, also read `react_on_rails_pro/CLAUDE.md`.\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~300 | Category: marketplace) -->\n# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/marketplace.json)\n\n<!-- File: .claude-plugin/plugin.json (Tokens: ~300 | Category: plugin-manifest) -->\n# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.claude-plugin/plugin.json)\n\n<!-- File: .cursor/mcp.json (Tokens: ~300 | Category: mcp-config) -->\n# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/shakacode/react_on_rails/HEAD/.cursor/mcp.json)\n</yakaai_skills>"}