# Extension Release Runbook

Last updated: 2026-07-06

Operational runbook for publishing extension artifacts from the public repo.

## Current source-backed extension reference

As of the 2026-07-06 release prep, `package.json`, `package-lock.json`, `package-lock.json#packages[""]`, `extension/manifest.json`, and `extension/package.json` are all aligned at `0.0.40`. `extension/manifest.json` is MV3, names the extension `OpenDevBrowser Relay`, and packages the background service worker at `dist/background.js`.

Use `npm run extension:sync` before release prep to write extension version metadata from the root package version. Use `npm run version:check` after sync to verify the root package, lockfile, manifest, and extension package agree.

## Distribution lanes

### Lane A (required): GitHub release artifact

Always produced from `.github/workflows/release-public.yml`:
- `opendevbrowser-extension.zip`
- `opendevbrowser-extension.zip.sha256`

This is the canonical extension release lane. The public release workflow also runs docs drift, Chrome Store compliance, best-practices skill assets, motion-design skill assets, lint, typecheck, tests, build, generated help, and extension build before packing the zip.

### Lane B (optional): Chrome Web Store publish

Manual-gated workflow:
- `.github/workflows/chrome-store-publish.yml`
- script: `scripts/chrome-store-publish.mjs`

Use this lane when store publication is enabled for the release.

## Required secrets (Lane B)

Configure in public GitHub repo secrets:
- `CWS_CLIENT_ID`
- `CWS_CLIENT_SECRET`
- `CWS_REFRESH_TOKEN`
- `CWS_EXTENSION_ID`

## Preflight checklist

- [ ] `package.json` version equals intended release version.
- [ ] `npm run extension:sync` keeps `extension/manifest.json` and `extension/package.json` aligned with the root package version.
- [ ] `npm run build` passes so the local relay CLI is available for the live screenshot capture flow.
- [ ] `npm run extension:build` passes.
- [ ] Start the local relay in a separate terminal with `npx opendevbrowser serve`.
- [ ] `node scripts/generate-store-assets.mjs` refreshes `extension/store-assets/` from the current icon set plus live popup and `canvas.html` captures.
- [ ] Verify the generated store assets and listing copy still reflect the shipped popup plus `canvas.html` surfaces, including token authoring, lease-aware history, and annotation flows when those screens are part of the release capture set, while keeping the extension in the relay-backed browser lane: local browser replay participation is allowed, public read-only desktop observation remains separate core runtime behavior, and neither the extension nor the optional helper is described as a desktop agent.
- [ ] Review `extension/store-assets/LISTING.md` for current homepage, privacy URL, upload copy, and permission/privacy answers.
- [ ] `node scripts/chrome-store-compliance-check.mjs` passes.
- [ ] `npm run extension:pack` creates `opendevbrowser-extension.zip` from `manifest.json`, `popup.html`, `canvas.html`, `dist/`, and `icons/`.
- [ ] `npm run version:check` passes.

## Lane A execution

1. Run tag-driven public release flow (`docs/RELEASE_RUNBOOK.md`).
2. Confirm the release workflow completed the registry-consumer smoke lane for the published npm package before treating the extension artifact as fully released.
3. Confirm GitHub release includes extension zip + checksum.
4. Confirm the active release evidence ledger, currently `docs/RELEASE_0.0.40_EVIDENCE.md` for package version `0.0.40`, records whether external release workflow evidence is complete or deferred.
5. Verify checksum locally if required:

```bash
shasum -a 256 opendevbrowser-extension.zip
```

## Lane B execution (workflow)

Trigger workflow dispatch for `Chrome Store Publish` with:
- `release_ref`: tag or commit to publish
- `release_tag`: `vX.Y.Z`
- `publish`: `false` for upload-only validation, `true` for live publish
- `publish_target`: `default` or `trustedTesters`

Workflow behavior:
- validates tag format and version match
- builds extension artifact
- uploads zip to Chrome Web Store
- optionally publishes to selected target

## Lane B execution (local/manual)

```bash
npm run build
npm run extension:build
npx opendevbrowser serve
node scripts/generate-store-assets.mjs
npm run extension:pack
npm run extension:store -- --zip opendevbrowser-extension.zip --publish-target default --publish
```

For upload-only dry run, omit `--publish`.

## Post-publish validation

- [ ] Store dashboard shows expected version.
- [ ] Release notes include store publication status and version.
- [ ] GitHub release tag and extension manifest versions match store version.

## Failure handling

### Upload fails

- verify OAuth credentials and extension ID
- retry upload-only path first (`publish=false`)

### Publish fails after upload

- validate listing readiness in store dashboard
- retry publish with `publish_target=trustedTesters` to isolate policy/review issues

### Version drift detected

- stop publication
- rebuild from correct release tag
- republish aligned version only

## Rollback controls

If a bad extension release is published:
- move users to previous stable release via store controls (if available)
- publish hotfix version from corrected tag
- update incident notes in release documentation

## Evidence to retain

- workflow run URL(s)
- registry-consumer smoke JSON or run-log excerpt proving the published npm package passed fresh install validation for the same release
- listing-copy snapshot or generated-asset review note confirming the release-facing browser replay, desktop observation, and browser-scoped computer-use boundary wording used for the release
- upload/publish JSON output summary
- store listing URL and visible version
- checksum artifact from GitHub release
