sow log
Every write command inside a Repository commits an application-level Operation to that Repository’s
SQLite database before it produces any external file side effect. That record is what makes crash
recovery possible — and once the Operation reaches a terminal state, the same record is your audit
trail. sow log reads it.
Synopsis
Operation lifecycle
Understanding the state field is most of understanding the log:
| State | Meaning |
|---|---|
planned |
Command, arguments, targets and intended actions are durably recorded |
staged |
New packages/metadata written to temporary locations and verified |
applied |
Desired state and required private pending payloads committed |
built |
The complete static Generation has been switched in |
done |
Terminal — a normal successful command |
done_dirty |
Terminal — --skip was given, so the public tree deliberately stayed behind |
failed |
Terminal — the operation failed before applied, nothing was committed |
rolled_back |
Terminal — a post-applied failure the process could safely undo |
recovering |
Non-terminal; the next write command must complete or roll it back |
Workspace lifecycle commands (init, repo new, repo rm) use the Workspace file journal instead
and do not appear in a Repository’s SQLite log. dist new/dist rm do appear — the Repository
database already exists at that point.
sow log
With no argument, prints the 50 most recent Operations, newest first.
Output excerpt, one Operation object from the operations array:
payload_json records the intent — including config_sha256, the digest of the configuration in
force, and manifest_sha256 for the resulting Generation. result_json records the outcome. A
failed Operation additionally carries error_class and error_message:
| Flag | Description | Default |
|---|---|---|
-C, --workdir DIR |
Workspace discovery start directory | current directory |
-r, --repo NAME |
Select a repository | selection rules |
-d, --dist NAME |
Show only Operations touching this Dist | all |
--json |
Emit the versioned JSON envelope | false |
One Operation in detail
Pass an Operation ID to get its full state transitions, timing, packages, memberships and file actions.
Output excerpt:
The files array uses the same phase vocabulary as
sow changes: payload, metadata, pointer, delete.
Build Operations also contain progress events. They keep the current state and put a
versioned object in detail_json:
The phases are rendering, promoting_payload, publishing_dists,
normalizing_public_tree, and finalizing. A progress row is durable audit data but does
not advance the recovery state machine or force its own SQLite checkpoint.
Filtering by Dist
-d restricts the listing to Operations that touched that Dist — useful when one Repository serves
several distributions:
sow log export
Writes terminal Operations as JSONL — one complete Operation detail record per line — for archival or ingestion into a log pipeline.
Omit FILE, or pass -, to write to stdout:
| Flag | Description | Default |
|---|---|---|
-C, --workdir DIR |
Workspace discovery start directory | current directory |
-r, --repo NAME |
Select a repository | selection rules |
-d, --dist NAME |
Export only Operations touching this Dist | all |
export has no --json; JSONL is its output format.
It refuses to clobber
An existing target is a rejection, never an overwrite — an audit export must not silently destroy a previous one:
export also refuses a target whose parent is not a real directory — a symlink, or a directory that
does not exist:
On macOS /tmp is a symlink to /private/tmp, so that refusal fires there. Write to an explicit
real path instead.
sow log prune
Deletes eligible terminal audit records older than BEFORE and safely compacts the database.
The absolute timestamp is echoed back so the local-timezone interpretation is never ambiguous.
| Flag | Description | Default |
|---|---|---|
-C, --workdir DIR |
Workspace discovery start directory | current directory |
-r, --repo NAME |
Select a repository | selection rules |
-T, --timeout DUR |
Maximum lock wait; 0 waits indefinitely |
0 |
-N, --no-wait |
Fail immediately when the lock is held | false |
--json |
Emit the versioned JSON envelope | false |
prune operates at Repository level and does not accept -d — pruning half an Operation would
produce a meaningless record.
BEFORE syntax
BEFORE is an ISO-8601 date YYYY-MM-DD, interpreted as local midnight, or an RFC 3339 timestamp
with a timezone.
What prune never deletes
prune is conservative by construction. It never removes:
- a non-terminal Operation;
- a record still required for recovery;
- current Package or Membership state;
- a Built Generation or its Changeset.
The pruned counter tells you exactly how many records were eligible, which is normally fewer than
the number of Operations older than the cutoff. Log and Changeset live in the same SQLite database,
but they follow different retention rules.
Examples
Investigate the most recent write:
List everything that failed:
Archive and shrink, monthly:
Which Operation last touched a Dist:
Exit codes
| Command | Code | Trigger |
|---|---|---|
log |
0 |
Records printed, including an empty ledger |
log |
2 |
Usage error (including a non-numeric Operation ID), Workspace not found, or ambiguous selection |
log |
5 |
State database unreadable |
log |
6 |
The given Operation ID does not exist |
log export |
0 |
Export written |
log export |
1 |
I/O failure writing the target, or the parent is not a real directory |
log export |
2 |
Usage error or ambiguous selection |
log export |
6 |
Target already exists |
log prune |
0 |
Prune completed, including pruning nothing |
log prune |
2 |
Malformed BEFORE, -d given, or ambiguous selection |
log prune |
4 |
Repository lock held and --no-wait given or --timeout expired |
log prune |
5 |
Integrity or recovery error |
See also
- Observability & Audit — how
logfits withstatus,checkandchanges - Transactions & Recovery — the journal that the log records
- sow changes — the physical counterpart to a semantic Operation
- JSON Output — the full log result schema