Releases
Start with the public release hub, then drill into the current v0.2.0 preview, the canonical v0.1.0 archive, unreleased proof, changelog, and upgrade policy.
Source of truth
AppSurface now treats release notes as a product surface instead of a post-ship afterthought. This folder is the public record that answers three questions quickly:
- What is changing next?
- How risky is it to adopt?
- Where will the final tagged story live once a version ships?
It also acts as a concrete AppSurface Docs example for teams that want stronger release notes in their own products.
Start here
- Package chooser is the fastest install map for deciding which AppSurface package to add first.
- Current coordinated release is the package-facing story for the coordinated AppSurface prerelease in this documentation tree.
- v0.1.0 is the canonical archive for the first coordinated stable AppSurface release.
- The
v0.1.0release-candidate routes redirect to v0.1.0, where the RC dates are recorded. - Unreleased is the living proof artifact for the next coordinated AppSurface version: the current merged-work ledger, not the final tagged narrative.
- Changelog is the compact ledger that points to unreleased and tagged stories.
- Pre-1.0 upgrade policy explains the stability contract before
v1.0.0. - Release authoring checklist is the maintainer workflow for turning the unreleased page into a tagged release.
- Coordinated release links explains when package rows use the frozen tree-local current pointer, an explicit historical note, a held release, or a proof-host note.
- The Durable discovery and reconciliation guide explains the public-preview release gate, schema ownership, and explicit worker-host boundary.
Older preview routes redirect to their canonical release notes so each release line has one live package-facing story.
Official release artifacts
Each generated tagged release owns four immutable versioned artifacts, one overwriteable tree-local pointer, and one permanent tree-local metadata sidecar:
releases/v{version}.md: the human release narrative.releases/v{version}.md.yml: AppSurface Docs metadata for the release note.releases/v{version}.release.json: machine-readable release metadata and generated file list.releases/v{version}.evidence.json: generated release evidence bundle proving repository release-artifact consistency.releases/current.md: generated frozen pointer from coordinated package links to this release note in the documentation tree that contains it.releases/current.md.yml: permanent, version-independent AppSurface Docs metadata for the frozen pointer. Release preparation preserves it and includes it in V2 evidence rather than regenerating it.
The release evidence bundle is not a signature or hosted-build attestation. It is the reviewable consistency proof used by release-prep and publish validation.
Durable public-preview release gate
The Durable packages are eligible for coordinated prerelease publication only when release review confirms schema
ownership, migrations 0001 through 0009, the canonical PostgreSQL role recipe, registry-scoped Work discovery,
the drain-first 0009 role transition, passive storage registration, explicit AddWorkerHost() hosting, startup
schema/epoch validation without DDL, recovery procedures, and the real PostgreSQL conformance evidence. The package
chooser is the machine-facing install map; the Durable discovery guide
is the reader-facing operational boundary. The durable schema commands do not replace this release review: scripts
are offline, status and preflight resolve a named connection environment variable, and apply requires a named
migration-owner environment variable. No command accepts or prints connection strings; the least-privilege role
guidance still applies to each online operation. The example is local proof rather than production operations guidance.
Release format
Story first
Each release note should open with the narrative that matters to evaluators and adopters. Explain what changed, why it matters, and which parts of the product surface are affected before dropping into mechanical lists.
Consumer path next
Each major item should answer the reader's next question without making them inspect the repository:
- Who should care?
- What can they now do?
- Which package, guide, example, or CLI command should they start with?
- What boundary or pitfall should they know before adopting it?
Use internal feature names only after the reader-facing behavior is clear. For example, introduce RazorWire auth projection as rendering allowed, forbidden, and anonymous UI from host-owned ASP.NET Core policies before relying on the phrase "passive auth projection." When a change ships with a guide or example, link that path from the release note next to the feature summary.
Release notes should also connect related concepts instead of only naming them. If an item mentions a package, guide, example, workflow, policy, diagnostic family, CLI command, or cross-package concept, link the first meaningful mention to the canonical page a consumer should read next. Prefer durable start-here links, package READMEs, guides, examples, and public docs routes over transient PRs or maintainer-only notes. Consumer projects that have concurrent release-note authors can use appsurface release compose instead of making every change edit one shared changelog.
Safety second
Every release note should make upgrade risk obvious near the top. Call out whether the note is unreleased or tagged, which surfaces are affected, how fresh the information is, and where migration guidance lives.
Archive third
Once AppSurface starts cutting tags, the long-form release note will live in this folder and the compact summary will live in CHANGELOG.md. Tagged notes become the durable archive for migration details and release narrative.
Append-only unreleased entries
The checked-in unreleased.md page is a stable release-note template. Feature pull requests add one Markdown file to releases/unreleased.entries/ instead of editing that shared page, so independently merged work does not repeatedly contend for the same line range. Name each file YYYY-MM-DD-topic.md, begin it with one exact directive, and put its consumer-facing Markdown below the directive:
<!-- appsurface:unreleased-entry section="included" -->
### Package and docs surface
- Describe the consumer outcome, link the package or guide, and state an important boundary.
The supported sections are taking-shape, included, and migration-watch. Entries are filename-sorted and inserted at the bottom of that section, after its placeholder bullet. Do not add a # or ## heading inside an entry because it would create a competing top-level section; ### headings are appropriate for grouping related items. Relative inline and reference link destinations are authored relative to the entry file, then rebased for unreleased.md and the tagged release note; external, rooted, query-only, fragment-only, and code-example content stays unchanged. Release preparation composes the page into the tagged release note, records the exact archived paths in its evidence-digested release manifest, then removes only those entries. A concurrently merged new entry therefore remains in the next cycle rather than being silently folded into, or lost during, the release reset.
What belongs in the release surface
- Package behavior changes
- CLI behavior changes
- Docs-facing behavior changes that affect adopters or evaluators
- Example changes that alter the recommended path
- Release policy changes
What does not belong in public release notes
Private maintainer-only recovery steps, secret handling, and operational escape hatches should live outside harvested docs. In this repository, those notes belong under .github/.