Skip to content
GitHub
Operations

Version Publication

Operator-driven world-model version-publication workflow: bundle accumulated enshrined rules, mint a per-action action module for each registered action into the module store, auto-generate the World Model Card, and coordinate publication. The world-model version is the unit of authority (per ADR-026); publication is how a version becomes authoritative for live decisions.


  • Version bundling — collect enshrined rules since the last published version into a publication draft, alongside any configuration-block changes or action-registry changes staged for the version
  • Action module minting — for each registered action, mint a deployable module bundle per ADR-080 D1: composition root + embedded context-schema subset + rule files + manifest (module version, world-model version, code provenance, embedded schema digest, content hash). Modules are written to the content-addressed module store keyed by (org, domain, action, world_model_version).
  • World Model Card auto-generation — published version emits worldmodel.version.published; the auto-generation pipeline reacts to the event and produces the card from rule corpus + provenance + configuration snapshot + coverage metrics per ADR-082 D2.
  • Publication coordination — operator review of the draft, final sign-off, release flow
  • The world-model version is the unit of authority per ADR-026. A published version is authoritative for that version; prior versions are not retroactively invalidated by subsequent corrections.
  • Vocabulary reconciliation and behavioral completeness are hard publish gates; ontology drift is a hard deploy gate per ADR-108 D5 + ADR-107 D5. Publish runs a vocabulary-reconciliation phase before the deterministic mint: holistically per declared action over its assigned enshrined rules, it converges divergent input names onto the action’s canonical input ontology — two rules naming one real quantity differently resolve to a single canonical input — then re-runs each realigned rule’s behavioral suite (the consistency gate). Publication then fails (422) unless every enshrined rule is behaviorally complete — its independently-extracted spec is internally consistent, passes, and has no dead input. At deploy, the action’s input_schema.json is sourced from the persisted ontology; the rules’ union is a deterministic drift check only (deploy aborts 422 if the union diverges from the ontology), never a fallback source. The materialized behavioral suite ships in the content-addressed bundle, and a deploy-time backstop re-runs it against the deployed predicate, so the check is carried in the immutable artifact, not asserted only at publish. Remediation is two-tier and the operator never edits code: mechanical failures (AST safety, declared == read, dead input) auto-repair in the codegen loop; semantic failures (the natural-language rule and its intended behavior disagree, the text is ambiguous, or a vocabulary harmonization is low-confidence / would rewrite a published input) route to the operator — natural-language chat-steering for the rule, and at publish a surfaced rename preview the operator arbitrates before it is applied. The guarantee is internal completeness and consistency, not real-world truth.
  • Module integrity is verified at load time per ADR-080 D2 + D3: the decision-server checks the content hash and the operator-approval marker before caching and executing the module.
  • Version is metadata across the context boundary per ADR-030. Downstream consumers (System Card, audit paths) read the version field on the response payload; the platform does not unwrap it as a partition boundary or as a synchronization signal. See Version Attribution.
  • World Model Card linkage flows via event-driven projection per ADR-065 D4 — worlds publishes world_model_card_published; the platform-side System Card pipeline projects the relevant fields into a platform-local snapshot for offline-renderable card embedding. See system-card for the full pattern.
  • Publication is operator-triggered, not enshrinement-triggered. Rules enshrine one at a time through the reviewer surface and accumulate in the world-model’s working state; an operator decides when to cut a new version per evolution-loop / Versioning and Release.
  • Concurrent operator actions on the same publication are serialized at the row level — one wins; the other receives a clean conflict response. Mirrors the row-level serialization on ApprovalDecision and the world-model authoring surfaces.
  • The publish-version mutate API is idempotent on (operator_id, correlation_id). A re-issued request with the same correlation ID returns the original outcome; the dedup anchor is recorded on the corresponding WorldAuthoringAudit row.
  • Prior versions are non-destructively retained. Historical World Model Cards remain valid content after a new version is published per ADR-026; no retroactive card mutation, no automatic recertification. Action modules in the module store are immutable and addressed by content hash; superseded versions remain queryable indefinitely.
  • Version is metadata, never a partition boundary. Per ADR-030, downstream consumers do not reset state on version publication; System Card surfaces render version markers as overlays on continuous data, not as partition boundaries.

