{
"id": "page:qa-01-versioning-and-delivery",
"_kind": "Page",
"_file": "wiki/qa/01-versioning-and-delivery.md",
"_cluster": "wiki",
"attributes": {
"title": "Versioning and Delivery",
"displayName": "Versioning and Delivery",
"slug": "qa/01-versioning-and-delivery",
"articlePath": "wiki/qa/01-versioning-and-delivery.md",
"article": "# Versioning and Delivery\n\n> Phase-5 deliverable. How the catalog schema is versioned, how downstream artifacts inherit that version, and how consumers pin.\n\n## Catalog schema versioning\n\nThe schema itself follows semver, governed by `graph/schema/versioning.md`. Every version is a `CatalogVersion` node in the graph (the meta-graph references itself).\n\n| Bump | Rule |\n|---|---|\n| **Major** | Removing a NodeKind / EdgeKind / required attribute, narrowing a type, narrowing an enum domain. Requires non-empty `breakingChanges` and a `MigrationSpec`. `supportedUntil` ≥ release + 180 days. |\n| **Minor** | Adding a NodeKind / EdgeKind / optional attribute, widening an enum domain. Backwards-compatible. |\n| **Patch** | Doc-only changes, prose clarifications, fixing typos in `displayName` defaults. No graph load semantics change. |\n\nSchema versions are tagged `catalog-vX.Y.Z` and published as a YAML bundle under `graph/schema/` releases.\n\n## Downstream artifact versioning\n\nEvery `DerivedArtifact` records `sourceGraphVersion` referencing the `CatalogVersion` it was produced against. This is more than housekeeping — it is the contract that lets downstream consumers reason about freshness.\n\n| Artifact | Version expression |\n|---|---|\n| Generated wiki site | `https://docs.../<catalog-semver>/...` (per-version archive). |\n| OpenAPI artifact | `info.version` = catalog semver; published as `openapi-<semver>.yaml`. |\n| TypeScript SDK | npm package `@a5c-ai/atlas@<semver>` whose major matches catalog major. |\n| Per-package READMEs | Front-matter `catalogVersion: X.Y.Z`. |\n| Stack diagrams | Filename suffix `-v<semver>.svg`. |\n| Glossary export | YAML/JSON dump named `glossary-<semver>.json`. |\n\n## Release pipeline\n\n1. **Pre-release CI** runs the full Phase-5 test pyramid against the candidate.\n2. **Adversarial review** (per [`process/00-process-design.md`](../process/00-process-design.md), Section 5) signs off.\n3. **Schema tag** `catalog-vX.Y.Z` lands on `main`. CI publishes the schema bundle.\n4. **Generator pass** runs against the tagged graph; produces the dated set of derived artifacts.\n5. **Downstream publish** in dependency order: SDK first (other consumers may depend on its types), then wiki, then OpenAPI, then per-package READMEs.\n6. **Release notes** are themselves derived from `CatalogVersion.releaseNotes` plus the diff of `addedNodeKinds` / `removedNodeKinds` / `breakingChanges`.\n\n## Consumer pinning\n\nConsumers (the babysitter SDK, dashboards, third-party tooling) pin to a catalog semver via the artifact most relevant to them:\n\n- **TypeScript consumers** pin via `npm` semver ranges on `@a5c-ai/atlas`.\n- **OpenAPI consumers** pin via the `openapi-<semver>.yaml` filename.\n- **Wiki consumers** pin via the `/<semver>/` URL prefix.\n\nA consumer using artifact at major version M is guaranteed:\n\n- Type-compatible reads against any minor/patch within M.\n- A migration path documented in the `M+1.0.0` `MigrationSpec` when M is sunset.\n- 180-day deprecation runway (`supportedUntil`) before previous-major artifacts go offline.\n\n## Yanking\n\nA bad release is yanked by:\n\n1. Bumping a patch (e.g. `X.Y.Z+1`) that reverts the offending change.\n2. Setting `supportedUntil` on the bad version to \"today\" — Phase-5 CI then refuses to serve it.\n3. Publishing a Level-1 `Gap` documenting the yank, its cause, and the fix.\n\nNo release is force-pushed, never amended; the audit trail is the lockstep of `CatalogVersion` nodes and their `supportedUntil` history.\n",
"documents": []
},
"outgoingEdges": [],
"incomingEdges": []
}