Concepts
codev keeps three kinds of records in the repository: specs say what the system does, decisions say why it is built the way it is, and changes are the work in progress that modifies both.
_codev/
├── config.yaml # project configuration
├── specs/ # behavior contracts — WHAT the system does
├── decisions/ # architecture decisions — WHY it is built this way
├── changes/ # work in progress, which modifies the two above
│ ├── <name>/ # proposal.md, design.md, tasks.md, specs/** (deltas)
│ └── archive/ # finished changes, dated
├── schemas/ # custom workflow schemas (optional)
└── codev.lock # pinned inherited git sources (when used)
codev finds this folder by walking up from the current directory, so every command works from any subdirectory of the project.
Capability
A capability is a unit of observable behavior the system offers — user
authentication, the theme setting, the validate command. Capabilities are
identified by a path of kebab-case segments, such as ui/theme or
identity/user-auth, which is also where their spec lives. Group them the way
your domain is organized, not the way your code is.
Spec
The main spec of a capability lives at _codev/specs/<capability>/spec.md. It
has a ## Purpose — one or two sentences on what the capability is for — and
a ## Requirements section:
# Theme Specification
## Purpose
Let users choose the color theme of the interface.
## Requirements
### Requirement: Theme follows the system preference by default
The application SHALL render with the operating system's color scheme until the user picks a theme.
#### Scenario: No theme chosen yet
- **GIVEN** a user who has never changed the theme setting
- **WHEN** their operating system is set to dark mode
- **THEN** the application renders with the dark theme
Each requirement is normative (it uses SHALL or MUST, or DOIT or
DOIVENT in a French spec) and has at least one
scenario describing observable behavior. A spec describes behavior, never
implementation: if the code can change without the behavior changing, the
spec should not change either.
You never edit a main spec directly. It changes only when a change is synced or archived, which is what makes its history readable.
Change
A change is a folder _codev/changes/<name>/ that carries one evolution of
the system: a proposal, spec deltas, a design and a task list, plus a
change.yaml holding its metadata. Which artifacts a change has is defined by
its schema; the default spec-driven schema is
described in The workflow.
A change is active while it lives in _codev/changes/<name>/. Archiving
moves it to _codev/changes/archive/<YYYY-MM-DD>-<name>/, where it becomes a
record of why and how the specs changed.
Delta
A delta is the part of a change that modifies a spec. It lives at
_codev/changes/<name>/specs/<capability>/spec.md — the same capability path
as the main spec it targets — and is organized in up to four operations:
| Section | Effect when merged |
|---|---|
## ADDED Requirements | Appends the requirements to the main spec |
## MODIFIED Requirements | Replaces the requirement of the same name, in place |
## REMOVED Requirements | Deletes the requirement, with a Reason and a Migration |
## RENAMED Requirements | Changes a requirement’s title, leaving its body untouched |
Here is a delta that modifies one requirement and renames another:
## MODIFIED Requirements
### Requirement: Theme follows the system preference by default
The application SHALL render with the operating system's color scheme until the user picks a theme, and SHALL switch live when that preference changes.
#### Scenario: No theme chosen yet
- **GIVEN** a user who has never changed the theme setting
- **WHEN** their operating system is set to dark mode
- **THEN** the application renders with the dark theme
## RENAMED Requirements
- FROM: The chosen theme is remembered
- TO: The chosen theme follows the user
A MODIFIED block replaces the whole requirement, so copy the entire block
from the main spec — scenarios included — before editing it. Content you leave
out is lost at merge time. If you are adding behavior without changing
existing behavior, use ADDED.
The merge touches only the requirements named in the delta. Everything else in the main spec — other requirements, free-form sections, comments — stays as it was.
A delta for a new capability starts with its own ## Purpose; merging it
creates the main spec. Removing a capability entirely — a REMOVED delta that
empties a spec — requires retire_capabilities: true in change.yaml,
because the deletion can only be undone from git.
The exact syntax is in File formats.
Decision
A decision, or ADR (architecture decision record), is a file
_codev/decisions/NNNN-<slug>.md that records an architectural choice: its
context, the decision, its consequences and the alternatives considered.
codev decision new "Use PostgreSQL for persistence"
codev decision accept 0001
A decision has one of five statuses: accepted, superseded, proposed,
deprecated or rejected. Every command that creates a decision —
codev decision new, supersede, deviate and
promote — creates it proposed, so you can write it freely;
codev decision accept makes it accepted once its text is final. Accepting
is the only step that makes a decision take effect: a proposed decision
supersedes nothing and deviates from nothing yet. A decision is in effect
when it is accepted and nothing supersedes it. The decisions in effect are handed to the agent
whenever it writes a design.md, so designs follow them instead of
re-debating them.
Each decision has a short id (0007) and a qualified id that names its
origin: project/0007 for a decision of the project itself,
path:~/shared/0100 or git:git@github.com:acme/shared.git/0100 for a
decision inherited from another repository.
Seal
An accepted decision is immutable. When a decision becomes accepted through a
codev decision command — accept, or new --status accepted — codev
records a SHA-256 hash of the decision’s body in _codev/decisions/seal.yaml; codev decision seal does the same for a
decision you accepted by hand. codev validate compares the body of
every local accepted or superseded decision with its hash, and reports an
edit as a decision_seal_mismatch error and a missing seal as a
decision_unsealed warning. A proposed decision is not sealed.
The frontmatter is not covered by the seal, so a status can move from
accepted to superseded without breaking it.
Note Seal a decision when its text is final: write the
proposeddecision first, then runcodev decision accept <ID>, which sets the status and records the seal in one step. If you have edited a sealed decision on purpose,codev decision seal <ID> --forcerecords the new body; to change what an accepted decision says, supersede it instead.
Supersession
To change a decision, supersede it rather than editing it:
codev decision supersede 0001 "Use SQLite for persistence"
codev creates a new proposed decision whose frontmatter lists
supersedes: ["0001"], and leaves 0001 untouched: it stays accepted, and in
effect, while you write the new one. Accepting the new decision marks 0001 as
superseded in the same step:
codev decision accept 0002
The old body stays exactly as it was, so its seal stays valid and the history
of the reasoning is preserved. Only an accepted decision can be superseded:
if another decision superseded 0001 in the meantime, codev decision accept
refuses with predecessor_not_accepted and writes nothing.
Deviation
An inherited decision cannot be superseded from your project, because you cannot write to its source. Instead, record a local deviation:
codev decision deviate path:~/shared/0100 "Services log in logfmt"
This creates a local proposed decision with deviates_from pointing at the
inherited one. The deviation takes effect when you accept it with
codev decision accept: the inherited decision then stays visible in
codev decision list, but it is no longer in effect for your project and is no
longer handed to the agent when writing designs. Until then, the inherited
decision is still in effect.
Promotion
A design often contains a decision that deserves to outlive the change. Write
it in design.md as a ### Decision: <title> block, then promote it:
codev decision promote add-audit-log "Append-only audit table"
codev creates a proposed ADR whose ## Decision section is the block’s
content, verbatim, and replaces the block’s body with a reference to the new
ADR. Review it and split the promoted text into the ADR’s sections, then accept
it with codev decision accept, which seals it — ideally before archiving the
change.
Inherited source
A project can inherit read-only material from other codev repositories — a
shared folder on your machine (path:) or a git repository pinned to a commit
(git:). Each source contributes its context:, its rules: and its
decisions. Nothing executable is ever inherited, and nothing is read from a
floating branch: git sources are pinned in _codev/codev.lock. See
Inherited sources.
Schema
A schema defines which artifacts a change has, what each one requires, and the
instructions and templates the agent follows to write them. codev embeds one
schema, spec-driven. A project can define its own in _codev/schemas/. See
Custom schemas.
In spec-driven, each instruction opens with the role that owns the
artifact and its “Done when” criteria: product owner for the proposal (why
and what), QA analyst for the specs (observable behavior), architect for the
design (how), tech lead for the tasks (sequencing and verification).