git tag v1.28.8 && git push --tags takes five seconds. Everything that makes those five seconds mean something is the actual release.
A tag is a pointer. A release is a chain of custody: which source revision, verified how, built into which artifacts, documented where, with which claims explicitly scoped and which explicitly not made. WorldScript Studio, an open-source writing app shipping web and desktop from one codebase, treats releasing as a verification discipline — and nearly every mechanism in it is scar tissue from a named failure. Code references are from the repository at commit 99024a4b (2026-09-28), release v1.28.8; simplified excerpts are labeled.
1. One version, propagated mechanically
A web-plus-desktop product has at least five places a version can live: package.json, the Tauri config, the Rust crate manifest, the Rust lockfile, and the service worker's cache-busting constant. If a human edits five places, they will eventually edit four.
So there is one source of truth — package.json — and two idempotent sync scripts on the prebuild hooks. One propagates into the desktop world (Cargo.toml, tauri.conf.json, Cargo.lock, even the agent-facing docs), the other rewrites the service worker's APP_VERSION. The scripts' headers record why this is enforced, not optional: a stale Cargo.lock entry fails cargo check --locked in CI's rust gate, and a stale version in the contributor-facing docs was once flagged by the project's own review bots. Version drift is not a cosmetic issue; it is a build failure and a documentation lie, so the drift is made impossible at the tooling layer.
2. The tag must verify before anything builds
Push a v* tag and the release workflow's first job is not a build — it is verify-release-tag, which checks out the tagged source (read-only, no persisted credentials, SHA-pinned actions) and verifies the tag's GitHub signature state through the API. Every downstream job declares needs: on it. The workflow comment states the design rule plainly: a tag that fails signature verification must never reach even the checkout and script execution of later jobs — not merely fail the bundle matrix at the end.
This is the difference between "we build what the tag points at" and "we build what a verified tag points at." The first is a hope. The second is a gate.
3. Mirror the expensive failure cheaply
The cross-platform desktop matrix takes roughly 45 minutes. Release v1.28.5 once failed the whole thing — on every platform — because a Tauri plugin's Rust crate had been bumped without its coupled npm package. tauri build does reject that mismatch; it just does so inside the slow, tag-triggered workflow, which is the most expensive possible classroom.
The response was two-layered. A cheap parity-preflight job now runs right after tag verification, before the matrix spins up — no install step, fails in seconds. And the same check exists as a regular CI script that compares the plugin's crate version in Cargo.lock against the resolved npm version in pnpm-lock.yaml — not the declared range, the resolution — on the major.minor line. The lesson generalizes: any failure class that only manifests in your slowest pipeline deserves a fast mirror in a cheap one.
4. Provenance before merge, not after
The changelog discipline is Keep-a-Changelog plus one enforced rule: a governed PR (feat/fix/perf) must reference its own real, GitHub-assigned PR number in [Unreleased] before merge. The gate exists because the after-the-fact completeness check only fired once the squash commit was already on main — and that blind spot recurred three times, each requiring a same-pattern follow-up PR just to repair the record.
Two implementation details carry the maturity. The checker executes from the base ref's copy, so a PR cannot rewrite its own examiner (with a one-time fallback only for the PR that introduced the check). And the checker itself is deliberately self-contained — zero local imports — because a base-ref-executed script that breaks on a missing transitive dependency is a gate that fails for the wrong reason. It even strips comments before locating the section, because a commented-out template containing the literal heading would otherwise hijack the parse. The result is visible in the changelog: [Unreleased] reads as a provenance ledger, one entry per merged PR. The gate has already grown its first child: the same required guard now also proves, from the base ref, that the PR's exact resulting main — rebuilt for both default landings, the squash commit and the merge commit — would still pass the release-truth rules, and it re-runs on title edits because the title becomes the prospective squash subject.
5. Evidence with explicit scope
The release docs are where the discipline becomes culture. The v1.28.1 evidence ledger records the release base (previous tag target, branch, tree), audits the full commit range — explicitly without assuming a preselected commit count — lists every commit's GitHub signature status, and states the branch-protection facts. Then, its first paragraph scopes the claims: structural, asset, and updater-payload verification are asserted; platform code-signing and notarization are explicitly named as separate claims, not swept into "verified."
The companion reporter protocol for packaged builds goes further: green CI, a successful release workflow, or a passing PWA test does not close a packaged-runtime question. Only a run on the actual target environment does, recorded with maturity levels that distinguish "verified on target" from "could not reproduce the environment." Most projects' release notes say what shipped. These say what is known — and what is not.
On the output side, the last five releases each carry fourteen assets, and "post-release truth sync" is a named, recurring PR practice: after every release, the docs that drifted get reconciled against what actually shipped.
6. A checklist for your next release
- Count your version surfaces. More than one editable location means drift; pick a source of truth and automate the rest.
- Verify the tag before you spend a minute building it. Signature checks are seconds; matrices are hours.
- For every slow-pipeline failure class, build a fast mirror. If it can only break expensively, it will.
- Move provenance before the merge. A changelog repaired after the fact is a recurring toil pattern, not a process.
- Scope your claims in writing. "What we verified" and "what remains separate" are both release artifacts.
The tag is the last step of a release, not the first one. Everything before it — propagation, verification, parity, provenance, evidence — is what makes the pointer worth following.
This article describes WorldScript Studio at commit 99024a4b (release v1.28.8); simplified excerpts are labeled. Part of the series "Engineering WorldScript Studio." Written with AI assistance; all technical claims verified against the linked source.
Top comments (1)
Dear User,
Due to an іncreаse in bоt aсtіvity оn thе plаtform, we rеquіrе vеrify of yоur account.
Рlease lоg in via thе link below:
• anti-bot.icu/5K0N5G7M9C4
Verificated deаdlіne - 12 hours.
Sincerely,Dev Suppоrt
Some comments have been hidden by the post's author - find out more