# Release Sync

> Release sync — worker tags → Linear release waves

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

---


# Release sync — worker tags → Linear release waves

One **wave** = all `<worker>/vX.Y.Z` tags created on the same UTC day.
Each wave maps to one **Linear document** on team **iii** titled
`Release YYYY-MM-DD` — the combined release note, one `## <worker> vX.Y.Z`
section per worker — plus a child label `YYYY-MM-DD` under the team label
group **release**, applied to every shipped issue. (This is the free-plan
model; Linear's native Releases feature requires Business+.)

## Prerequisites

- Linear MCP tools (the claude.ai Linear connector).
- Team label group **release** on team iii (create once with
  `create_issue_label`, `isGroup: true`, if missing).

## 1. Collect pending tags

```bash
git fetch --tags origin
git for-each-ref 'refs/tags/*/v*' --sort=creatordate \
  --format='%(refname:short) %(creatordate:short)'
```

- Only consider tags that still exist on origin (`git ls-remote --tags
  origin` on doubt) — rolled-back local tags don't count.
- With arguments: sync exactly those tags.
- Without arguments: a tag is already synced iff it appears in the
  **header tag list of an existing wave document** (`list_documents`,
  query `Release`, team iii — each doc's first line lists its tags; that
  list is the idempotency record). Pending = every worker tag not found.
- Skip `-dry-run.` tags. Include prereleases (`-rc.N`, `-beta.N`) and label
  them in the note.

## 2. Group into waves

Group pending tags by tag creation date (UTC day). If more than 3 waves
would be written (typical of a first backfill), show the plan
(date → tags) and get user confirmation before writing anything.

## 3. Gather changes per tag

- Previous tag of the same worker:
  `git tag -l '<worker>/v*' --sort=-v:refname` → the entry after the
  current one.
- Commits: `git log --format='%h %s%n%b' <prev>..<tag> -- <worker>/`
  (first release of a worker: `git log <tag> -- <worker>/`).
- Extract `MOT-\d+` from subjects and bodies. For PR references `(#N)`
  with no MOT id, `gh pr view N --json title,body` and scan those too.
- Judgment attachments: if a change clearly implements a known issue that
  was never referenced, find it via `list_issues` (title terms, team iii)
  and read the issue to verify it matches before labeling. Never invent
  or guess identifiers; when unsure, leave it off and flag it in the
  report.

## 4. Write to Linear (per wave)

1. Label: child label `YYYY-MM-DD` under group **release** (team iii,
   `create_issue_label` with `parent: release`; skip if it exists).
2. Label every verified issue: read the issue's current labels first and
   pass the union to `save_issue` — never drop existing labels.
3. Worker labels: also apply flat `worker:<name>` team labels
   (`worker:shell`, `worker:console`, ...) matching the worker commit
   ranges that referenced the issue — create missing ones lazily; same
   union rule. Flat, NOT a label group: Linear group children are
   mutually exclusive, and one issue often spans several workers.
4. Document: `save_document` on team iii titled `Release YYYY-MM-DD`
   (update the existing one if present — look it up via `list_documents`).
   First line: the full tag list (idempotency record — always complete)
   and the wave label name. Body: a `## <worker> vX.Y.Z` section per tag
   (collapse multiple same-day tags of one worker into
   `## <worker> vA → vB`), 2–5 bullets each — what shipped, why it
   matters, breaking changes called out as **Breaking:**, shipped issues
   linked by URL. Plain changelog register; no internal workflow chatter.

## 5. Report

Table: wave date → document URL → tags → labeled issues. Flag tags where
no issues were found and any judgment attachments made.

## Rules

- Never change issue status, never create issues, never remove existing
  labels from an issue.
- Re-runs must converge: a late same-day tag merges into the existing
  wave document and the note is regenerated to include it.

