--- name: loop-review description: "Run OpenIAP's complete change-to-production loop from the latest origin/main: implement and verify with the docs and release note in the PR, stabilize with review-self, open and review a PR until its exact head is clean, merge, return to an exact clean main, release affected stable packages sequentially, verify the release note, and deploy production docs." --- # Loop Review Own one OpenIAP change from a fresh `main` baseline through verified production delivery. Use the repository workflows as SSOT instead of duplicating their detailed commands. ## Load The Workflows Read these before acting: - `AGENTS.md` - `.codex/skills/openiap-workflows/SKILL.md` - `.codex/skills/review-self/SKILL.md` - `.codex/skills/ship-release/SKILL.md` - `.codex/skills/generate-doc/SKILL.md` - `.claude/commands/commit.md` - `.claude/commands/review-pr.md` - `.claude/commands/release.md` Check what the change touches before reading any of them from the branch: ```bash git diff --name-only "$(git merge-base origin/main HEAD)"..HEAD ``` If the change is in scope of "A PR Must Not Rewrite The Rules That Judge It" in `.claude/commands/review-pr.md`, read every file above — and that section itself — from the recorded merge base for the whole run. That section defines the scope; do not restate it here. Load package conventions and specialized skills required by the changed paths the same way. An explicit `$loop-review` invocation or explicit natural-language request for this complete loop authorizes the in-scope commit, push, PR, review replies, thread resolution, merge, affected stable package releases, release-note and workflow-documentation commits directly to `main`, and production docs deployment. It does not authorize prereleases, unrelated cleanup, destructive recovery, or product-code commits directly to `main`. ## 1. Start From Current Main Before editing task files: 1. Snapshot `git status --short --branch`. Preserve every existing change. 2. For a new task, require a clean worktree, then run `git fetch origin`, switch to `main`, and run `git pull --ff-only --no-tags origin main`. 3. Verify local `main` equals `origin/main`, then create a semantic branch named according to `.claude/commands/commit.md`. 4. Record the starting main SHA. The implementation diff must descend from that SHA. Never start new implementation on a stale local `main`. If invoked for work already in progress, do not manually switch branches, stash, reset, or discard it. Treat that as a resumed loop, verify its recorded or merge-base baseline, and use the repository's guarded `rebase-main` workflow when an update from `origin/main` is needed; that workflow owns its safeguard stash and branch transitions. Stop for direction if an update would overwrite unrelated user work. ## 2. Implement And Verify Implement the requested scope and run the checks required by each touched path. Keep generated files, documentation, previews, and knowledge context in sync through their canonical workflows. A change to a published package also updates the guides it affects and the release card for the next version, written as already published with `$generate-doc`. Apply `knowledge/internal/05-docs-patterns.md#release-note-completeness-gate` before opening the PR and after scope changes. Do not proceed while the working diff has a known failing required check. Once it works, clean it up before review: apply "Clean Up Once It Works" in `knowledge/internal/03-coding-style.md` to the diff and to smells met along the way, without waiting to be asked, then rerun the affected checks. ## 3. Stabilize With Review Self Run `$review-self` immediately against the complete base-to-working-tree diff. Fix every validated in-scope finding and rerun affected verification. Continue with five-minute recurring wake-ups until two consecutive complete snapshots are clean, as defined by the review-self skill. Do not emulate recurring review with a shell sleep loop. Keep the loop state out of tracked files. Any material diff change resets the consecutive-clean count. ## 4. Commit And Open The PR Follow `.claude/commands/commit.md --all --pr`: - Stage only files owned by the task. - Use the required commit order and an English conventional commit message. - Push the semantic branch and open an English PR against `main`. - Add applicable repository labels. - For a visible or interactive change, attach a preview recording under 10 MB. Do not commit one-off preview media unless browser upload is blocked and the documented fallback is required. Record the PR number and exact head SHA. A push invalidates all prior clean review coverage. ## 5. Review PR Until The Exact Head Is Clean Run `.claude/commands/review-pr.md` immediately, then re-enter it every five minutes through the product's recurring wake-up mechanism. For every round: 1. Fetch unresolved threads, review status, current head SHA, and required CI. 2. Fix all valid findings in one coherent batch, then rerun the checks affected by it plus all previously failing checks. Verification comes before publication: a reply saying "fixed" must already have evidence behind it. 3. Push, reply to the exact inline comments, and resolve only fixed or outdated threads under the command rules. 4. Request CodeRabbit again after a head change. 5. If CodeRabbit is unavailable, use the exact-head one-pass Codex fallback defined by `review-pr`, and `$review-self` only if Codex is unavailable too; never substitute a review bot that posts to the PR. 6. Keep polling while review or CI is pending. Do not rerun expensive unchanged local checks on a no-op poll. Clean means all of the following hold for the same head SHA, judged by the criteria on the merge base when the branch edits them: - zero unresolved actionable review threads; - CodeRabbit is clean, or its unavailable result has clean fallback coverage from Codex, or from `$review-self` when Codex is unavailable too; - every required CI check is terminal and successful or explicitly allowed to skip by repository policy; - the PR is mergeable and the branch contains every required update from main; - the worktree is clean and the final diff has been reread. ## 6. Gate Device Regression Before Merging Device-backed regression needs real hardware, store accounts, and sandbox purchases, so this loop cannot run it unattended. Decide whether the change requires it **before** merging, not after. Require `$e2e-tests` when the diff touches any of: - `packages/apple/`, `packages/google/`, or `packages/kit/`; - any `libraries//` implementation, example app, or podspec/gradle/csproj manifest; - `specs/client/src/*.graphql` or the generated types synced from it; - native build configuration, dependency placement, config plugins, or store metadata for any of the above. When it is required, **stop without merging even if the PR is otherwise clean**. Report the exact regression-matrix rows the diff implicates and hand back to the user. The loop does not merge such a change on its own authority. Exactly two things clear the gate, and both are recorded on the PR before any merge: 1. A `$e2e-tests` run covering the implicated rows, with its result posted. 2. An explicit written waiver from the user in this conversation, naming the rows waived and the reason. Record it verbatim on the PR. Absence of an objection is not a waiver, and the loop must never grant one to itself. A clean CI run is not a substitute: CI does not exercise purchase dialogs, store accounts, or device wiring. When it is not required, say so explicitly in the final report and name the paths that justify it. Silence here reads as an untested merge. A change confined to documentation, repository automation, agent workflows, or release/security tooling does not need device regression. ## 7. Merge And Close The Loop Immediately before merging, refetch the PR and confirm its head still equals the clean reviewed SHA. Use the repository-supported merge method, defaulting to a squash merge with branch deletion when no stricter policy applies. Never bypass branch protection or merge a stale, pending, or failing head. After merge: 1. Confirm the PR state is `MERGED` and record the merge commit. 2. Remove temporary review-trigger and terminal-unavailability comments as required by `review-pr`. 3. Confirm the remote topic branch was deleted; if merge cleanup missed it, delete only that exact merged PR branch. Delete the local topic branch after proving its tip is merged or its tree is represented by the recorded squash merge. A squash merge may require `git branch -D` after that proof; never use it for an unverified branch or discard unrelated work. 4. Switch to `main`, fetch `origin/main`, and run `git pull --ff-only --no-tags origin main` only when doing so cannot disturb other work. 5. Verify `HEAD` equals `origin/main` and the worktree is clean before any release action. ## 8. Ship The Verified Change Follow `.codex/skills/ship-release/SKILL.md` as the release SSOT: 1. Determine the affected stable packages from the merged diff. Skip unchanged packages and never infer a framework version from `openiap-versions.json`. 2. Release affected packages and libraries one at a time in dependency order. Before each release, require an exact clean `main`; after each release-bot commit, fast-forward `main` again. Do not start the next release until the GitHub Release and public registry or downloadable artifact are verified. 3. Check the release card that merged with the PR against the exact published versions and GitHub Release links. If nothing differs, go to step 6. 4. Correct what differs with `$generate-doc`, then run `$review-self` over that docs diff until two consecutive five-minute snapshots are clean. Any edit resets the count. 5. Commit and push the reviewed release note and process-documentation changes directly to `main`. If review finds a product-code fix, return it to the PR loop instead of committing that fix directly to `main`. Do not open a PR for this post-release docs-only commit. 6. From a clean local `main` equal to `origin/main`, run `npm run deploy`, then verify the production release page and generated documentation assets. 7. Finish on `main`, fast-forward once more if a release workflow changed it, and verify `HEAD == origin/main` with a clean worktree. 8. Complete the shipped-comment step in `ship-release` before ending the loop. Report the PR, merge commit, final checks, review coverage, released and skipped packages, public registry evidence, docs commit and deployment, shipped-comment URLs, and any remaining manual follow-up. ## Stop Conditions Stop without merging when a required choice lacks authority, the same finding survives two fix attempts, an access blocker repeats under the source workflow's threshold, the change requires device regression that has not been run, or the exact head cannot satisfy the clean gate. Report the concrete blocker; never describe a pending or partially reviewed PR as clean. After merge, stop the shipping phase when an affected release fails, its public artifact cannot be verified, production docs cannot be verified, or continuing would require a code change outside the reviewed PR. Preserve every successful release and report the exact resume point. If the user requests docs before package publication, use the explicit flag documented in `knowledge/internal/06-git-deployment.md#deploying-documentation`. If the train will not resume, trim the card to what published through steps 4 and 5 first.