# Preship

> Run the full OpenPlayerJS verification gauntlet before committing, opening a PR, or preparing a release. Use when the user says "verify", "is this ready", "run the checks", "prepare the release", or when finishing any non-trivial change. Covers build, type-check, lint, tests+coverage, generated-file hygiene, downstream-consumer checks, e2e, and release dry-run.

- Skill: `openplayerjs/preship` (Agent Skill)
- Install (CLI): `npx skillmds@latest add openplayerjs/preship`
- Raw SKILL.md: https://api.skillmd.com/api/skills/openplayerjs/preship/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: openplayerjs (https://skillmd.com/u/openplayerjs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/openplayerjs/preship

---


# Preship — verification gauntlet

Run the applicable tier completely. Report every failure verbatim; never summarize a red
gate as "mostly passing." A tier is green only when every command in it exited 0.

## Tier 1 — every change (always run)

Run these from the repo root, in this order (order matters: build regenerates the types the
tests and dist checks depend on):

```sh
pnpm run type-check
pnpm run lint
pnpm run build
pnpm run test
```

Then verify hygiene:

1. **Coverage** — the `pnpm run test` summary must show ≥85% for branches, functions, lines,
   and statements globally. If a metric dropped below, add tests (see the `write-tests`
   skill); never lower a threshold or add a coverage exclusion — that is an ask-first change.
2. **No generated files in the diff** — `git status --porcelain` must show no changes under
   `dist/`, `coverage/`, `playwright-report/`, `test-results/`, or to `CHANGELOG.md`.
   `pnpm-lock.yaml` may change only if the task added/updated a dependency (which itself
   requires user approval).
3. **No new escape hatches** — on the changed files:
   ```sh
   git diff -U0 master... -- packages/ | grep -nE '^\+.*(as any|@ts-ignore|@ts-expect-error|eslint-disable)'
   ```
   Every hit must match a sanctioned pattern (opaque alias for untyped external libs;
   experimental browser APIs) and carry an inline justification comment. Anything else: fix
   with a typed alternative from CLAUDE.md R4.
4. **Core bundle isolation** — if the change touched core's public surface or any rollup
   config, confirm core is still external:
   ```sh
   grep -l "class EventBus" packages/{hls,ads,player,youtube}/dist/*.js
   ```
   Any hit means core got bundled into a consumer package — a build config regression.

## Tier 2 — core/player public types changed

Trigger: the diff touches any exported type, class signature, or `PlayerEventPayloadMap` in
`packages/core` or `packages/player`.

- Public-surface changes are breaking for downstream consumers that pin exact versions. If
  `.claude/CLAUDE.local.md` lists local consumer repos with verification steps, run them now.
  If a downstream check fails: **do not** edit that repo unless the task included it. Report
  the exact errors to the user and ask how to proceed (fix downstream vs revise the API here).
- Also confirm the API diff is intentional: after `pnpm run build`, run
  `git diff --stat -- '*/dist/types/*' 2>/dev/null || true` mentally against the task — every
  changed declaration file should map to something the task asked for.

## Tier 3 — user-visible behavior changed

Trigger: the change affects what plays, renders, or responds to input in a browser (UI
controls, engines, ads flow, autoplay, fullscreen).

```sh
pnpm run test:e2e
```

- E2E specs live in `e2e/*.spec.ts` and load pages from `examples/*.html`. If the change adds
  user-visible behavior with no covering spec, write one (pattern-match the closest existing
  spec, e.g. `e2e/src-switch.spec.ts`) and add/extend an example page.
- Playwright flakes: retry a failing spec once in isolation
  (`pnpm exec playwright test e2e/foo.spec.ts`) before treating it as a real failure; if it
  fails twice, it is real — report it.

## Tier 4 — release preparation (only when explicitly asked to prepare a release)

Pre-conditions: Tiers 1–3 green, working tree clean, on `master` (or the user named a branch).

```sh
pnpm run preflight
pnpm run release:dry-run
```

Review the dry-run output against these expectations and report discrepancies:
- **Core changed since last tag** → core releases first, then player/hls/ads/youtube ALL at
  the same version (lockstep). One version number across the family.
- **Core unchanged** → only packages with their own commits since their last per-package tag
  appear.
- Bump size matches the conventional commits since the last tag (`feat`→minor, `fix`→patch,
  breaking→major). If the user wants a different bump, the command is
  `release:minor`/`release:major` — never a hand-edited version field.

**Hard stop:** never run `pnpm run release` (or any non-`:dry-run` variant), `npm publish`,
or `git push` without the user explicitly instructing it in this session. Publishing is
irreversible. Present the dry-run summary and wait.

## Reporting format

End with a table: one row per gate actually run, columns = gate, command, result
(pass / fail + one-line reason). Below it, verbatim output for every failure, then the
single next action you recommend. If everything passed, say what tier was run and that the
change is ready for commit/PR/release respectively.

