--- name: pa-brat-beta-release description: Manage Personal Assistant BRAT beta prerelease workflow. Use when the user asks to prepare, explain, validate, publish, or follow up a BRAT beta/prerelease build; asks about beta branch management; wants to move master-integrated work into BRAT testing; or needs the work branch to master to beta packaging or stable release process. --- # PA BRAT Beta Release Use this skill for Personal Assistant prerelease builds intended for BRAT beta testers. The detailed repo SOP is `docs/operations/brat-beta-testing.md`; read it before changing the workflow or executing a beta release. ## Branch Model Keep these roles distinct: - `master`: the sole integration and release-source branch. All accepted runtime code, tests, research/design docs, governance and release-tooling changes land here through a PR merge or an explicitly authorized direct commit. - Work branch: optional isolation/review transport. It has no beta or stable release authority; accepted commits must enter `master` first. - Beta packaging branch: temporary branch named exactly `beta/`, created from the exact verified `master` HEAD. A beta branch may contain only the generated `[release] vX.Y.Z-beta.N` packaging commit and tag above `master`. Do not add feature/fix/docs commits there, and do not merge or rebase the beta release commit back to `master`. ## Safety Boundaries - Treat `make release`, `make publish`, tag creation, branch pushes, GitHub Releases, and sending BRAT tester instructions to others as release-side effects. - Do not publish, push branches, push tags, create GitHub Releases, or hand off BRAT tester instructions/URLs to others unless the user clearly asks for that action in the current turn. Reporting a verified published URL to the user in this conversation is read-only and does not require separate authorization. - If the target version, `master` baseline, or baseline tag is ambiguous, stop and ask before creating release state. - Prefer `make release-dry-run VERSION=x.y.z-beta.N` before any local release commit/tag. ## Preparation Workflow Choose the lane from the user's request: - **Explain/status/inspect:** read local state, the runbook, and remote status when needed. Do not fetch, switch, pull, create branches, or write release state. - **Dry run only:** inspect `scripts/release.mjs` and run the existing dry-run command when its prerequisites already hold. It writes no release files, but currently requires a clean matching `beta/` branch at `master` HEAD and a tagged baseline. Report unmet prerequisites; a dry-run request alone does not authorize creating branches or changing the checkout to satisfy them. - **Prepare:** perform the workflow below within the requested scope. Preparing the baseline/packaging branch does not authorize a release commit, tag, or push. When asked to prepare a beta: 1. Inspect current state: - `git status --short --branch` - `git branch --show-current` - `node -p "require('./package.json').version"` - `git tag --sort=-v:refname | sed -n '1,20p'` If `git status --short --branch` shows any uncommitted changes, stop before switching or creating beta branches. Ask the user to commit, stash, clean, or explicitly confirm the intended dirty-worktree scope. 2. Confirm all accepted work is already in `master`. A work branch with commits not reachable from `master` must be merged by PR or authorized direct commit before beta preparation continues. 3. Refresh and verify the local integration baseline: - `git fetch origin master` - `git switch master` - `git pull --ff-only` - `git rev-list --left-right --count master...origin/master` Require both counts to be zero before creating the packaging branch. This one preparation check is necessary: `make release` treats a live master mismatch as unavailable CI evidence and falls back to local checks; only `make publish` rejects it. A successful `git pull --ff-only` alone does not exclude local commits ahead of origin. - do not run another full gate here: `make release` obtains exact-master CI evidence or runs the full local fallback after the packaging branch is ready If local `master` is ahead, beta preparation must stop until the user explicitly authorizes pushing `master` and the two refs match. Rely on release/publish scripts for their remaining source/ref/version checks instead of repeating them manually. 4. Choose the next prerelease version, usually `-beta.N`. 5. Create the packaging branch from the exact current `master` HEAD: - `git switch -c beta/` 6. Run or recommend: - `make release-dry-run VERSION=` - `make release VERSION=` only when the user asked to create local release state. - `make publish VERSION=` only when the user asked to publish and the publish preflight below passes. The release command uses the release-critical documentation gate. Full `docs:check` lifecycle/status findings remain a separate CI and maintenance signal and must not block beta or stable publication. ## Validation Reuse And Cost Use ordinary `make release VERSION=` once. It automatically tries to reuse the latest same-repository master push CI for the exact clean, synchronized source SHA. The current attempt must have passed the full `validate` job, including dependencies, Lint, Build, Test and Audit bundle; docs-only success, skipped steps, old SHA/run/attempt or incomplete API data cannot substitute. The script prints the accepted run URL/SHA or fallback reason. Reuse retains local diff, third-party notice and release-doc checks. Missing evidence, unsupported origin, missing `gh` or a bounded API timeout falls back to the existing local full gate. `RELEASE_LOCAL_CHECKS=1 make release VERSION=...` forces full local checks for diagnosis. Stable uses the same evidence rules; dry-run does not query CI or execute checks. Do not use `SKIP_CHECKS` as a substitute for this evidence check. Beta publication follows completed functionality acceptance on master. For normal generated packaging, tag CI independently reuses successful full master push CI for the exact release parent, with the same repository/current attempt and required full steps above. Normal master advances are allowed while that parent remains in master history. It installs dependencies, builds versioned assets, runs artifact tests, and retains metadata, notice, release-doc, bundle audit and asset checks; it does not repeat source lint/full Jest/coverage. Missing, invalid, failed, docs-only, incomplete or unavailable evidence falls back to the full gate; invalid source/packaging identity rejects publication. Stable also uses exact parent CI reuse under the release runbook. This replaces the earlier always-full beta tag rule. Reused CI does not prove this machine's node_modules or old dist is valid for deployment. Do not add another test/build before or after `make release`, or while waiting on tag CI, without changed inputs or a concrete failure. Normal beta packaging does not require redeployment or repeated functionality smoke. `scripts/release.mjs` enforces both the matching `beta/` name and the pre-release `HEAD == master` source invariant. ## Publish Preflight Use `make publish VERSION=` after accepted scope and validation. Trust its clean-worktree, branch, tag/HEAD, source-parent, version and packaging checks instead of manually repeating each SHA/ref/version query. `scripts/publish-release.mjs` queries live `origin/master`, then pushes the beta branch + tag atomically. If `master` advances normally after the live preflight, the workflow accepts the verified source parent as an ancestor; divergent/rewritten master history is rejected. Reuse a normal successful push receipt. Recheck remote refs only for an ambiguous result, concurrent change, or a next action that needs current remote state. Script/workflow live preflight remains required. ## Publish Verification After publish, verify the GitHub prerelease before claiming BRAT readiness: ```bash gh release view \ --json tagName,name,isDraft,isPrerelease,assets \ --jq '{tagName,name,isDraft,isPrerelease,assets:[.assets[].name]}' ``` Expected: - `tagName` and `name` equal ``. - `isPrerelease` is `true`. - `isDraft` is `false` and the tag workflow completed successfully. - Assets include `main.js`, `manifest.json`, `styles.css`, `LICENSE`, `NOTICE`, and `THIRD_PARTY_NOTICES.md`. - The released `manifest.json` asset has `version` equal to ``. Download only `manifest.json` for the default completion check. Download all assets for local hashes/JS syntax checks only when explicitly requested or a specific artifact/download failure needs diagnosis. Wait for download completion before inspecting the file. Asset verification is not BRAT/app/device smoke. Use workflow-step changes and blockers for progress updates. If the host requires periodic updates during an unchanged step, keep them short; do not launch redundant checks to fill the wait. Separate local preparation, remote tag gate and post-publish timing; polling/sleep overlaps the running gate and must not be added to its elapsed time. For release workflow failures, inspect GitHub Actions before giving testers the BRAT URL. ## BRAT Smoke Do not claim BRAT validation unless the plugin was installed or updated through BRAT from the published GitHub Release. Normal packaging beta reuses completed master functionality acceptance and verifies the Release/assets. Do not automatically deploy or repeat Obsidian, BRAT Chat/Memory/Pagelet, or mobile smoke. Trigger targeted install/app/device smoke only for installation or asset layout, plugin ID or platform changes; a concrete download/load/upgrade failure; or an explicit request. Choose BRAT install/update and enable/reload/Settings for installation changes, the affected action for a load/runtime issue, and mobile only for the affected platform or request. New runtime fixes return to master functionality acceptance before packaging. For app smoke, use `obsidian-test-vault-smoke`; for iOS, use `obsidian-ios-real-device-smoke`. ## Stable Graduation When beta blockers are closed: 1. Confirm every accepted beta fix is already on `master`; fixes may enter by PR or authorized direct commit, never only on a beta branch. 2. Verify `master` again. Do not merge beta release commits or prerelease metadata into it. 3. Cut the stable release directly from `master`: - `git switch master` - `git pull --ff-only` - `git branch --show-current` - `git status --short` - `make release-dry-run VERSION=` - `make release VERSION=` - `make publish VERSION=` only after explicit publish intent. Stable changelog generation ignores prerelease tags, so the stable release notes should cover the full range from the previous stable tag. ## Recovery - If a beta is bad, put the fix on `master` first. If no published tag exists, recreate the packaging branch from that updated `master` only with explicit authority to replace local release state. - If a beta is already published, publish the next beta tag such as `2.9.0-beta.3` from updated `master`; do not rewrite tags without explicit maintainer approval. - If `make release-dry-run` reports the current package version is untagged, stop and resolve the baseline tag before proceeding.