Concepts
Git-first
Releaseledger is git-first. Git tags and commit ranges define the shipped change
set. The canonical evidence of what shipped is git rev-list --reverse --topo-order <base>..<head>
โ every commit reachable from the release target and absent from the previous release.
Agent Skill source and discovery
The repository-maintained source skill is skills/releaseledger/SKILL.md. It is a canonical source file and legacy compatibility location, not a package-bundled skill that automatically becomes visible to an external agent.
Install the skill for agents at .agents/skills/releaseledger/SKILL.md in a project or at ~/.agents/skills/releaseledger/SKILL.md for the current user. Releaseledger also recognizes supported OpenCode, GitHub Copilot and VS Code, Claude, Gemini, Cursor, and Codex compatibility roots, including an injectable administrator equivalent of /etc/codex/skills for diagnostics.
Skill diagnostics use a bounded filesystem registry. They inspect all known local copies, validate the required name, description, and integer protocol metadata, and report conflicts instead of assuming that the first existing path is active. Host runtimes have different precedence rules, so Releaseledger does not claim to reproduce universal activation precedence.
Git tag ownership policy
Git tags remain evidence of shipped releases. The [git] key tag_creation defaults to local and accepts local or external. With tag_creation = "external", an external publication workflow owns tag creation. This changes remediation ownership only; release check --phase published still fails until the externally created tag is visible.
Taskledger, issue trackers, and PR descriptions are optional provenance that enrich curated entries, but releaseledger works correctly with only git.
Source refs
A source ref is a coverage identity. Two kinds are accepted:
Global refs (taskledger, GitHub, etc.):
tl:task-0006,github:pr-42. Canonicalized by ledgercore.Git commit refs:
git:<7-to-40 hex sha>. The primary evidence type for git-first workflows.
A git-range:*, git-tag:*, or git-branch:* ref is a non-coverable
range marker โ useful as release metadata but never creating a missing-coverage row.
Pinned release snapshot
Git-backed releases store both symbolic refs and the resolved commit SHAs. The
resolved SHAs are the immutable snapshot used by default for later git-backed
commands (git range, git scaffold, audit init, review, release check,
strict build coverage). This prevents a moving branch head from silently adding
new commits to an in-progress release.
Resolve HEAD once when attaching the range. A new commit belongs to the
release only after an explicit refresh.
Release
A release is a versioned record stored as release.md with YAML front matter
and an optional Markdown body. It tracks status, previous version, release date,
source boundary, source refs, and changelog file metadata.
Release statuses are:
planneddraftcandidatereleasedyankedcanceled
canceled means the release was never shipped: it is excluded from
previous-version inference and not built into public changelogs by default.
Canceled releases may carry cancel_reason and superseded_by metadata
and remain visible in release list as an audit tombstone.
Release identity compares v1.2.3 and 1.2.3 as one external release while
preserving exact stored version paths and concrete predecessor references.
Unique aliases resolve at the service boundary; conflicting aliases are
reported explicitly.
Version correction is a domain operation across the release identity, bundle,
entry ownership, predecessor links, audit sheet, changelog identity, and
indexes. release rename --dry-run previews those surfaces. Use
release restore --from-tag when a canceled release was later shipped, and
use release rename --replace-canceled-target --reason TEXT when a correct
canceled bundle must displace an obsolete canceled alias. Changelog mutation
remains explicit with --rename-changelog-section.
Entry
An entry is one release-note item stored under
releases/<version>/entries/entry-NNNN.md. Entries are grouped by kind for
changelog rendering.
Entry kinds are:
addedchangedfixedremoveddeprecatedsecuritydocsqualityinternal
documentation and doc are accepted aliases for docs.
Entry statuses are draft, accepted, and rejected. Changelog builds
include accepted entries by default.
Event
Events are append-only operation rows. They do not store wall-clock timestamps or before/after deltas. Releaseledger relies on git history for chronological review and on per-record revisions for validation.
Commit audit sheet
A commit audit sheet is a per-release review artifact that maps every commit in the selected git range to a reviewer decision and, when applicable, to a release entry. It is evidence state, not changelog prose.
The sheet exists to prevent release notes from being generated from commit subjects. Each row records the commit SHA, inspected paths, reviewer-observed behavior, public/internal impact, decision, and target release entry. Public changelog entries are written from reviewed behavior, API/docs impact, changed paths, tests, and diff evidence. Commit subjects are evidence-only and must not be copied or mechanically transformed into release summaries.
Decisions are needs_review, accepted, grouped, internal, and
rejected. public_impact values are public, docs, internal, none,
and unknown.
Audit validation is phase-aware:
evidencevalidates inspection completeness and row evidence quality without requiring entries.completeadditionally validates accepted entry coverage, internal coverage when requested, and the commit-subject summary guard.
This concept keeps Git as the canonical source of shipped changes while making the human or agent review work durable and auditable.
Coverage and audit accounting
Raw entry coverage records whether an entry directly carries a source ref. The release gate additionally accounts for the audit decision on Git commits:
acceptedandgroupedrequire an accepted public entry.internalis satisfied by complete inspected audit evidence in public mode; with--include-internal, it requires an accepted internal entry.rejectedis satisfied by complete inspected rejection evidence.needs_review, missing rows, and incomplete evidence are unresolved and block.
This separation keeps internal commits from being attached to unrelated public
notes merely to satisfy a counter. Coverage JSON retains the raw status and
adds audit_decision, coverage_requirement, gate_satisfied, and
accounted_as.
Release-check phases
release check --phase current evaluates persisted state with the compatible
default behavior. --phase finalize --released-at DATE asks whether a planned,
draft, or candidate release is ready to transition to released and does not
require a tag. --phase published checks post-release consistency, including a
release date, matching Git tag when Git is active, changelog presence, and clean
reconciliation. Human output renders every gate included in the final result;
JSON exposes stable failed_checks and actionable next_actions.
release prepare is preparation-only and never finalizes a release. Its JSON result contains ordered next_actions with command text, mutation metadata, and manual-action markers; human output renders the same list. Without a proposed date, the generated current-release changelog dry run includes --unreleased.
Versioning
Release and entry files contain versioning.schema_version and a positive
versioning.revision. New records start at revision 1, and the revision
increases by exactly one whenever that record file meaningfully changes.
Planned versus released
A dated planned / draft / candidate release is intentionally treated as a
consistency warning or strict failure in review/check flows, because default
public full builds include only released releases. Finalize a shipped release
explicitly before the final public build.
Index
Releaseledger rebuilds indexes/releases.json and indexes/entries.json
after mutations. Indexes are derived state and should remain deterministic.
Global refs
External provenance is recorded as caller-supplied global refs, for example
tl:task-0103. Releaseledger stores these refs but does not resolve or
validate external ledger state.