an.stores#

Project mall: a dict of dol-backed MutableMapping stores.

The mall is the unit of persistence in an. Every long-lived state — assets (characters, props, environments, voices, styles, sounds), the scene file pair, intermediate artifacts (audio, viseme tracks, best-of-N take records, per-shot mp4s, the content-keyed shot cache), final output and its caption sidecar, the agent’s decision log, and the asset library’s lockfile of pinned check-outs — is keyed inside a store. Stores are dol-backed so the same call sites work against filesystem, SQLite, S3, etc.

>>> import tempfile
>>> from pathlib import Path
>>> with tempfile.TemporaryDirectory() as d:
...     mall = build_project_mall(d, ensure=True)
...     sorted(mall.keys()) == [
...         'audio', 'captions', 'characters', 'contact_sheets', 'decisions',
...         'environments', 'library_lock', 'measurements', 'output',
...         'pictures', 'previews', 'props', 'render_reports', 'scenes',
...         'shot_cache', 'shots', 'sounds', 'sources', 'styles', 'takes',
...         'visemes', 'voices',
...     ]
True

Functions

build_project_mall(project_dir, *[, ensure])

Build the standard project mall over project_dir.

Classes

CharactersStore(root_dir)

Per-character directory store.

EnvironmentsStore(root_dir)

Per-environment directory store (meta + sidecar art).

VoicesStore(root_dir)

JSON-only voice descriptors.

StylesStore(root_dir)

Pure-JSON style descriptors.

PropsStore(root_dir)

Per-prop directory store.

ScenesStore(project_dir)

MutableMapping exposing the scene file pair under a project root.

SoundsStore(root_dir)

Per-sound directory store.

AudioArtifactStore(root_dir)

TTS-rendered audio clips (.wav).

VisemeArtifactStore(root_dir)

Lip-sync viseme tracks (.json) — stored as bytes for cache uniformity.

TakesArtifactStore(root_dir)

