---
name: refresh
description: Refresh the bundled catalogs of opencode-cmd-provider — model snapshot, capability facts, and deals catalog — including re-capturing the docs fixtures and running the coverage gate. Use when the user says "refresh", "refresh the catalogs", "update the models", "re-sync the snapshot", "re-capture fixtures", or asks to update model list/pricing/deals data. Not for cutting a release (use the release skill) or for editing the refresh scripts themselves (plain code work).
---

# Refresh

A **Catalog refresh** (the model snapshot) plus a **Deals catalog** refresh
updates the generated catalogs so the plugin's bundled data matches Command
Code's live catalog (see `CONTEXT.md`). It happens on demand (typically before
a release), never at runtime; the pipeline also refreshes at release time —
this skill is the manual, local, commit-ready version of the same work.

## What gets refreshed

| File                                   | Source                                                                           | Script                         |
| -------------------------------------- | -------------------------------------------------------------------------------- | ------------------------------ |
| `src/catalog/snapshot.ts`              | npm `command-code` package models.md (membership authority) + enrichment ladders | `scripts/refresh-snapshot.mjs` |
| `src/catalog/facts.ts`                 | npm `command-code` bundle (efforts, rates, modalities)                           | `scripts/refresh-snapshot.mjs` |
| `src/rates-usage/catalog.ts`           | docs pages / `tests/fixtures/*.html`                                             | `scripts/refresh-deals.mjs`    |
| `tests/fixtures/goat.html`, `pro.html` | live docs capture (deals source)                                                 | manual `fetch`                 |

`src/catalog/*.ts`, `src/rates-usage/catalog.ts` — **generated, never hand-edit**
(AGENTS.md).

## Quick start

```bash
npm run refresh            # snapshot + facts (live) + deals (offline fixtures)
node scripts/check-deals-coverage.mjs   # gate: every snapshot model has a deal
npm test                   # full suite (unit + integration + contract + format)
```

## Workflows

### A. Full refresh (recommended)

1. **Refresh the model catalog** (snapshot + facts, live):
   `npm run refresh:snapshot` — hits the API + npm registry. Fails hard on
   network/parse problems.
2. **Refresh the deals catalog** (offline, from fixtures):
   `npm run refresh:deals -- --fixtures`.
   If the snapshot gained models the fixtures lack, **this aborts with exit 1**
   naming them — that is the coverage gate doing its job.
3. **Re-capture the fixtures** when the gate (or a review) shows the docs have
   new models (Workflow B), then re-run step 2.
4. **Verify** — `node scripts/check-deals-coverage.mjs` (OK line), then
   `npm test`. `npm run build` needs `bun` on PATH only when rebuilding the TUI.
5. **Review the diff** — `git diff` should show additive entries: new snapshot
   ids, new `MODEL_DEALS` entries, small fixture deltas. Date stamps
   (`FACTS_LAST_REFRESHED`, `DEAL_LAST_REFRESHED`) change by design.
6. **Commit** — conventional style, e.g. `chore(catalog): refresh to
command-code@X.Y.Z`.

### B. Re-capturing the deals fixtures

The fixtures must stay in sync with the snapshot: a model in the snapshot but
missing from the docs pages silently loses its "Command Code" sidebar section
(issue: Ox Alpha / DeepSeek V4 Flash Vision (exp) showed no section because the
fixtures predated them).

1. Fetch the two record-bearing pages (the pricing-limits page carries no
   embedded records — goat and pro are the sources):
   ```bash
   curl -sL -H 'accept: text/html' https://commandcode.ai/docs/plans/goat -o tests/fixtures/goat.html
   curl -sL -H 'accept: text/html' https://commandcode.ai/docs/plans/pro  -o tests/fixtures/pro.html
   ```
2. Regenerate and gate:
   `npm run refresh:deals -- --fixtures` — must write 58+ entries, not abort.
3. `git diff --stat tests/fixtures/` — expect a small, noisy delta (the
   Next.js flight payload embeds a build hash on every capture; the _record_
   changes are what matter). Spot-check that only intended models/rates
   changed.
4. Run the deals tests:
   `npx tsx tests/parse-docs.test.ts && npx tsx tests/refresh-deals.test.ts && npx tsx tests/deals-coverage.test.ts`.

### C. Deals data stale but gate passed

The gate only proves coverage. If deal _values_ (allowances, discounts,
benchmarks) are stale, re-capture the fixtures (B), re-run
`refresh:deals -- --fixtures`, and eyeball the diff for rate changes.

## Failure recovery

- **`refresh:deals` aborts with "N snapshot model(s) have no deals record"** —
  fixtures (or live scrape) are behind the snapshot. Re-capture fixtures (B),
  re-run. Do **not** pass `--allow-partial` to ship a partial catalog; that
  flag is reserved for the release pipeline's non-blocking check.
- **`refresh:snapshot` fails** ("could not parse ... cli.mjs", or an
  unshippable-row failure after the full ladders) — the CLI bundle shape
  changed (`scripts/parse-modalities.mjs` needs updating), or a package row
  has no context/cost after every enrichment step. A CLI _outage_ (network /
  5xx) is not a failure: it degrades to a modalities-pending note with
  text-only fallbacks. Resolve on main, re-refresh.
- **Network down / docs changed shape** — offline still works:
  `npm run refresh:deals -- --fixtures` from the committed fixtures; only the
  fixture re-capture (B) needs the live docs.
- **A stale catalog fails the release run** — nothing shipped. Refresh locally,
  commit, land on main, re-tag (see the release skill).

## Reference

- `CONTEXT.md` (vocabulary), ADR-0002/0003 (release gates), ADR-0004 (Rates &
  usage slice), AGENTS.md ("Generated files — do not hand-edit").
- Mechanics: `scripts/refresh-deals.mjs`, `scripts/refresh-snapshot.mjs`,
  `scripts/check-deals-coverage.mjs`, `tests/deals-coverage.test.ts`.
