Docs/Operations/Resource versioning

Resource versioning

How Fermix versions prompt and memory resources in SQLite, tracks provenance, and lets you inspect, diff, and roll back revisions with mix tasks.

Fermix keeps a version history of its prompt and memory files, so you can review past versions and undo changes. It persists its prompt files — both the bootstrap prompt files (the standing instructions loaded into every prompt) and the memory-derived profiles (USER.md and MEMORY.md) — as versioned resources in its SQLite database (the local file where Fermix stores this state). Every write creates a new revision row with a content hash (a fingerprint of the content) and a provenance record (a note of what caused the change), giving you a full audit trail and the ability to roll back to any prior state.

What gets versioned

Resources fall into two categories:

  • File-backed resources (IDENTITY.md, FERMIX.md, SOUL.md, REALTIME.md, USER.md, MEMORY.md): the rendered content of these prompt files is stored as a revision every time the content changes. These support rollback.
  • Checkpoint resources: revision records created during conversation compaction. When Fermix summarizes older messages to stay within the model’s context limit, it saves that summary as a checkpoint revision scoped to the conversation. These are audit and history records only. Rollback is not supported for checkpoint resources.

See memory and prompt and compaction for how these files are built and used.

Database schema

Two tables back the versioning system:

resources(
  id, agent_id, resource_type, scope_id,
  resource_path, current_revision,
  created_at, updated_at
)

resource_revisions(
  id, agent_id, resource_type, scope_id,
  revision, parent_revision,
  content_hash, content, byte_size,
  mutation_source, provenance_json,
  created_at
)

current_revision on the resource row is the current revision number (not a row id); it points at the matching revision in resource_revisions. content_hash is stored on each revision row. A new revision is only written when the hash differs from the current revision’s hash, so writes are idempotent (rewriting identical content creates no new revision).

scope_id identifies the conversation key for checkpoint resources. File-backed resources use a global scope (scope_id = "global").

Provenance and mutation source

Every revision carries a mutation_source string and a provenance_json blob. mutation_source describes what triggered the write:

Value Trigger
"seed" Initial file seeded on install by the setup wizard
"imported" File found on disk with no registry record; self-healed on first read
"manual_edit" Direct file or API edit
"extraction_rebuild" Memory promotion rebuilt the file
"scheduler_rebuild" Scheduled job triggered a rebuild
"compaction" Conversation compaction checkpoint
"soul_curation" Owner-confirmed /soul persona edit
"rollback" Created by a rollback operation

provenance_json carries structured metadata specific to the mutation source: for example, the job id for a scheduler rebuild, or the source revision number for a rollback.

The seed revision is also what lets Fermix detect template drift. fermix doctor’s bootstrap templates check compares the current shipped template for FERMIX.md, SOUL.md, and REALTIME.md against the content their seed revision recorded at install time. Seeding only ever writes a file that does not already exist, so an install keeps its original bootstrap files when a shipped template later changes; the check warns when one of them has drifted, so you can diff your file against the current template and pull in anything you want. Installs seeded before revision tracking have no seed revision to compare against — the check passes and names those files instead. IDENTITY.md is excluded because it embeds the agent name, so a render comparison cannot tell template drift from a rename.

Mix tasks

All resource history operations use Mix tasks (commands run with mix, available when running Fermix from source rather than the packaged binary). You reference a resource by its type name (e.g. user_md, checkpoint).

Task Purpose
mix fermix.resource.list List all resources with their current revision.
mix fermix.resource.show <name> [rev] Print the current content, or a specific revision.
mix fermix.resource.history <name> Print all revisions with metadata.
mix fermix.resource.diff <name> <rev_a> <rev_b> Print a unified diff between two revisions.
mix fermix.resource.rollback <name> <rev> Roll back to a prior revision.

Examples

mix fermix.resource.list
mix fermix.resource.history user_md --limit 10
mix fermix.resource.show user_md 3
mix fermix.resource.diff user_md 2 3
mix fermix.resource.rollback user_md 2

mix fermix.resource.rollback prints a preview diff and prompts for confirmation before writing; pass --yes to skip the prompt (useful in scripts). The diff task accepts --context N to widen the unified-diff context (default 3 lines), and any task accepts --agent <id> to target a non-default agent.

The –scope flag

Checkpoint resources are scoped to a conversation key. Pass --scope <conversation-key> to target them:

mix fermix.resource.history checkpoint --scope telegram:123456789

Checkpoint resources do not support rollback. Running mix fermix.resource.rollback checkpoint ... returns an error — checkpoint revisions are audit and history records only.

Rollback behavior

Rolling back any file-backed resource creates a new revision row with mutation_source: "rollback" and advances the resource’s current_revision to that new revision number. The file on disk is updated to match. Rolling back to content identical to the current revision is a no-op — no new revision is written, and Fermix reports that the resource is already at the target content.

One important caveat for USER.md and MEMORY.md: future memory rebuilds can overwrite a rolled-back file if the underlying promoted memories are unchanged. The rebuild sees the same source memories and regenerates the same content, which may differ from the revision you rolled back to. If you want a rollback to persist, edit or remove the memories that drove the unwanted content, then rebuild.

For SOUL.md, a rolled-back revision persists until the next /soul apply, revert, or reset. The /soul revert N command in the channel is the higher-level surface for this operation: it is owner-only, requires a /soul apply <token> confirmation, and invalidates the running agent’s cached persona so the revert takes effect without a restart. The mix task performs the same rollback — the same new revision and the same rewrite of the file on disk — but it runs outside the daemon and cannot invalidate that cache, so a running daemon keeps serving the pre-rollback persona until you restart it. (The stale-base check that refuses a write when SOUL.md changed underneath the draft applies to /soul apply of a curation proposal — not to revert or reset.)

Internal consumers

Five internal components write resource revisions:

  • Prompt.BootstrapLoader loads the bootstrap files when composing the system prompt for each agent turn. If a file exists on disk but has no registry record, it captures a first revision (imported); if the on-disk content has drifted from the recorded revision, it captures that change (manual_edit) — this is how a hand-edited prompt file gets picked up and versioned.
  • Memory.PromptFiles commits a new revision whenever a memory rebuild changes the rendered content of USER.md or MEMORY.md. It skips the write when the content hash matches the current revision.
  • Prompt.SetupSeeder seeds the initial bootstrap files on first install.
  • Memory.Compactor writes the checkpoint revisions: when a conversation is compacted, the resulting summary is committed as a checkpoint revision scoped to that conversation.
  • SoulCuration is the only path that writes SOUL.md outside setup seeding. Every owner-confirmed /soul edit, revert, or reset is committed as a versioned revision.
  • Memory: how facts are stored, promoted, and used to rebuild USER.md and MEMORY.md.
  • Prompt and compaction: how bootstrap files are loaded into the system prompt and when compaction checkpoints are created.
  • CLI reference: full listing of fermix daemon commands.

Next steps