Best-of-N take records (.json bytes), keyed by the line's audio key: which take was kept, its sha256, every take's score and the scorer (an#265).

ShotArtifactStore(root_dir)

Per-shot rendered mp4s.

PreviewArtifactStore(root_dir)

Low-res preview renders (mp4 or png sequence wrapper).

ContactSheetStore(root_dir)

Contact sheets (.png): frames of a render at its settled beats, labelled with their time, for a person or an agent to LOOK at (core study §2.10).

MeasurementStore(root_dir)

Measurements a clock-owning renderer made of its content (.json bytes), keyed by that content's key — DERIVED data, never the author's (an#279): a Manim shot's length, its timeline of beats, its findings.

PictureStore(root_dir)

An opaque renderer's raw picture (.mp4) — a Manim scene's own render, before it is conformed to a film's fps and size, so a change that is not to the picture (narration, fps) does not run Manim again (an#279).

RenderReportStore(root_dir)

What a render found (.json), keyed like the output it describes — render_reports["main"] — so orchestrate and MCP read the findings that an render warned (an#279).

SourcesStore(root_dir)

Python scene sources (.py bytes) — a Manim scene file per key.

OutputStore(root_dir)

Final composited renders.

DecisionLogStore(log_path)

Append-only JSONL log keyed by ordinal index (as string).

ProjectLock(project_dir)

<store>/<key> -> pin over a project's assets.lock.json.

class an.stores.AudioArtifactStore(root_dir)[source]#

Bases: _BlobStore

TTS-rendered audio clips (.wav).

class an.stores.CharactersStore(root_dir)[source]#

Bases: JsonSidecarStore

Per-character directory store.

>>> import tempfile
>>> with tempfile.TemporaryDirectory() as d:
...     store = CharactersStore(d)
...     store['maya'] = {'name': 'Maya', 'voice_ref': 'maya-warm'}
...     store['maya']['name']
'Maya'
class an.stores.ContactSheetStore(root_dir)[source]#

Bases: _BlobStore

Contact sheets (.png): frames of a render at its settled beats, labelled with their time, for a person or an agent to LOOK at (core study §2.10).

Content-addressed — the key is the sha256 of the PNG bytes — so a shot whose render is reused from the shot cache still points at its sheet through the cached provenance, and two shots with one picture share one file.

class an.stores.DecisionLogStore(log_path)[source]#

Bases: MutableMapping

Append-only JSONL log keyed by ordinal index (as string).

Mutating in-place (__setitem__, __delitem__) is intentionally forbidden; the log is append-only by design.

>>> import tempfile, os
>>> with tempfile.TemporaryDirectory() as d:
...     log = DecisionLogStore(os.path.join(d, 'decisions.jsonl'))
...     _ = log.append(kind='test', body={'x': 1})
...     _ = log.append(kind='test', body={'x': 2})
...     entries = list(log.values())
...     entries[0]['body']['x'], entries[1]['body']['x']
(1, 2)
append(*, kind, body, **extra)[source]#

Append one decision; returns its ordinal index.

Return type:

int

class an.stores.EnvironmentsStore(root_dir)[source]#

Bases: JsonSidecarStore

Per-environment directory store (meta + sidecar art).

class an.stores.MeasurementStore(root_dir)[source]#

Bases: _BlobStore

Measurements a clock-owning renderer made of its content (.json bytes), keyed by that content’s key — DERIVED data, never the author’s (an#279): a Manim shot’s length, its timeline of beats, its findings.

class an.stores.OutputStore(root_dir)[source]#

Bases: _BlobStore

Final composited renders.

class an.stores.PictureStore(root_dir)[source]#

Bases: _BlobStore

An opaque renderer’s raw picture (.mp4) — a Manim scene’s own render, before it is conformed to a film’s fps and size, so a change that is not to the picture (narration, fps) does not run Manim again (an#279). Content-addressed (the key is the sha256 of the mp4): the measurement record under the picture key names it, so a record and its picture are written as one (an#291).

class an.stores.PreviewArtifactStore(root_dir)[source]#

Bases: _BlobStore

Low-res preview renders (mp4 or png sequence wrapper).

class an.stores.ProjectLock(project_dir)[source]#

Bases: MutableMapping

<store>/<key> -> pin over a project’s assets.lock.json.

Every write rewrites the whole (small) file, sorted, so the lockfile diffs cleanly under version control. The mapping is the assets section; kits is the kits section, and a write to either keeps the other.

property kits: MutableMapping[str, dict[str, Any]]#

kit asset id -> record of the kits checked out into the project.

class an.stores.PropsStore(root_dir)[source]#

Bases: JsonSidecarStore

Per-prop directory store.

>>> import tempfile
>>> with tempfile.TemporaryDirectory() as d:
...     store = PropsStore(d)
...     store['lamp'] = {'name': 'Desk lamp'}
...     store['lamp']['name']
'Desk lamp'
class an.stores.RenderReportStore(root_dir)[source]#

Bases: _BlobStore

What a render found (.json), keyed like the output it describes — render_reports["main"] — so orchestrate and MCP read the findings that an render warned (an#279).

class an.stores.ScenesStore(project_dir)[source]#

Bases: MutableMapping

MutableMapping exposing the scene file pair under a project root.

Keys: currently always "main". The store enforces this by raising KeyError for other keys.

patch_shot_durations(durations)[source]#

Set duration on the named shots WITHOUT regenerating scene.md.

__setitem__ rewrites the markdown from the IR, which drops every word of prose and every comment the IR does not hold. This writes the JSON through the read boundary as usual, and patches only each shot’s duration: line in the markdown (inserting one into its ```` `yaml shot `` block, or the block itself, when there is none) — what an sync --accept-measured uses to take a measured duration into the authored scene (an#279).

Return type:

None

class an.stores.ShotArtifactStore(root_dir)[source]#

Bases: _BlobStore

Per-shot rendered mp4s.

class an.stores.SoundsStore(root_dir)[source]#

Bases: JsonSidecarStore

Per-sound directory store.

>>> import tempfile
>>> with tempfile.TemporaryDirectory() as d:
...     store = SoundsStore(d)
...     store['hit'] = {'description': 'a stick on a table'}
...     store.write_audio('hit', b'RIFF....')
...     store['hit']['description'], store.read_audio('hit')
('a stick on a table', b'RIFF....')
AUDIO_NAME = 'audio.wav'#

an.sounds reads its header for the duration a fade-out needs, deterministically.

Type:

The sidecar holding the audio bytes. WAV only in v1

class an.stores.SourcesStore(root_dir)[source]#

Bases: _BlobStore

Python scene sources (.py bytes) — a Manim scene file per key.

class an.stores.StylesStore(root_dir)[source]#

Bases: JsonDirStore

Pure-JSON style descriptors.

class an.stores.TakesArtifactStore(root_dir)[source]#

Bases: _BlobStore

Best-of-N take records (.json bytes), keyed by the line’s audio key: which take was kept, its sha256, every take’s score and the scorer (an#265).

class an.stores.VisemeArtifactStore(root_dir)[source]#

Bases: _BlobStore

Lip-sync viseme tracks (.json) — stored as bytes for cache uniformity.

class an.stores.VoicesStore(root_dir)[source]#

Bases: JsonDirStore

JSON-only voice descriptors.

>>> import tempfile
>>> with tempfile.TemporaryDirectory() as d:
...     store = VoicesStore(d)
...     store['maya-warm'] = {'provider': 'elevenlabs', 'voice_id': 'xyz'}
...     'maya-warm' in store
True
an.stores.build_project_mall(project_dir, *, ensure=False, **overrides)[source]#

Build the standard project mall over project_dir.

Pass ensure=True to create the per-store directories on disk if they don’t exist. Pass keyword overrides to swap in alternate stores (e.g. an in-memory dict for tests).

Return type:

dict[str, MutableMapping]

Modules

artifacts

Artifact stores — derived, regeneratable products of the pipeline.

characters

Characters store — descriptor + sidecar folder per character.

decisions

Decision log — append-only JSONL of agent decisions and user approvals.

environments

Environments store — backgrounds, set pieces, and prop bundles.

library_lock

The project lockfile: which library version each checked-out asset came from.

props

Props store — descriptor + sidecar folder per prop.

scenes

Scenes store — wraps the project's scene.md + ir/scene.json pair.

sounds

Sounds store — one directory per sound: sound.json beside audio.wav.

sources

The project's opaque scene sources: files a whole-shot renderer runs as they are.

styles

Styles store — visual style presets (color palette, line weight, fonts).

voices

Voices store — pure JSON; one entry per voice.