Every operator publication action appends a row to the WorldAuthoringAudit record family. The discriminator introduced for publication is:

  • target_type = world_model_version, action = version_published — operator publishes a new world-model version

The audit row is appended alongside the entity-state mutation in the same transaction; it is never appended outside the originating use-case transaction. The (operator_id, target_type, target_id, action, occurred_at, correlation_id) row remains queryable for the full active window per data-retention.

WorldAuthoringAudit is not agent memory (per the records-vs-memory framing). It is operator-scoped (app.user_id) with no domain RLS, distinct from ApprovalDecision (same identity domain, different action surface — enshrinement-gate decision vs authoring).

The publication call shares the call-flow shape with enshrinement — apps/operations consumes spectral.worlds via HTTP through apps/api per ADR-047. Within Python the operator invokes the use-case handler worlds.application.publication.PublishWorldModelVersion directly from apps/api/operator/publications per ADR-070 Tier 1 (single-Python-consumer call flow consumed directly by apps/* per the validator’s app-context-surface rule). The handler is minted in spectral.worlds.application.publication.

The publication transaction is atomic across four artifact mints:

  1. The new WorldModel version row.
  2. One ActionModule row per registered action (with its content hash, code provenance, embedded schema digest, and module bundle written to the module store).
  3. The WorldModelCard via mint_world_model_card_at_publication.
  4. The outbox row for worlds.world_model_card.published (typed payload at spectral.worlds.contracts.events.world_model_card_published per ADR-065 D2).

After commit, the World Agent emits worldmodel.version.published — signal-shaped; spectral.platform’s decision-server does not subscribe to it for state changes (per Version Attribution — module-cache invalidation happens lazily on first request for the new version, not by version-event subscription).

The operator UI surfaces this workflow as a single staged Publish surface — the deliberate, irreversible-feeling promotion of approved rules into a new live version. It moves the operator through staged changes, to a type-to-confirm gate, to a success state, with the version-history timeline folded in:

  1. Staged changes — the approved rules accumulated since the live version, with the added / changed / removed counts for the next version, plus any configuration-block / action-registry changes; previewed before publishing
  2. Type-to-confirm — final sign-off behind a confirm gate: a “what publishing does” explainer, and a confirm button that unlocks only once the operator types publish vN exactly. The publish carries a correlation_id supplied by the UI for idempotency, then lands on a success state
  3. Version history (folded in — not a separate surface) — the timeline of published versions, each linking to its World Model Card (the card’s entry point) and its human-written release notes

Release-notes authoring is the release-notes editor — the operator-authored narrative plus three-category restatement content that ships with the new version.

Every UI surface has a corresponding API endpoint per the API/UI parity rule — the UI is a thin client over the same routes.

The HTTP routes the UI consumes as an API client (per the parity contract) include:

  • POST /worlds/:world_id/publications — operator triggers a new world-model-version publication (idempotent on (operator_id, correlation_id)); request includes the in-flight release-notes reference; response carries the minted world_model_version and the module-store entries created for each action
  • GET /worlds/:world_id/publications/:id — publication status (draft, in-progress, completed, failed)
  • GET /worlds/:world_id/versions — list of published versions (newest first); each entry links to its World Model Card, the action-module entries in the module store, and accompanying release notes

Auth middleware sets app.user_id via SET LOCAL per ADR-041 D4; RLS predicates compare against app.user_id per ADR-039. The apps/operations deployable consumes these routes via HTTP per ADR-047 and never imports spectral.worlds internals; the architecture validator at STRICT=True enforces this.