Standards Pack Upgrades (P2-25)¶
The org/team standards layer is pulled and pinned by cortexbuild standards
pull (see 07-ORG_ROLLOUT and the standards sync docs). This
page covers upgrading a pinned pack to a newer version safely and
reversibly.
Versioning¶
A pack declares a semantic version in <pack>/pack.yaml:
version: 2.1.0
The version is recorded next to the resolved SHA in the supply-chain lockfile
(.cortexbuild/standards/standards.lock.json, field pack_version). The
bump kind of an upgrade drives the trigger:
| Transition | Bump | Behaviour |
|---|---|---|
1.2.3 → 1.2.4 |
patch |
preview, auto-applyable |
1.2.3 → 1.3.0 |
minor |
preview, auto-applyable |
1.2.3 → 2.0.0 |
major |
breaking — requires --confirm to apply |
1.2.3 → 1.1.0 |
downgrade |
use standards downgrade (snapshot restore) |
A missing or non-semver pack.yaml version resolves to 0.0.0 (never raises).
Preview → Apply¶
# 1. Preview only (no mutation). Resolves the ref to an EXACT SHA.
cortexbuild standards upgrade v2.0.0 --source git@example.com:org/pack.git
# 2. Apply. Re-fetches and pins the previewed SHA.
cortexbuild standards upgrade v2.0.0 --source ... --apply --confirm
The preview reports the version transition, bump kind, added/removed rule ids, and any override conflicts (counts + ids only — no proprietary bodies leave the machine; the output is routed through the egress redactor and carries no wall-clock, so it is byte-stable).
Fail-closed pinning (S5)¶
preview resolves the target ref to a full SHA. apply re-fetches and
refuses to proceed if the ref now resolves to a different SHA than the one the
preview pinned (a moved or forged tag) — raising a supply-chain error. After
materialising the exact SHA, the pack content is re-hashed and verified against
the lockfile before the upgrade is considered done.
Override conflicts (B3)¶
Customer overrides live in .cortexbuild/rules/{foundational,adaptive}/. Before
an upgrade can clobber the org-side version of an overridden rule, the override
is classified against the new pack via the shared reconcile classifier. Any
conflicting-tier override is surfaced in the preview and blocks a silent
apply unless --confirm is passed. A major (breaking) bump always requires
--confirm as well.
Reversibility (B3)¶
Every --apply first writes an atomic pre-upgrade snapshot of the reversible
surface:
.cortexbuild/standards/(pack + lockfile, incl.pack_version).cortexbuild/ownership.json(the render ownership manifest).cortexbuild/rules/(customer overrides)
The snapshot is built in a temp sibling and atomically swapped into
.cortexbuild/standards-backups/<id>/, so a crash mid-snapshot can never leave a
half-written backup. To roll back:
cortexbuild standards downgrade --backup-id pre-1.0.0-to-2.0.0-<sha12>
downgrade restores the snapshot byte-identically (overrides, lockfile, and
ownership manifest) and re-renders all tool surfaces from the restored SSoT, so
the whole repo — not just .cortexbuild/ — returns to its pre-upgrade state with
no half-old / half-new surfaces.
Atomic apply (no half-migration)¶
If any step of an apply fails (e.g. post-upgrade content verification, or a migrator error), the engine restores the pre-upgrade snapshot before re-raising — the repo is never left half-old / half-new.
Migrations¶
Breaking pack changes can ship a reversible migrator registered against the exact version endpoints it bridges:
from cortexbuild_core.standards.migrate import register_migrator
@register_migrator("1.0.0", "2.0.0")
def _rename_rule(repo_root):
...
return ["renamed rule-foo -> rule-bar"]
run_migrations(repo_root, from_version, to_version) dispatches every registered
migrator whose endpoints fall within the upgrade span, in a deterministic order.
The default registry is empty (no pack migrations exist yet), so an upgrade runs
zero migrators — but the framework + dispatch are in place and tested.
Audit trail¶
Each applied upgrade and each downgrade appends an upgrade-kind event to the
append-only governance audit log (.cortexbuild/audit-log.yaml, see
07-ORG_ROLLOUT). The audit log is append-only and is
deliberately not rolled back by a downgrade — the record of what happened
survives the reversal.