effect-ledger · git:20260925.f38b8f5 · 2026-09-25 · sha256 687997bf6b05a798
effect-ledger git:20260925.f38b8f5A
Immutable. This exact content never changes and is served at /api/v1/blob/687997bf6b05a798.
---
namespace: aiwg
name: effect-ledger
platforms: [all]
description: Record an effect, sign an effect, reconcile an effect or check "did this PR merge" through the signed AIWG effect ledger, using one aiwg effect command with scriptable exit codes
---
# Effect Ledger
Record and reconcile side effects (tracker comments, PR merges, issue closes,
git commits and tags, files, decision receipts) in the signed AIWG effect
ledger with the `aiwg effect` CLI. The ledger proves what AIWG recorded and
what a verifier observed. It never authorizes an effect and never replays one:
an operator decision authorizes, the ledger proves.
## Triggers
- "record an effect" → `aiwg effect record`
- "sign an effect" → `aiwg effect record` (signed intent and completed)
- "reconcile effect" → `aiwg effect reconcile`
- "did this PR merge" → `aiwg effect reconcile --kind tracker.pr.merged`, or
`aiwg effect probe --kind tracker.pr.merged --target gitea:owner/repo#34`
when no merge intent was recorded (read-only, writes nothing)
- "did we already post this comment" → `aiwg effect lookup` before posting
- "verify the effect ledger" → `aiwg effect verify` (add
`--with-decisions <audit.jsonl>` to check #1567 operator-decision links)
- "the effect ledger lock is stuck" → `aiwg effect recover-lock` (operator only)
## When to record
Record every externally visible effect that a retry or a crash could repeat:
cycle and closing comments, merges, issue closes, tags, release files, and
decision receipts. Do not record read-only queries.
## Process
1. **Name the effect.** Pick the kind and target, and the causal context that
makes it unique. For a cycle comment:
`--kind tracker.comment --target gitea:owner/repo#12 --issue 12 --action cycle-comment --cycle 1`.
`aiwg effect id <identity>` prints the effect ID.
2. **Check before acting.** Run `aiwg effect lookup <identity>`. Exit 0 means
the effect is already present: do not repeat it. Exit 4 means an earlier
attempt has no outcome: run `aiwg effect reconcile` first.
3. **Carry the ID into the target** wherever the target allows it: a hidden
`<!-- aiwg-effect: <effect-id> -->` line in a comment body, or an
`Effect-Id: <effect-id>` git trailer. Verifiers use the marker to prove the
effect happened.
4. **Perform the effect**, then record and sign it in one call:
```bash
aiwg effect record --kind tracker.comment --target gitea:owner/repo#12 \
--issue 12 --action cycle-comment --cycle 1 --payload-file comment.md
```
`record` writes the signed intent, runs the kind's verifier, and appends
`completed` when the verifier reports `present`. Repeating it with the same
payload exits 0 with `"idempotent":true`. Use `--unverified` only when no
verifier can see the target, and say so in your report.
5. **Reconcile uncertain effects.** `aiwg effect reconcile <effect-id>` (or the
same identity flags) asks the verifier again and appends a `reconciled`
record each time. For "did this PR merge", once the merge intent is
recorded: `aiwg effect reconcile --kind tracker.pr.merged --target gitea:owner/repo#34`.
Reconciling an effect with no recorded intent is a usage error (exit 2);
record the intent first with `aiwg effect intent` or `aiwg effect record`,
or use `aiwg effect probe <identity>` for an ad-hoc check that records
nothing (same exit codes 0, 3 and 4).
6. **Link the authorizing decision** when an operator approved the effect:
`--link operatorDecisionEventId=sha256:<hex>` (and
`operatorDecisionRecordHash`) on `intent` or `record`.
## Exit codes
| Code | Meaning | What to do |
|---|---|---|
| 0 | present or recorded | Continue |
| 3 | absent | The target does not show the effect. Do not assume it is safe to replay; follow the workflow's own policy |
| 4 | unknown | Stop and escalate. Never replay on unknown |
| 5 | conflict | The same effect ID was recorded with a different payload. Stop |
| 6 | integrity failure | The ledger failed verification. Stop and report |
| 2 / 1 / 7 | usage / internal / artifact root unavailable | Fix the command or the artifact root; nothing was written |
## Rules
- Output is JSON by default and every document has a `schema` member; add
`--format text` only for people.
- Never pass raw bodies, secrets or tokens as flags. Payloads are digested from
`--payload-file` or given as `--payload-digest`.
- The ledger key lives in the host secret service. `aiwg effect keys list`
shows key IDs and public keys only; `keys init` and `keys rotate` are
operator actions.
- `aiwg effect recover-lock --lock <name> --authorize` is an operator action.
It refuses live, reused or unverifiable lock owners and records the recovery
in the ledger. Never run it without the operator's explicit approval.
## References
- @$AIWG_ROOT/docs/contracts/effect-ledger.v1.md — contract, exit codes and verifier rules
- @$AIWG_ROOT/docs/cli/reference.md — `aiwg effect` command reference