Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · Versioning
page:docs-versioninga5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
II.
Page JSON

page:docs-versioning

Structured · live

Versioning json

Inspect the normalized record payload exactly as the atlas UI reads it.

File · wiki/docs/versioning.mdCluster · wiki
Record JSON
{
  "id": "page:docs-versioning",
  "_kind": "Page",
  "_file": "wiki/docs/versioning.md",
  "_cluster": "wiki",
  "attributes": {
    "nodeKind": "Page",
    "sourcePath": "docs/VERSIONING.md",
    "sourceKind": "repo-docs",
    "title": "Versioning",
    "displayName": "Versioning",
    "slug": "docs/versioning",
    "articlePath": "wiki/docs/VERSIONING.md",
    "article": "\n# Versioning\n\n**Posture (spec 40 §2.2, WP-PKG-02): semver encodes the release train; within a\ntrain every package is exact-pinned lockstep; majors mark breaking trains.**\n\nThis page is the one place that states how versions are chosen in this\nrepository. There is exactly one mechanism — `scripts/release-version.cjs`, the\nsingle resolver — and nothing else assigns, bumps or infers a version.\n\n## 1. The lockstep train\n\n- All 43 publishable `@fabricstack/*` packages (inventory derived at run time by\n  `scripts/lib/publishable-packages.cjs`, never hand-maintained) plus the root\n  manifest, the private workspace members in the private scope and the plugin\n  manifests (`plugins/*/plugin.json`, `versions.json`) carry **one** version:\n  the train version. Today that is `7.0.0`.\n- Every **internal dependency** — any dependency whose name is in the\n  publishable inventory or the workspace set — is pinned to that exact version.\n  `*`, `latest`, `workspace:*`, `^`/`~` and comparator ranges are forbidden on\n  internal edges (external dependencies keep whatever ranges they need).\n- A consumer therefore installs a whole train: `@fabricstack/orchestrator@7.0.0`\n  resolves to `@fabricstack/orchestrator-sdk@7.0.0`, which resolves to\n  `@fabricstack/harness-sdk@7.0.0`, and so on. Mixed trains cannot be assembled\n  by accident, which is the property that makes a private product with a\n  handful of whole-train consumers (the platform itself, the Form 1 archives,\n  enterprise installs via dist-tags) supportable.\n\n## 2. The single resolver\n\n`scripts/release-version.cjs` (library: `scripts/lib/release-version.cjs`,\ntests: `scripts/__tests__/release-version.test.mjs`,\n`scripts/__tests__/verify-manifests.test.mjs`) is the only place the released\nversion is decided (FIX-001, `docs/release-incident-2026-08-13.md`):\n\n| Command | Role |\n| --- | --- |\n| `resolve --branch <b> --sha <short-sha>` | Produces THE release identity once: `main` releases the root version `X.Y.Z`; `staging` / `develop` release `X.Y.(Z+1)-<branch>.<sha>` on their own channels. Any other branch is a hard error. |\n| `verify --branch --sha --version` | Validates an explicitly passed version against the resolver instead of re-reading manifests. |\n| `sync-workspace-versions.mjs --version <v>` | Writes the resolved version into every synchronized manifest and every internal dependency pin (publication workspace only). |\n| `verify-manifests --version <v>` | Proves the tree IS at `<v>`: every synchronized version, every internal pin, and — since WP-PKG-02 — that no internal dependency carries a wildcard, dist-tag, `workspace:` protocol or range. Failures are reported as `<manifest>:<line>`. Runs on every PR (`ci.yml`, publish-isolation job) and before every publication. |\n| `assert-channel-tags`, `ensure-tag`, `tag-source`, `from-tag` | Channel promotion and tag provenance; read-only against the registry except `npm view`. |\n\nThe tree is committed **at** the train version. Nobody edits a `version` field\nby hand and nobody adds a per-package bump: a train moves when the resolver says\nso, and `verify-manifests` refuses a tree that disagrees with itself.\n\n## 3. Breaking changes: D10 at train level\n\nIntent decision D10 (`docs/specs/platform-gaps/00-intent.md`): *break freely,\nmajor bump; no compatibility shims; in-repo consumers migrated in the same\neffort.* Under the lockstep posture that rule is expressed **once per train**,\nnot per package:\n\n- A train that contains any breaking change to any published surface bumps the\n  train **major**. Minor and patch trains carry only additive or corrective\n  changes across the whole set.\n- Because every package shares the number, a consumer reads the major as \"this\n  train broke something somewhere\" and runs the migration for the train — there\n  is no per-package matrix to reconcile.\n- The compatibility obligation is satisfied inside the repository: the same\n  change that breaks an API migrates every in-repo consumer, and the exact pins\n  guarantee no stale package can observe the old surface.\n\n### How 7.0.0 was chosen\n\nThe public train (`a5c-ai/babysitter`, `@a5c-ai/*`) is at lockstep `6.0.x`. The\nRN-1 cutover (spec 15) renames every package into the private `@fabricstack/*`\nscope, retires duplicate bins, and (spec 40 §2.1) lands `exports` maps that make\ndeep imports of `dist/` unreachable. Each of those is a breaking change for\nevery consumer, so by the rule above the first private train is a **major**\nbump over the last public one: `6.0.x → 7.0.0`. It is `7.0.0` rather than any\nother number because the private train continues the public lineage (a\nconsumer migrating from `@a5c-ai/babysitter-sdk@6.0.x` to\n`@fabricstack/orchestrator-sdk@7.0.0` sees the expected ordering) while making\nit impossible to confuse the two trains. Subsequent breaking trains bump to\n`8.0.0`, `9.0.0`, … ; non-breaking trains move the minor or patch.\n\n## 4. Changesets: removed, and why\n\nThe repository once carried the changesets tool (`.changeset/config.json`, a\n`fixed` group for the adapters packages, and one stranded changeset file).\nResearch for spec 40 (`docs/specs/platform-gaps/research/packaging-state.md`\n§1.1) found it referenced by **no workflow**: contributors were occasionally\ntold to \"add a changeset\", but nothing ever consumed the files. Spec input 3\nof that research required *wire-or-remove*. WP-PKG-02 removed it:\n\n- `.changeset/` is deleted (config, the stranded changeset, and the\n  agent-mux-era config/README copies).\n- No workflow, script or root/package manifest references the tool; the\n  contributor-facing instructions in `packages/adapters/**` (PR template, the\n  historical CONTRIBUTING, the `integrate-harness` process and skill) now say\n  the opposite: do not bump versions.\n- The repository therefore carries **one** versioning mechanism, the resolver,\n  and one exact-pin rule enforced by `verify-manifests`.\n\n### Alternative considered and rejected: per-package semver via changesets\n\nWiring changesets (each PR declares a per-package bump; a \"Version Packages\"\nPR aggregates them; internal dependencies float on `^` ranges so packages can\nrelease independently) was the other coherent half of wire-or-remove. It was\nrejected because:\n\n1. **Nobody resolves against per-package signals.** Consumers of a private\n   product take whole trains via dist-tags; 43 independently versioned\n   manifests would decorate the registry with information no consumer uses.\n2. **Independent versions require floating internal ranges.** Per-package\n   releases only work if `@fabricstack/orchestrator-sdk` may depend on\n   `^7.0.0` of `@fabricstack/harness-sdk`; that reintroduces the mixed-train\n   installs and the \"which version is actually running\" ambiguity the\n   incident-hardened lockstep scheme exists to prevent (`docs/release-incident-2026-08-13.md`).\n3. **Two mechanisms, one truth.** Changesets would compute versions in a\n   second place, exactly the \"several places each infer the released version\"\n   failure mode FIX-001 closed. The single resolver is never bypassed.\n4. **D10 is simpler at train level.** One major per breaking train is a\n   clearer contract for a whole-train consumer than a per-package matrix of\n   majors that all ship together anyway.\n\nThe rejected alternative remains a valid design for a public, ecosystem-facing\npackage set; it is the wrong fit for a private platform consumed as a unit.\n\n## 5. Rules for contributors\n\n- Never edit a `version` field or an internal dependency pin by hand.\n- When adding an internal dependency, pin it to the current train version\n  exactly (copy the root `package.json` `version`); `npm run test:verify-manifests`\n  and `node scripts/release-version.cjs verify-manifests --version <train>` must\n  stay green.\n- A change that breaks a published surface is fine (D10) — note it in the PR so\n  the next train is cut as a major; migrate every in-repo consumer in the same PR.\n- Release mechanics (tags `fabric/<branch>/v<version>`, Artifact Registry\n  publication, channel promotion) are described in `docs/release-pipeline.md`;\n  the operator procedures — normal train, dry-run rehearsal, half-published-train\n  recovery from the immutable tag, dist-tag repair, public-namespace checks — are\n  in [docs/RELEASE-RUNBOOK.md](RELEASE-RUNBOOK.md). Both consume the resolver's\n  output and never re-derive it.\n",
    "documents": []
  },
  "outgoingEdges": [],
  "incomingEdges": [
    {
      "from": "page:docs",
      "to": "page:docs-versioning",
      "kind": "contains_page"
    }
  ]
}

Shortcuts

Back to overview
Open graph tab