Reference
Core store files
The store's control and ledger files: the manifest that declares the store, the ID counters, the version ledger, the worklog (appended per change, correctable until released, then frozen), and the concurrency lease. Choose a file to see what it holds and what it protects.
Core store file
The store manifest
manifest.toml .working/toml/
The store's control document and discovery marker: declarations for its schema, types, views, modules, and enforcement posture.
Template
Closed keysets throughout: an unknown key in any base section is a validation finding. The base
[opf] table carries the exact discovery token standard = "opf", the
spec version the store conforms to, and the homes generation. The base of a spec 2.0.0 store:
The reference tooling does not yet implement spec 2.0.0: its scaffold still writes
spec_version = "1.2.0" with no homes key.
The top-level tables:
[opf] standard, spec_version, homes (2), layout (inline | per-record),
posture (off | warn | required), import_status (none | partial | complete)
[store] sync_target (empty under the in-repo default)
[modules] governance, delivery_assurance, operational_policy, concurrent_operation
[profiles.*] additive requirement bundles (version, base_compat, posture_floor,
required_modules, extension_namespace); may only ADD requirements
[types.*] one table per enabled type, carrying its normative namespace
[providers.*] handler + roles (create, auth, sync); local-directory and
generic-git-remote ship as universal fallbacks
[views.*] kind (deterministic | composed | projection), sources, target
[deliverables.*] the curated CHANGELOG.md declaration
[archive] period ("year")
[unmanaged] pre-existing files kept in place, enumerated
[vendors] registered x-<vendor> extension namespaces
The reference scaffold writes: every module false, no profile, an empty vendor
registry, posture = "required", import_status = "none",
layout = "inline", the twelve baseline type bindings, and thirteen declared views
(the twelve Markdown views plus the DECISIONS.toml projection), each targeting
.working/<name>.
Operations on an existing store resolve its pointer and validate the manifest; initialization instead builds a new manifest, and planned verbs currently refuse without resolving a store. An unreadable or unparseable manifest is a cannot-evaluate that stops a reader. A profile a tool supports is enforced fail-closed; a profile it does not support is ignored for enforcement and recorded as unevaluated, so an unknown profile does not fail base validation. Weakening the posture (required toward warn or off) is a guardrail-configuration change: it takes effect only through the maintainer's explicit, recorded authorization, and a profile floor can raise, never lower, the effective posture.
The manifest is control data, not a record source, so it has no paired Markdown view; it is,
however, what declares every other pair, because the [views.*] map is the registry
the renderer and the drift gate read. It is created by opf init, validated before a
byte is written; updated by the adopter's own reviewed edit to
enable a module, register a vendor, or record an unmanaged path, and, in the standard's planned
opf migrate operation, re-pointing the recorded sync target. Migration is not yet
implemented in the reference CLI. opf render reads the view map, and
opf doctor checks posture, types, modules, unmanaged containment, and sync agreement.
The problem it solves
Declare the store contract so tools need not infer it.
The manifest makes the store's contract explicit and machine-checkable: a tool validates the
base before operating, enforces only what is declared, and records a profile it does not support
as present-but-unevaluated rather than failing over it. Because the machine subdirectory is
observed at each use rather than declared and trusted, renaming it is a directory move with
nothing to go stale. Tooling locates the machine store by finding exactly one immediate
subdirectory of .working/ whose manifest declares the token; zero matches or more
than one stops the tool, never guesses.
At a glance
- Declares
[opf][modules][types.*][views.*][providers.*][profiles.*]- Read by
opf renderopf doctoropf absorbopf recordimplemented readers of an existing store- Written by
opf inita reviewed adopter editopf migrate(planned; not yet implemented in the reference CLI)
What it protects
One reviewed contract, checked at every load
The manifest records the store contract in one file. Closed keysets let validation report unknown base keys as findings. The intended benefit is less reliance on undocumented defaults.
Core store file
The ID counters
counters.toml .working/toml/
The ID authority: one monotonic high-water value per record namespace.
Template
Every record ID has the form <NS>-<n>: a two-letter namespace mapped
one-to-one to its type and a positive integer. The counters hold each namespace's allocated
high-water mark. A fresh store starts the twelve baseline namespaces and the importer's LF
namespace at zero. The file contains a schema marker and namespace-to-integer pairs.
The scaffold's values, shown with display indentation:
Allocation increments the counter under the store's lock as one atomic claim, so no gap between choosing an ID and reserving it can double-allocate. Counters are never reset and IDs are never reused, even when a record is superseded, refuted, or its work reverted. Rotation, index rewrites, and store relocation never touch this file. Counters are a control ledger, not a record type, so no view renders from them.
It is created by opf init with all namespaces at zero, updated by ID allocation
(atomically under the store lock, whenever any process creates a record in any type), and read
by opf doctor (for
counter completeness, monotonicity against a prior committed snapshot, and every live or archived
ID within its high-water) and by record creation, to allocate the next ID.
The problem it solves
Durable records need permanent names.
Reusing an ID can make a link ambiguous. The standard requires atomic allocation and monotonic counters so references can retain a stable identity; this is a contract adopters must preserve when creating records.
At a glance
- Tracks
<NS>-<n>12 baseline namespaces + LF monotonic high-water- Written by
opf initID allocation, atomicopf record- Read by
opf doctorrecord creation
What it protects
Stable IDs for later reference
The standard requires IDs to remain resolvable in active or archived records. The integrity checks compare IDs with counter high-water marks and counters with a prior snapshot. They check those invariants, not whether a cited record's claims are true.
Core store file
The version ledger
version.toml .working/toml/
The version and release ledger: numbers, dates, spans, and digests, never release prose.
Template
Two arrays of rows. Each [[release]] row records the SemVer version
(unique in the ledger), the RFC 3339 UTC date read from the clock at the release
event, the worklog_span (the inclusive, contiguous span of worklog entry IDs the
release covers), and a coverage_digest over the covered entries, computed at release
cut. Spans must tile: contiguous, non-overlapping, in ID order, so the unreleased tail is
everything after the last span. Each [[summary]] row backs one public changelog
entry: covers (a version, a range like 1.0.0..1.2.3, or
unreleased), status (working, published, or superseded), the freeze
digest once published, and superseded_by when a range rollup replaced
it. Summary rows hold digests and ranges only; prose lives in exactly one place, the root
CHANGELOG.md.
A release cut appends a row and freezes the covered worklog span; from then on any change to
those entries breaks the recorded digest and fails the gate. Publishing a changelog summary
records its freeze digest here. The freeze check compares the published entry's LF-normalized
UTF-8 digest with its recorded digest; line-ending-only changes do not alter that digest.
Other edits require recorded re-publication. A fresh store scaffolds an empty ledger
(release = [], summary = []).
It renders two deterministic views: the root VERSION file (the latest release's
version as exact bytes, the one generated file that carries no header) and the optional human view
VERSION.md. Both are byte-drift-gated. The initial scaffold declares
VERSION.md but omits the root VERSION view. When recording the first
release, declare that view so the reference renderer can produce the required root file.
Doctor checks VERSION whenever releases exist, even if its view is undeclared
(see doctor coverage). The ledger is
created by opf init (empty), updated by the release cut (a new append-only release
row) and the changelog publish and rollup flow (summary rows and their digests), and read by
opf render (the VERSION and VERSION.md renders), the changelog range-coverage and
freeze gates, opf doctor (span tiling, frozen coverage digests, append-only
history). The specification describes release-delta tooling as a consumer of the ledger;
that integration is not implemented in the reference tooling.
The problem it solves
Keep version metadata, detailed entries, and public summaries separate.
The release triad assigns version metadata to the ledger, detailed entries to the worklog,
and curated prose to CHANGELOG.md. The root VERSION file is required
whenever releases exist and rendered from the latest ledger release when declared as a view.
Release rows are append-only and
immutable; summary rows change through publication and supersession under their own rules.
At a glance
- Records
[[release]][[summary]]SemVer, dates, spans, digests- Feeds
VERSIONVERSION.mdCHANGELOG.md- Read by
opf renderopf doctorchangelog gates
What it protects
One ledger, one version, everywhere
The drift gate makes a stale VERSION file a reported failure, and the span-tiling
rule means late attribution to a published release cannot pass the gate, rather than being
forbidden by policy.
Core store file
The worklog
worklog.toml WL .working/toml/
The detailed operational record: one entry per change, appended as the work happens.
Template
An array of [[entry]] rows using a reduced record envelope: id
(namespace WL), date, actor, a change kind
(added, changed, fixed, removed,
security, docs, or infra; a manifest may register
additional kinds), a one-line summary, optional detail, and
optional links and refs to the records and revisions it concerns. Its status is
the single state recorded, and it never takes the /proposed qualifier
whatever the actor: a worklog entry records a fact, not a proposal awaiting ratification.
The worklog is the fact layer of the release triad. Every change gets an entry; every entry stays forever. Entries are mutable until a release freezes their span, immutable after, and never consumed, rolled away, or deleted. Every fact ever recorded stays in the worklog or its archive, and survives store relocation byte for byte. At release, the release's coverage digest freezes the covered entries; from then on any change to them is a gate failure, and an entry can never be appended into an already-released span, because spans are contiguous frozen ID intervals. Only released, frozen spans may rotate to the archive; the unreleased tail never rotates, whatever its age or size.
It renders WORKLOG.md, a deterministic, byte-drift-gated view at
.working/ top level, opening with the standard do-not-edit header. The worklog is
created by opf init (empty), updated by every change as an appended entry (IDs
allocated through counters.toml), by pre-release corrections in place, and by rotation of
released spans into the archive; it is read by opf render (WORKLOG.md), the release
cut (span selection and coverage digest), the changelog drafting flow (summaries are drafted from
spans), and opf doctor (span tiling, frozen digests, ID partition between active and
archive).
The problem it solves
Keep the detailed record beneath each summary.
The rollup flow replaces public summaries while retaining worklog entries and publication digests. Review the revised summary for accuracy and completeness. Before release, correct worklog mistakes through review; after release, append a new entry linking the one corrected.
At a glance
- Records
[[entry]]one per change never deleted; frozen once released- Renders
WORKLOG.md- Read by
opf renderopf doctorrelease cut changelog drafting
What it protects
A retained record beneath summaries
The intended benefit is a durable change record from which summaries can be drafted. A change to released entries that disagrees with their recorded digest is an integrity finding.
Core store file
The single-writer lease
lease.toml .working/toml/
Present only while a run holds the store's single-writer lease; its absence is the normal state.
Template
The standard requires a run to take a lease before mutating an existing store and to make it
observable at the sync target before writing. Its consistency contract includes a divergence
check for collisions during propagation; cross-system synchronization is planned in the
reference CLI. The file carries the holder, the operation, and
an acquired-at timestamp read from the clock at acquisition: a closed four-key shape,
schema, holder, operation, and acquired_at.
Where the concurrent-operation module is enabled, the lease is additionally recorded as a
session_lease record (namespace SL) with the states held, released, or
reconciled.
A lease is never seized from a live holder. It is reconciled against recorded state on resume or close, and a leftover lease from a dead run is released only through that reconciliation. The standard discloses the residual honestly: between taking the lease and its reaching the sync target there is a propagation window in which two systems can both begin; the divergence check is the overlapping control that catches that collision, and the two layers together, not the lease alone, are the guard. The lease is transient operational state, not a record source, so no view renders from it.
The standard describes acquisition before mutation and release at clean close or after
reconciliation of a dead run. Implemented coverage is narrower: opf record claims
a lease, and opf doctor validates its shape when present.
The retired opf import modes refuse before any write and take no lock.
opf init holds the lease, under the shared operation lock, only while it writes
the store, removes the lease and releases the lock before it reports success, and clears a
dead run's leftover lock record only with --recover. opf sync
and opf migrate are planned, not implemented cross-system enforcement.
The problem it solves
Two runs writing the same store at once can each produce a locally consistent state that cannot merge.
A textual merge can combine incompatible record changes. The standard's lease and divergence requirements are intended to reduce that risk; they are not evidence of implemented synchronization or measured reductions in corruption.
At a glance
- Held during
- standard: store mutations CLI lease: record and init
- Contains
schemaholderoperationacquired_at- Enforced by
- record acquisition
opf doctorshape validation; cross-system reconciliation planned
What it protects
Concurrency safety that is honest about its bounds
The intended benefit is fewer concurrent-write conflicts. The standard discloses a propagation window, and the reference initializer supplies no concurrency serialization.