---
type: Axis
title: mutability (write-discipline axis)
description: The mutability/write-discipline architecture axis — how a persisted entity may be changed after creation (immutable → append-only → mutable). A per-entity-with-default axis whose commitment surface is the persistent-data schema (the write path the store permits). DEEP (RFC #75 5A.4 / P1 #851 → promoted 4.5.0a6 #856); worked example is the append-only action-log vs the mutable canonical issue/discussion record vs the immutable published wheel — the three rungs all live in the skill at once.
tags: [axis, architecture, mutability, write-discipline, append-only, immutable, rfc-75, deep]
timestamp: 2026-06-20T00:00:00Z
---

# Mutability (write-discipline axis)

> **DEEP axis (P1 #851 → 4.5.0a6 #856).** Full §6 depth with a worked example
> from the skill's own history — the skill runs all three rungs at once: the
> action-log is append-only, the canonical issue/discussion record is mutable,
> and a published wheel/content-addressed artifact is immutable, each enforced by
> a different write path. Distinct from `temporality` (whether you *stamp when* a
> change happened) and `consistency` (how *concurrent* writes reconcile):
> mutability is whether a record may be changed in place *at all* after it is
> written.

## Concept

Mutability is the **write-discipline** axis (RFC #75 §3): how an entity may be
changed after creation. The ladder runs immutable (write-once; never altered —
corrections are new records) → append-only (existing rows are never updated, only
new rows appended; state is a fold) → mutable (rows are updated in place). Its
**commitment surface is the persistent-data schema** (§4): the discipline is the
write path the store and access layer permit, and tightening it later means
rewriting every UPDATE into an append or a new-version write. Its **scope is
per-entity-with-default** (§5): a system-wide default ("entities are mutable")
with per-entity deviations (a ledger is append-only; a published artifact is
immutable) declared in the entity record.

## Why it is an axis (discriminator test — §2)

1. **Ordered tiers** — each rung permits more in-place change (immutable ⊂
   append-only ⊂ mutable in what writes they allow; the *constraint* loosens
   down the ladder).
2. **Cross-cutting bundle** — a rung dictates the write path, the
   correction/versioning model, the read path (a fold for append-only), the
   audit story, and the write-discipline tests.
3. **Asymmetric migration cost** — relaxing to mutable is easy; *tightening*
   (mutable → append-only/immutable) is a rewrite of every write path plus a
   reconstruction of history that the prior in-place updates already destroyed.
4. **Requirement-keyed selection** — falsifiable probes pick the rung.

## Schema view (the §6 entry — validated by `axis_catalog`)

```yaml
id: mutability
kind: architecture-axis
scope: per-entity-with-default
default_tier: mutable
maintenance_discipline: >-
  entities are MUTABLE by default — rows are updated in place. A per-entity
  tightening to append-only (a ledger, an event/audit stream) or immutable (a
  published, content-addressed artifact) is declared in the entity record's
  axis-materialization facet, and the write path is then ENFORCED to forbid
  in-place UPDATE. The discipline forbids quietly updating an append-only row
  (it destroys the very history the tier exists to keep — the append-log /
  recorded-history scar). Per-entity deviations live in the entity record.
selection:
  probes:
    - "Once written, must this record NEVER change (a published artifact, a content hash)? → immutable."
    - "Must every change be a new appended fact, never an in-place edit (a ledger, an audit stream)? → append-only."
    - "Are in-place edits the normal, expected operation? → mutable."
    - "Is something UPDATE-ing rows in a store meant to be append-only? → that violates the tier."
composes_with:
  - "history fidelity = mutability × temporality (append-only preserves the sequence)"
applies_when: []
tiers:
  - tier: immutable
    commitment_delta:
      surface: persistent-data-schema
      delta: "write-once; a record is never altered after creation. Corrections are entirely new records (a new version/id). Maximally safe to cache + reference."
    admin_tool: "version/content-address registry."
    enforcement:
      - "the write path permits INSERT only; any UPDATE/DELETE to an existing record is rejected."
    tests:
      - "an attempt to modify an existing immutable record is rejected; a correction creates a new record."
    forecloses: "in-place correction; references must track versions."
    migration_cost_to_next: "low — allow appending related rows while keeping each row immutable (append-only)."
  - tier: append-only
    commitment_delta:
      surface: persistent-data-schema
      delta: "existing rows are never updated; only new rows are appended. Current state is a fold over the appended facts. Full history is retained."
    admin_tool: "event/log viewer; a fold/replay tool."
    enforcement:
      - "the write path appends; no UPDATE of an existing row is permitted; reads fold the sequence."
    tests:
      - "state == fold(appended rows); an in-place UPDATE is rejected; replay is deterministic."
    forecloses: "in-place mutation; storage grows monotonically (a retention interaction)."
    migration_cost_to_next: "medium — permit in-place UPDATE (mutable) — but note history before the switch is lost going forward."
  - tier: mutable
    commitment_delta:
      surface: persistent-data-schema
      delta: "rows are updated in place; the row holds only the latest state. Simplest write path; intermediate states are not retained unless temporality says so."
    admin_tool: "standard CRUD tooling."
    enforcement:
      - "in-place UPDATE is the normal write; concurrency control (the consistency axis) governs conflicting writes."
    tests:
      - "an UPDATE changes the row in place; the latest value is read back."
    forecloses: "reconstructing intermediate states from the row alone."
    migration_cost_to_next: "n/a — the most permissive rung (tightening UP the ladder is the expensive direction)."
examples:
  - "This is a per-entity axis and the skill instantiates all three rungs simultaneously — the clearest demonstration of why mutability is per-entity-with-default. The action-log is APPEND-ONLY: every recorded turn, classification, and forge operation is a new row, current state is a fold over the sequence, and the discipline this axis names is enforced precisely because violating it is catastrophic — a regenerator or projection that quietly UPDATEd an action-log row would destroy the very audit trail the log exists to keep (this is the same family as the #604/#698 regenerator scar, where a write path that should have preserved genesis clobbered it; mutability says the action-log's write path must permit INSERT only). The canonical issue/discussion record is MUTABLE: bodies, TOCs, and metadata are edited in place, the row holds only the latest state, and the temporality axis (updated_at) supplies the 'when changed' that mutability deliberately does not retain. A published wheel or content-addressed UI bundle is IMMUTABLE: a new build is a new version (a new PyPI release, a new content hash), never an edit of an old one, which is exactly why a released artifact is safe to cache and reference. The asymmetric-cost lesson is live here: relaxing the action-log to mutable would be one line, but it would forfeit history irrecoverably — the expensive direction this axis warns about is *tightening*, and the action-log was designed append-only from the start to avoid ever needing it."
```

## Selection procedure (§8)

Bidirectional check per entity under the mutable default. The escalation
(tightening) pass asks "must every change be a new fact, or must this never
change?" — a yes forces append-only or immutable. Recorded in the entity record;
an in-place UPDATE against an append-only store is a systems-analysis finding
(5A.5).

## Composition (§5)

Mutability × temporality = **history fidelity** — an append-only entity preserves
the full sequence temporality wants to query, where a mutable one keeps only the
latest. Rule authored in 5A.3.
