Amend A9 with state-change log conventions #4
@@ -283,6 +283,40 @@ Requirements:
|
|||||||
Requirements: structured logs to journald / external log stack, **not** kept
|
Requirements: structured logs to journald / external log stack, **not** kept
|
||||||
in-container. Every gate crossing, tool call, and escalation is logged.
|
in-container. Every gate crossing, tool call, and escalation is logged.
|
||||||
|
|
||||||
|
**State-change log conventions.** Every durable mutation of agent state emits
|
||||||
|
exactly one structured log event, so problems can be diagnosed after the fact
|
||||||
|
by replaying the operational trail:
|
||||||
|
|
||||||
|
- **Emission is owned by the state store.** The log line is written by the same
|
||||||
|
code path that performs the durable write, immediately after the commit
|
||||||
|
returns — a state-change line exists iff the change hit disk. Callers supply
|
||||||
|
the *cause*; no other layer logs durable mutations, so the trail cannot drift
|
||||||
|
from what was persisted.
|
||||||
|
- **Format: one JSON object per line**, with a fixed envelope on every event:
|
||||||
|
- `ts` — UTC ISO-8601 timestamp
|
||||||
|
- `agent` — `nisse-dev` | `nisse-ops`
|
||||||
|
- `event` — dotted type from the taxonomy below
|
||||||
|
- `task_id` — correlation ID for the enclosing unit of work, minted when the
|
||||||
|
unit starts (`use <project>`, milestone start, ticket pickup) and threaded
|
||||||
|
through every event it causes; `null` only outside any unit (e.g. boot).
|
||||||
|
- `cause` — what triggered the mutation: operator command, approval
|
||||||
|
(`rev-N` + channel), escalation trigger, reconciliation verdict, or crash
|
||||||
|
recovery.
|
||||||
|
- **Event taxonomy** (extended as components are built; names are never reused
|
||||||
|
or renamed):
|
||||||
|
|
||||||
|
| Event | Event-specific fields |
|
||||||
|
|---|---|
|
||||||
|
| `state.transition` | `from`, `to`, `project` |
|
||||||
|
| `intent.begin` / `intent.commit` / `intent.abort` | `intent_id`, `kind` |
|
||||||
|
| `gate.open` / `gate.approve` / `gate.reject` | `gate`, `rev`, `channel` |
|
||||||
|
| `boot.reconcile` | `action`, per-intent verdicts |
|
||||||
|
| `schema.migrate` | `from_version`, `to_version` |
|
||||||
|
|
||||||
|
- **Logs are diagnostic, never load-bearing.** Nothing reads logs back to
|
||||||
|
derive state — the state store (A2) is the sole source of truth, the same
|
||||||
|
rule that keeps Matrix room history (A1) non-authoritative.
|
||||||
|
|
||||||
### A10. Canonical Transcript Schema
|
### A10. Canonical Transcript Schema
|
||||||
|
|
||||||
The durable record is a **canonical event log** in SQLite, not a provider-shaped
|
The durable record is a **canonical event log** in SQLite, not a provider-shaped
|
||||||
|
|||||||
Reference in new issue
Block a user