49 KiB
Audit Event Taxonomy
Event names MUST match this table exactly. Do not invent new event types. For stage completions, ALWAYS use STAGE_COMPLETED — do not substitute stage-specific names like "Requirements Analysis Complete" or "Code Generated".
Stage lifecycle is report-owned: the conductor requests gate, revision,
completion, and skip outcomes through tools/aidlc-orchestrate.ts report.
The state tool entries below are the engine's internal atomic emitters, not
commands a stage or conductor invokes directly.
See
docs/reference/12-state-machine.mdfor the state transitions that emit each event. Events marked✓are MANDATORY and asserted bytests/feature/t48-audit-event-emitters.sh.
Naming Convention
All event names follow SUBJECT_PAST_VERB — every event answers "what happened?"
Emitter-Owned Fields
The structured renderer writes exactly one Timestamp and one Event line per
block; callers must not supply either field. For compatibility, the generic
audit append --field Timestamp=... form is still accepted, but its value is
intentionally ignored. Historical shards are not rewritten: readers that parse
whole files must split on --- and use the first timestamp in each block, or
deduplicate timestamp fields produced by older versions.
Event Registry (95 events, 23 categories)
Workflow Lifecycle (4 events)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
✓ WORKFLOW_STARTED |
Scope determined, workflow begins | Timestamp, Scope, Request; optional Source Baseline (sha256:<listing-hash> or unbindable) |
tools/aidlc-utility.ts intent-create |
✓ WORKFLOW_COMPLETED |
All in-scope stages done | Timestamp, Scope, Details | tools/aidlc-state.ts complete-workflow |
✓ WORKFLOW_PARKED |
Workflow parked mid-flow for a later session (no stage advanced) | Timestamp, Stage | tools/aidlc-state.ts park |
✓ WORKFLOW_UNPARKED |
Park marker cleared on explicit --resume re-entry |
Timestamp | tools/aidlc-state.ts unpark |
Phase Lifecycle (4 events)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
✓ PHASE_STARTED |
Phase begins (first in-scope stage about to run) | Timestamp, Phase, Stage count, Scope | tools/aidlc-utility.ts intent-create (Init phase), tools/aidlc-state.ts advance (phase boundary) |
✓ PHASE_COMPLETED |
Crossed a phase boundary | Timestamp, From phase, To phase, Stages completed | tools/aidlc-state.ts advance, tools/aidlc-state.ts complete-workflow |
PHASE_VERIFIED |
Traceability check at boundary | Timestamp, Phase boundary, Pass/fail, Issues | tools/aidlc-state.ts advance, tools/aidlc-state.ts complete-workflow |
PHASE_SKIPPED |
Scope excludes phase | Timestamp, Phase, Scope, Reason | tools/aidlc-utility.ts intent-create (per-phase scope eval) |
Stage Lifecycle (6 events)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
✓ STAGE_STARTED |
Stage enters [-] Active |
Timestamp, Stage, Agent; optional Source Baseline when the entered stage declares workspace_requires |
tools/aidlc-state.ts advance, tools/aidlc-utility.ts intent-create (init stages) |
STAGE_AWAITING_APPROVAL |
Stage enters [?] (gate open) |
Timestamp, Stage, Artifacts, optional Recovered=true (backfilled gate row) or Revalidated=true (an already-open gate consumed a blocking-sensor override); a blocking-sensor override also carries Blocking Sensor Override, Blocking Sensor IDs, optional Blocking Sensor Detail Paths, and Blocking Sensor Reasons. Its authorization is the preceding exact DECISION_RECORDED → HUMAN_TURN → QUESTION_ANSWERED pair. |
tools/aidlc-state.ts gate-start (organic, --recovered backfill, or override revalidation), tools/aidlc-state.ts revise (gate re-entry), tools/aidlc-state.ts approve (backstop re-entry after its opening guards pass) |
STAGE_REVISING |
Stage enters [R] (user rejected gate) |
Timestamp, Stage, Revision count, Feedback, optional Recovered=true (backfilled by the approve-time revision backstop) |
tools/aidlc-state.ts reject, tools/aidlc-state.ts approve (backstop backfill) |
✓ STAGE_COMPLETED |
Stage finishes ([x]) |
Timestamp, Stage, Details, Artifacts | tools/aidlc-state.ts approve (gated stages; also auto-advances to next), tools/aidlc-state.ts advance (non-gated stages), tools/aidlc-utility.ts intent-create (init stages) |
STAGE_JUMPED |
Forward/backward/redo jump target reached | Timestamp, Direction, Source, Target, Scope; optional Source Baseline. Backward jumps also carry JSON arrays for Changed Upstream Artifacts, Invalidated Downstream Artifacts, and Invalidated Downstream Reviews | tools/aidlc-jump.ts execute |
STAGE_SKIPPED |
Current stage reports a justified skip, or a jump skips it ([S]) |
Timestamp, Stage, Reason | tools/aidlc-state.ts skip (internally routed by aidlc-orchestrate.ts report --result skipped), tools/aidlc-jump.ts execute |
Session Events (5 events — hook-owned, independent of workflow lifecycle)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
SESSION_STARTED |
Fresh Claude Code session begins (source=startup or clear) | Timestamp, Source | hooks/aidlc-session-start.ts |
SESSION_RESUMED |
Existing Claude Code session resumed (source=resume) | Timestamp, Source | hooks/aidlc-session-start.ts |
SESSION_COMPACTED |
Context compaction occurred | Timestamp, Current Stage, State Validity | hooks/aidlc-validate-state.ts (PreCompact) |
SESSION_ENDED |
Claude Code session terminates | Timestamp, Reason | hooks/aidlc-session-end.ts |
HUMAN_TURN |
A supported prompt-submit or answered-widget seam was observed (the approval/interview gate requires one since the last gate resolution); omitted when the driver declares AIDLC_UNATTENDED=1 |
Timestamp | hooks/aidlc-record-human-turn.ts (UserPromptSubmit + PostToolUse AskUserQuestion) + the per-harness prompt-submit adapters |
HUMAN_TURN is chronological presence evidence, not authenticated decision
content. The --user-input, --feedback, and --details fields recorded by
authority-bearing tools are caller-supplied prose. A narrow defense-in-depth
tripwire rejects recognized explicit conductor/model self-attribution, but
unlabelled, paraphrased, localized, or otherwise unrecognized wording remains
indistinguishable from human-authored text. AIDLC_SKIP_HUMAN_PRESENCE_GUARD=1
also disables that tripwire for deterministic recovery/tests. Audit shards are
operational evidence, not a tamper-proof human-authorship boundary.
Initialization Events (3 events — fire IN ADDITION TO STAGE_COMPLETED)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
WORKSPACE_SCAFFOLDED |
Directory tree created | Timestamp, Details | tools/aidlc-utility.ts handleInit |
WORKSPACE_SCANNED |
Workspace detection done | Timestamp, Project type, Details | tools/aidlc-utility.ts handleInit |
WORKSPACE_INITIALISED |
State file created | Timestamp, Details | tools/aidlc-utility.ts handleInit |
Navigation Events (7 events)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
SCOPE_CHANGED |
--scope changed existing scope |
Timestamp, Old scope, New scope | tools/aidlc-utility.ts |
PLUGIN_SELECTION_CHANGED |
select-plugins changed enabled plugins |
Timestamp, Previous Selection, New Selection | tools/aidlc-utility.ts select-plugins |
DEPTH_CHANGED |
--depth changed depth level |
Timestamp, Old depth, New depth | tools/aidlc-utility.ts |
TEST_STRATEGY_CHANGED |
--test-strategy changed test strategy |
Timestamp, Old strategy, New strategy | tools/aidlc-utility.ts |
REVIEW_CLASS_CHANGED |
--review changed the per-run review override |
Timestamp, Old Override, New Override | tools/aidlc-utility.ts |
SCOPE_DETECTED |
Auto-detected from freeform text | Timestamp, Detected scope, Input text, Source, Matched keywords (optional; present when Source=keyword) |
tools/aidlc-utility.ts detect-scope |
RECOMPOSED |
The adaptive composer re-shaped a running workflow's pending stages (suffix flips via recompose) |
Timestamp, Scope, Stages skipped, Stages added, Stages in Scope | tools/aidlc-utility.ts recompose |
Change Control Events (2 events)
Change Control is one per-intent setting, strict or relaxed, that decides what a governed checkpoint does when an input changed after the human approved or confirmed something. Both rows are provenance emitted through the library by their owners; the public audit CLI refuses them.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
CHANGE_CONTROL_SET |
The intent's Change Control value moved: the change-control <strict|relaxed> verb (from the --change-control flag or a plain-chat request) rewrote the state line, a scope-change carried a scope-supplied value to the new scope's default, or a governed checkpoint observed that a memory layer edit changed the effective value for this running intent |
Timestamp, Old Value, New Value, Source (you, scope <name>, or <layer>.md) |
tools/aidlc-lib.ts (recordChangeControlSet for the verb and scope-change, governedChangeControl for the checkpoints) |
CHANGE_ACCEPTED |
A governed checkpoint found that an input changed after a human approval or confirmation and, under relaxed, recorded the change and continued instead of refusing. Written once per distinct change: the same Recorded and Current values for the same Checkpoint, Stage, and Unit never produce a second row |
Timestamp, Stage, optional Unit, Checkpoint (plan-approval, review-receipt, summary-confirmation), Changed (a bounded path list or (paths unavailable)), Recorded, Current, Details (the one line the human hears) |
tools/aidlc-lib.ts (recordAcceptedChanges, called by the checkpoint owners: aidlc-log.ts decision / answer / review, aidlc-testing-posture.ts begin, aidlc-state.ts gate and completion checks, the plan-approval guard hook) |
Interaction Events (11 events)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
DECISION_RECORDED |
Before presenting a non-gate structured question, to record the options shown. Consolidated-summary prompts also carry checkpoint identity | Timestamp, Stage, Decision, Options; optional Checkpoint, Questions File, Unit, Attempt Generation, Workflow | tools/aidlc-log.ts decision |
GATE_APPROVED |
Human approved at gate | Timestamp, Stage, User Input; optional Review Finding Dispositions (versioned JSON mapping every current New/Unresolved review finding to Accepted risk, keyed by review artifact, finding ID, and finding-content fingerprint), Unit, Gate Scope, Gate Stages, Attempt Generation (team Unit gates); Unit merge gates also carry Pinned OID, Strategy, Target branch | tools/aidlc-state.ts approve, tools/aidlc-unit.ts gate |
GATE_REJECTED |
Human requested changes | Timestamp, Stage, Feedback; optional Review Finding Dispositions (versioned JSON for findings the human explicitly rejected with an exact reason), Recovered=true (backfilled by the approve-time revision backstop), Prior Accepted Source Fingerprint (the prior attempt's validated final swarm aggregate; never a replacement completion baseline), Unit, Gate Scope, Gate Stages, Attempt Generation (team Unit gates); Unit merge gates also carry Pinned OID, Strategy, Target branch |
tools/aidlc-state.ts reject, tools/aidlc-state.ts approve (backstop backfill), tools/aidlc-unit.ts gate |
QUESTION_ANSWERED |
Non-gate question answered by user | Timestamp, Stage, Details; optional Unit, Attempt Generation | tools/aidlc-log.ts answer |
SUMMARY_CONFIRMATION_RECORDED |
Consolidated-summary choice recorded after the matching prompt and a fresh human turn; reserved from the public audit CLI | Timestamp, Stage, Details, Checkpoint, Questions File, Questions SHA-256, Hash Scope (required on new receipts; legacy rows may omit it), Summary Authorization Id (on a Looks correct receipt: sha256 over the attempt, stage, Unit, workflow, questions path, confirmed-content hash, and choice; identical confirmations mint the same id, changed answers a new one; legacy rows omit it); optional Unit, Workflow |
tools/aidlc-log.ts answer --checkpoint summary-confirmation |
PLAN_APPROVAL_RECORDED |
Provenance that Code Generation consumed a protected Plan Approval challenge/response receipt; this Markdown row is not authorization evidence. Directive Epoch is recorded for diagnosis and never compared: the approval binds to Plan Target, Run floor (the stage attempt), and Approval Fingerprint (the plan content) |
Timestamp, Stage, Details, Checkpoint, Plan Target, Intent, Directive Epoch, Run floor, Approval Fingerprint, Questions File, Questions SHA-256, Prompt SHA-256, Session | tools/aidlc-log.ts answer --checkpoint plan-approval |
PLAN_APPROVAL_OVERRIDDEN |
The human broke the glass: they typed Override Plan Approval: <reason> as a prompt (recorded by the human-turn hook, never from a picked option) and the conductor ran answer --override with that reason after the normal receipt path refused. The receipt this row accompanies binds to plan content and stage attempt only; source certification is skipped for it. Always paired with a PLAN_APPROVAL_RECORDED row carrying Override: yes; reserved from the public audit CLI |
Timestamp, Stage, Reason (verbatim), Failed Checks (the normal path's refusals, separated by a vertical bar), Session, Unit (or stage-level), Fingerprint |
tools/aidlc-log.ts answer --checkpoint plan-approval --override |
REVIEW_REQUESTED |
Conductor dispatches the §12a reviewer sub-agent; reserved from the public audit CLI. Structurally malformed rows are non-authoritative and do not consume an ordinal | Timestamp, Stage, Reviewer, Iteration, Artifact Fingerprint (sha256:<hex> from one stable snapshot of every declared artifact exactly as dispatched for review), Request Id (review:<32 lowercase hex>, minted per request; the completion row and the review record echo it), optional Unit + Attempt Generation (authoritative-DAG per-unit claims), Source Fingerprint on workspace_requires stages, Unit Source Fingerprint (manifest bytes + claimed source listing) on per-unit workspace_requires stages, optional Retry (pending-request, accepted once after a modern binding exists), optional Upgrade (legacy-request, one bounded modernization of a valid request recorded before request ids or source binding), optional Recovery (stale-receipt) plus Recovery Cause (artifact, source, or artifact+source). Rows written under the retired appendix protocol also carry Review Appendix Artifact, Review Appendix Offset, Review Appendix Prior Digest, Review Appendix Prior Length, and Review Challenge; they stay readable, and a completion of such a request echoes them unchanged so the pair still binds |
tools/aidlc-log.ts review |
REVIEW_COMPLETED |
Reviewer verdict recorded; gates approval and is reserved from the public audit CLI. Malformed rows are ignored without consuming their pending request | Timestamp, Stage, Reviewer, Iteration, Verdict, Request Fingerprint (must match the request), Artifact Fingerprint (the same stable snapshot: the reviewer writes no artifact, so the reviewed bytes are the requested bytes), Request Id (must match the request), Review Record (record-relative path .aidlc-reviews/<stage>/stage/<attempt>/<iteration>.json or .aidlc-reviews/<stage>/units/<unit>/<attempt>/<iteration>.json) + Review Record Digest (sha256:<hex> over the record bytes; a record that no longer hashes to it is not the review), optional Unit + Attempt Generation (per-unit claims), Request Source Fingerprint + Source Fingerprint (identical request-time source identity on workspace_requires stages), Unit Source Fingerprint or Unit Source Binding Bypass on per-unit workspace_requires stages, Review Challenge only for the deprecated appendix migration path, Recovery only for the one stale-receipt recovery pass, optional Workflow for isolated runs |
tools/aidlc-log.ts review --verdict |
PIPELINE_LINK_COMPLETED |
A declared pipeline link returned in order; current-attempt receipts gate pipeline approval and are reserved from the public audit CLI | Timestamp, Stage, Link, Position (k/N), optional Repo (required by the protocol for multi-repo chains), optional Workflow (single-stage:<slug> for isolated runs) |
tools/aidlc-log.ts link |
Hash Scope: confirmed-content-v1 identifies the semantic questions-file digest
used by newly emitted receipts. It normalizes line endings, preserves the
original order of the preamble and confirmed sections, and trims trailing
whitespace from the resulting canonical content. It includes every visible
Q section and each Requested Changes Feedback section, including follow-up
questions added after an assumption decision. Exactly one visible top-level
Assumption Confirmation section is valid only after the summary and is
excluded, along with its contents; a same-named pre-summary section remains part
of the confirmed digest. The excluded section's assumptions and answer are not
covered by the digest and remain subject to the stage's existing decision/answer
and sensor checks. Any other visible Markdown or
raw-HTML heading after the summary is invalid. Heading-like text in HTML
comments, code spans, fenced or indented code, and HTML attribute values is not
a section.
A receipt with no Hash Scope retains the legacy whole-file digest contract;
an in-flight legacy receipt therefore needs a fresh human confirmation to
create a scoped receipt before an allowed post-confirmation append can recover.
Any other scope is rejected.
Summary-confirmation authority comparisons preserve append order within one audit shard. Across shards, different timestamps establish order; equal timestamps are causally unordered. Completion fails closed when such a tie could change the current attempt, selected receipt, or whether an artifact was written after confirmation, and requires fresh evidence with a later timestamp.
Unit Configuration and Lifecycle Events (7 events — unit-major Construction)
The interactive twin of the swarm's SWARM_UNIT_* ledger. UNIT_COMPLETED is
the completion receipt the engine's coverage walk prefers over bare artifact
existence once any receipt exists for the stage; the emitting verb verifies
the unit's required artifacts as regular files on disk before committing it.
Run floor is an exact boundary token (<event>:<timestamp>#<ordinal>), so
same-second attempts within one shard cannot reuse receipts. Equal-time
boundaries in different shards are causally unordered and use a deterministic
AMBIGUOUS:<timestamp>#<digest> floor; prior receipts cannot match it.
Unit-major stages key the floor to workflow/jump/rejection boundaries because
their work can precede their own STAGE_STARTED.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
UNIT_OWNERSHIP_SET |
Unit-major ownership mode is set before unit activity starts | Timestamp, Mode | tools/aidlc-state.ts set-unit-ownership |
UNIT_GATE_RHYTHM_SET |
Team-owned gate rhythm is set before unit activity starts | Timestamp, Rhythm | tools/aidlc-state.ts set-unit-gate-rhythm |
UNIT_STARTED |
A unit's work begins on an inline per-unit stage; refused while another unit of the stage is open | Timestamp, Stage, Unit, Run floor; optional Attempt Generation | tools/aidlc-state.ts unit start |
UNIT_PAUSED |
A unit stops before completion; the checkpoint carries why and what comes next | Timestamp, Stage, Unit, Run floor, Reason, Next Action; optional Attempt Generation | tools/aidlc-state.ts unit pause |
UNIT_RESUMED |
The paused unit is explicitly resumed (the engine hard-stops until this) | Timestamp, Stage, Unit, Run floor; optional Attempt Generation | tools/aidlc-state.ts unit resume |
UNIT_COMPLETED |
The unit's work is done AND its required artifacts are regular files on disk (verified at emit) | Timestamp, Stage, Unit, Run floor; optional Attempt Generation | tools/aidlc-state.ts unit complete |
UNIT_MERGED |
Main landed the pinned candidate content and folded this Unit's row; transported receipts now satisfy main's floors | Timestamp, Unit, Owner, Pinned OID, Merge commit OID, Attempt Generation | tools/aidlc-state.ts fold-unit-merge |
Artifact Events (3 events — hook-emitted)
The artifact hook emits for writes in either the active intent's record tree or
the active space's shared codekb/<repo>/ tree.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
ARTIFACT_CREATED |
New artifact written in the active intent record or space-level codekb tree | Timestamp, Tool, File, Context, optional Summary Authorization Id (the active summary confirmation for the written stage and Unit at write time, read from <record>/.aidlc-summary-authorization/<stage>/stage.json or <record>/.aidlc-summary-authorization/<stage>/units/<unit>.json; absent when no confirmation is active) |
hooks/aidlc-write-audit-log.ts (PostToolUse; Write to net-new path) |
ARTIFACT_UPDATED |
Existing artifact modified in either tree | Timestamp, Tool, File, Context, optional Summary Authorization Id (as for ARTIFACT_CREATED) |
hooks/aidlc-write-audit-log.ts (PostToolUse; Edit, or Write overwriting existing) |
ARTIFACT_REUSED |
Re-use decision on backward jump or per-repo pipeline reuse evidence; only Decision=keep grants the pipeline exemption; reserved from the public audit CLI |
Timestamp, Stage, Decision, Artifacts, optional Repo, optional Workflow (single-stage:<slug> for isolated freshness-bound reuse) |
tools/aidlc-state.ts reuse-artifact |
Subagent Events (1 event — hook-emitted)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
SUBAGENT_COMPLETED |
Subagent task finishes | Timestamp, Agent Type, optional Agent ID, optional Message | hooks/aidlc-log-subagent.ts (SubagentStop) |
Reviewer Enforcement Events (2 events - hook-emitted)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
REVIEWER_SCOPE_BLOCKED |
A per-unit reviewer's tool call was refused for reaching into sibling units' construction/ paths (the §12a read-scope bound) |
Timestamp, Tool, Target, Stage, Unit | hooks/aidlc-reviewer-scope.ts (PreToolUse) |
REVIEW_FREEZE_BLOCKED |
A file-tool or shell produces[] write was refused because it would invalidate a fresh READY review receipt before the gate (the §12a terminal-receipt ordering) |
Timestamp, Tool, Target, Stage, optional Unit | hooks/aidlc-review-freeze.ts (PreToolUse) |
Plan Approval Enforcement Events (2 events - hook-emitted)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
PLAN_APPROVAL_BLOCKED |
A code-generation developer-agent dispatch or workspace mutation was refused because the active unit or zero-Unit stage target lacked a current, explicitly approved plan contract (stage Steps 2-3 must precede Step 4) | Timestamp, Tool, Target, Stage, Unit | hooks/aidlc-plan-approval-guard.ts (PreToolUse) |
GUARD_DISABLED |
A tool call passed the Plan Approval guard because its deterministic off-switch (the disable environment variable documented in the hooks reference) was set while a workflow existed. One row per streak: the hook appends only when the newest row in the active shard is not already this event for the same guard | Timestamp, Guard (plan-approval-guard), Tool |
hooks/aidlc-plan-approval-guard.ts (PreToolUse) |
Documents (3 events)
The DocumentKB is a space-level store, so all three events land in the space-level audit shard (spaces/<space>/intents/audit/) even for an intent-scoped document — the intent UUID is recorded as a field rather than selecting the shard. This keeps one document's history in one place across an associate/dissociate scope change. These events are provenance, not a backup: deleting the whole documentkb/ tree destroys the per-document records, so document ids, tombstones, and intent links do NOT survive it — the next sync re-indexes the surviving originals as brand-new rows. Only a lost index.json alone is recoverable (sync rebuilds it from the per-document metadata.json files).
| Event | When | Required Fields | Emitter |
|---|---|---|---|
DOCUMENT_INDEXED |
A customer document was indexed into the DocumentKB for the first time (from onboard, and from sync's fresh-document branch) |
Timestamp, Space, Document, Source, Digest, optional Intent | tools/aidlc-knowledge.ts |
DOCUMENT_UPDATED |
An indexed document's record changed — a new revision, a re-extraction, a move, a summary, or an intent association change (from associate, dissociate, rebind, summarize, onboard's edited-row branch, sync's moved/changed/retried branches, and the idempotent audit-repair pass) |
Timestamp, Space, Document, Change, optional Intent | tools/aidlc-knowledge.ts |
DOCUMENT_REMOVED |
The original is gone; the row became a metadata-only tombstone and extracted content was deleted (from sync) |
Timestamp, Space, Document, Last Path, Last Digest | tools/aidlc-knowledge.ts |
All three are written to the space-level shard (intents/audit/), not an intent's,
even when the document carries related_intent_ids. A document outlives any single
intent and associate/dissociate can move its scope, so filing its provenance under
the active intent would split one document's history across shards. An
associate/dissociate that changes nothing emits no event: a per-call event
would fill the ledger with non-changes and break reconstruction-from-the-ledger.
Utility Events (1 event)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
HEALTH_CHECKED |
--doctor completed |
Timestamp, Request, Details | tools/aidlc-doctor.ts via the shared utility collector |
Error/Recovery Events (2 events)
| Event | When | Required Fields | Emitter |
|---|---|---|---|
ERROR_LOGGED |
Tool CLI exited non-zero via error() |
Timestamp, Tool, Command, Error | tools/aidlc-lib.ts emitError (called by every tool's error() helper) |
RECOVERY_COMPLETED |
User answered the compaction-awareness prompt | Timestamp, Choice, Current Stage | tools/aidlc-state.ts acknowledge-compaction |
Construction Bolt Events (4 events)
Emitted only during Phase 3 (Construction). See stage-protocol.md Terminology for Bolt as a sprint-like iteration whose intended Unit grouping is recorded during Delivery Planning (2.9), while runtime batching comes from the Unit dependency graph. BOLT_STARTED / BOLT_COMPLETED (and swarm-path BOLT_FAILED) are emitted from aidlc-bolt.ts on the swarm / worktree path; a default gated run does not record them. AUTONOMY_MODE_SET is emitted by aidlc-bolt.ts set-autonomy after the ladder on any walk, including a default gated run.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
BOLT_STARTED |
Swarm / worktree path only: aidlc-bolt.ts start for one Unit and its worktree. Not emitted on a default gated stage-major run. |
Timestamp, Bolt names, Batch number, Walking skeleton (true/false), optional Bolt slug, Base commit, Base Source Listing (when --worktree; the listing is the content-addressed raw-aware source baseline propagated from worktree creation), and Attempt Generation (team Unit claim) |
tools/aidlc-bolt.ts start |
BOLT_COMPLETED |
Swarm / worktree path only: aidlc-bolt.ts complete for that same Unit/worktree. Does not close the batch — SWARM_COMPLETED does. |
Timestamp, Bolt names, Batch number, optional Bolt slug (when --merge), optional Attempt Generation (team Unit claim) | tools/aidlc-bolt.ts complete |
BOLT_FAILED |
A Bolt failed during code-generation, or was explicitly aborted by the user | Timestamp, Failed Bolt, Error summary, optional Bolt slug (halt-and-ask correlation surface read by aidlc-worktree info --slug), optional Reason (aborted for explicit abort), optional Succeeded siblings, optional Attempt Generation (team Unit claim) |
tools/aidlc-bolt.ts fail and tools/aidlc-bolt.ts abort |
AUTONOMY_MODE_SET |
User answered the ladder prompt after the walking skeleton | Timestamp, Mode (autonomous or gated) |
tools/aidlc-bolt.ts set-autonomy |
Worktree (7 events)
Emitted during Phase 3 (Construction) when Bolts run inside per-Bolt git worktrees. Worktree primitive emits WORKTREE_*; state fork/merge subcommands emit STATE_*; audit fork/merge subcommands emit AUDIT_*.
Worktree path values are project-relative (.aidlc/worktrees/bolt-<slug>) in
new rows. Readers resolve them against the project root and remain compatible
with legacy absolute values.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
WORKTREE_CREATED |
Per-Bolt git worktree created from main on Bolt start | Timestamp, Bolt slug, project-relative Worktree path, Branch name, Base branch, Base commit, Base Source Listing (sha256:<hash> over the raw-aware source listing computed from the immutable base before the audit-first create), Repo (recorded selector or - for the workspace root), optional Intent record and Swarm Unit/Batch/Stage/Run floor provenance |
tools/aidlc-worktree.ts (create) |
WORKTREE_MERGED |
Bolt's worktree merged back to main on gate approval | Timestamp, Bolt slug, Worktree path, Target branch, Strategy | tools/aidlc-worktree.ts (merge) |
WORKTREE_DISCARDED |
Aborted Bolt's worktree explicitly removed | Timestamp, Bolt slug, Worktree path, Reason | tools/aidlc-worktree.ts (discard) |
STATE_FORKED |
State file forked to worktree on Bolt start | Timestamp, Bolt slug, Worktree path, Source state hash, Target state hash, optional Attempt Generation (team Unit claim) | tools/aidlc-state.ts (fork) |
STATE_MERGED |
Worktree's state merged back to main state on gate approval | Timestamp, Bolt slug, Worktree path, Source state hash, Target state hash, Conflict resolution | tools/aidlc-state.ts (merge) |
AUDIT_FORKED |
Audit log forked to worktree on Bolt start (audit-of-intent — emit precedes the byte-copy) | Timestamp, Bolt slug, Source Audit Hash, Fork Boundary, optional Attempt Generation (team Unit claim) | tools/aidlc-audit.ts (audit-fork) |
AUDIT_MERGED |
Worktree's audit entries appended to main audit on gate approval; per-Bolt entry order preserved, cross-Bolt order reflects merge-completion order. The review records named by the delta's paired REVIEW_COMPLETED rows are carried into the main intent record first, digest-verified, or the merge refuses |
Timestamp, Bolt slug, Entries Merged, Source Audit Hash, Fork Boundary, Fork Timestamp | tools/aidlc-audit.ts (audit-merge) |
Practices (4 events)
Emitted by the Inception stage practices-discovery and by the Construction orchestrator at runtime. The stage emits at the affirmation gate; the orchestrator emits at runtime via --type empty (fallback advisory) and --type override (discriminator-field for the bolt-plan-marker-conflict path).
| Event | When | Required Fields | Emitter |
|---|---|---|---|
PRACTICES_DISCOVERED |
Greenfield or brownfield lead draft, three support contributions, human interview, and lead integration completed; drafts await affirmation | Timestamp, sources scanned, drafts produced | tools/aidlc-state.ts practices-event --type discovered |
PRACTICES_AFFIRMED |
Team approved practices at the practices-discovery affirmation gate; content promoted to aidlc/spaces/<active-space>/memory/team.md and project.md |
Timestamp, affirming user, sections written, mandated/forbidden rules appended | tools/aidlc-state.ts practices-promote |
PRACTICES_OVERRIDE |
Cross-row promotion failed during practices-discovery affirmation, OR walking-skeleton stance from active-space team.md overrode bolt-plan's marker for the current Bolt |
Timestamp, Reason (discriminator); per-path field set: write-failure path emits Reason + Failure detail only (no Bolt fields); bolt-plan-marker-conflict path emits Reason + Bolt slug + Practices Stance + Bolt-Plan Marker. The two field sets do not overlap, so doctor filters by Reason and routes by either name family — write-failure-* for the affirmation promotion path, bolt-plan-marker-conflict for the orchestrator runtime path |
tools/aidlc-state.ts practices-promote (write-failure path); tools/aidlc-state.ts practices-event --type override (bolt-plan-marker-conflict path — discriminator-field disambiguation, no separate event) |
PRACTICES_SECTION_EMPTY |
Orchestrator read a practices section that returned empty; falling back to org defaults (advisory-only) | Timestamp, Section name, Fallback source | tools/aidlc-state.ts practices-event --type empty |
Merge Dispatch (3 events)
Emitted when Construction's Bolt-merge step calls aidlc-pipeline-deploy-agent via Task to determine the merge strategy from team practices prose. Emitted via the aidlc-bolt dispatch-event subcommand. The orchestrator brackets each aidlc-pipeline-deploy-agent dispatch — pre-call INVOKED, post-call RETURNED on successful parse, FALLBACK on timeout/malformed-YAML. Audit-of-intent semantic: INVOKED emits before the LLM Task call (no disk side-effect for the dispatch itself; reconciliation by slug + timestamp window). Doctor reconciles orphan INVOKED rows.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
MERGE_DISPATCH_INVOKED |
Orchestrator dispatched aidlc-pipeline-deploy-agent with current practices section + Bolt context | Timestamp, Bolt slug, Practices section excerpt; optional Pinned OID + Attempt Generation + Pin Transaction for Unit merge gates | tools/aidlc-bolt.ts dispatch-event --event MERGE_DISPATCH_INVOKED |
MERGE_DISPATCH_RETURNED |
Agent returned parsed YAML with strategy, target branch, confidence, notes | Timestamp, Bolt slug, Strategy, Target branch, Confidence, Notes; optional Pinned OID + Attempt Generation + Pin Transaction | tools/aidlc-bolt.ts dispatch-event --event MERGE_DISPATCH_RETURNED |
MERGE_DISPATCH_FALLBACK |
Agent timed out or returned malformed YAML; orchestrator fell back to org defaults — critical observability hook | Timestamp, Bolt slug, Fallback reason, Defaults applied; optional Pinned OID + Attempt Generation + Pin Transaction | tools/aidlc-bolt.ts dispatch-event --event MERGE_DISPATCH_FALLBACK |
Sensor Events (5 events)
Emitted by the deterministic-sensor system. The sensor dispatcher emits the four SENSOR_* events; the paired-coverage doctor row emits GUARDRAIL_LOADED with Scope: all, because doctor reads the full resolved guardrail set without an active stage (the per-workflow org → project → phase → stage scoping in the When-clause below describes the steady-state loader, not doctor's unscoped read). fire_on: write sensors run from the PostToolUse hook on matching writes; fire_on: gate sensors run once per existing declared deliverable before gate-start opens the first gate, revise re-enters it, or the approve-time revision backstop attempts recovered re-entry. Blocking severity is enforced only for gate-fired sensors in this release; write-fired failures remain advisory.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
SENSOR_FIRED |
Dispatcher invoked a sensor against a stage output, from either a matching PostToolUse Write/Edit or gate-boundary deliverable dispatch | Timestamp, Fire id, Sensor ID, Stage slug, Output path | tools/aidlc-sensor.ts fire |
SENSOR_PASSED |
Sensor completed and reported no findings (also: tool-unavailable, script-error fall-through — see Note footnote) | Timestamp, Fire id, Sensor ID, Stage slug, Output path, Duration ms | tools/aidlc-sensor.ts fire |
SENSOR_FAILED |
Sensor completed and reported findings; detail file written at <record>/.aidlc-sensors/<stage-slug>/<sensor-id>-<fire-id>.md |
Timestamp, Fire id, Sensor ID, Stage slug, Output path, Detail path, Findings count | tools/aidlc-sensor.ts fire |
SENSOR_BUDGET_OVERRIDE |
Sensor exceeded its configured cap (registry / binding / depth-derived per the three-layer cap model) and was terminated or skipped | Timestamp, Fire id, Sensor ID, Stage slug, Output path, Cap layer, Cap value, Observed value | tools/aidlc-sensor.ts fire |
GUARDRAIL_LOADED |
Guardrail loader resolved the scope-hierarchical guardrail set for the active workflow (org → project → phase → stage); doctor's paired-coverage check reads from this event | Timestamp, Scope, Path, Rule count | tools/aidlc-utility.ts |
The
Notefield onSENSOR_PASSEDis optional. It carriestool-unavailablewhen the per-sensor script's underlying binary isn't on PATH, orscript-error: <reason>for spawn-failure / non-zero exit / malformed JSON / detail-write failure paths. Those remain advisory for write-fired sensors, but a blocking gate binding requires a verified pass, so anyNote, dispatcher failure, malformed verdict, or budget override refuses gate entry. Pair correlation is viaFire id(echoed verbatim fromSENSOR_FIREDto the terminal row);Output pathalone does not disambiguate repeated write dispatches or a later gate dispatch of the same sensor + stage + path tuple.
Pair by
Fire id, not by audit-row index. Write dispatch can fan out one tool call across several sensors, while gate dispatch fans each gate-bound sensor across every existing deliverable. Terminal rows may interleave by spawn duration, sofindAllEvents("SENSOR_FIRED")[i]does NOT pair withfindAllEvents("SENSOR_PASSED")[i]by index. Audit-walking consumers (thesensor_firings[]populator, doctor, designer) MUST match terminal rows to FIRED rows via the 8-hexFire idcorrelator.
Learning Loop (3 events)
Emitted by stage-protocol §13 (Learnings Ritual). The runtime-graph compile emits MEMORY_EMPTY when a just-approved stage's memory.md has zero non-blank entries under the four standard headings. The learning-gate tool emits RULE_LEARNED when the user keeps a surfaced or free-text learning (a learning IS a practice — it lands as a practice line under the routed heading in {project,team}.md) and SENSOR_PROPOSED when a learning installs a sensor binding (manifest + originating stage sensors: frontmatter). Doctor reads MEMORY_EMPTY rows over time to detect systematic diary-skipping across stages.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
MEMORY_EMPTY |
A stage approval triggered a runtime-graph compile and the stage's memory.md had zero non-blank entries under any of the four §13 headings | Timestamp, Stage | tools/aidlc-runtime.ts compile |
RULE_LEARNED |
The learning gate persisted a kept learning as a practice line under the routed heading in {project,team}.md |
Timestamp, Stage, Candidate-ID, Content-Hash, Destination, Heading, Source | tools/aidlc-learnings.ts persist |
SENSOR_PROPOSED |
The learning gate scaffolded a project-tier sensor manifest and bound it to the originating stage's sensors: frontmatter |
Timestamp, Stage, Candidate-ID, Sensor ID, Manifest path, Matches, Destinations, Source | tools/aidlc-learnings.ts persist |
Swarm (7 events)
Six events emit from the swarm referee aidlc-swarm.ts — the deterministic verdict surface the conductor consults — and SWARM_SOURCE_MERGED emits from aidlc-worktree.ts after application source lands in main. The referee is stateless (no iteration counter): prepare captures the exact stage-attempt token, stamps the Unit/Batch/Stage/Run floor into WORKTREE_CREATED plus worktree metadata, forks the per-unit worktrees, and emits SWARM_STARTED with both the prepared batch and the full attempt-bound Unit obligation set (and SWARM_DEGRADED when the conductor reports a loud downgrade); finalize requires that prepared token to still match the current attempt before merging, then preserves it on each convergence row. Completion compares the live authored DAG with that durable obligation set and refuses shrink or expansion until the DAG is restored or the stage attempt restarts. A worktree prepared by the immediately preceding unstamped release remains finalizable only when its frozen audit prefix proves the matching legacy SWARM_STARTED, BOLT_STARTED, STATE_FORKED, and AUDIT_FORKED sequence, the fork hash still matches, all three worktree mirrors exist, and the derived frozen attempt still equals the current attempt; this compatibility path never emits a backdated start or adopts a stale worktree. It re-verifies the conductor's claimed-converged set, snapshots the exact declared record artifacts plus the bound source-manifest.json, serialised-merges those records and AIDLC metadata for the genuine passes, and emits the per-Unit pair (SWARM_UNIT_CONVERGED / SWARM_UNIT_FAILED — except a converged unit whose record/metadata merge-back failed, which gets neither row until a finalize retry merges it), the per-failed-Unit baton row (SWARM_BATON_RETURNED), and the batch tally (SWARM_COMPLETED). Source merge then requires authority correlated to durable worktree provenance and the current Bolt/batch/stage attempt, links the main checkout from the stage-entry baseline or the prior attempt's validated final aggregate recorded on GATE_REJECTED, and emits SWARM_SOURCE_MERGED. Rejection never replaces the completion baseline. The opening link is revalidated against that trusted predecessor; later links must form an exact fingerprint chain. A pre-binding worktree whose convergence predates immutable source fields retains the historical branch merge; modern incomplete authority fails closed and does not advance batch routing. If Git mutation lands but SWARM_SOURCE_MERGED cannot be appended, the command preserves the worktree and reports a non-retryable [merge-succeeded:<sha>] failure: do not rerun the merge, because no authenticated recovery receipt exists; restart the stage attempt or use the explicit source-freshness off-switch only with human approval. If SWARM_SOURCE_MERGED did land and only subsequent worktree, branch, or retained-ref cleanup failed, rerunning the same merge performs cleanup-only reconciliation without reapplying source or duplicating authority. The check subcommand emits nothing — it is an advisory verdict that informs the conductor's retry decision. Because the loop and its cap live in the driver, the per-Unit rows carry no Iterations / Cap value fields.
| Event | When | Required Fields | Emitter |
|---|---|---|---|
SWARM_STARTED |
Swarm referee prepare captured the exact attempt and forked a batch of dependency-linked Units |
Timestamp, Batch number, Unit names, Unit obligations, Concurrency cap, Stage, Run floor | tools/aidlc-swarm.ts |
SWARM_UNIT_CONVERGED |
A swarm Unit re-verified green (and untampered), its exact declared record artifacts plus bound source manifest landed, and its AIDLC metadata merge-back landed; unless explicitly bypassed, finalize also verified the current global/unit source bindings and raw-aware base-to-worktree footprint against reviewed source-manifest claims | Timestamp, Batch number, Unit name, Stage, Run floor, optional Source Fingerprint and Source Commit (immutable reviewed source accepted by aidlc-worktree merge), or Source Freshness Bypass: true when finalize explicitly used AIDLC_SKIP_SOURCE_FRESHNESS=1 (the freshness/unit/footprint guarantees do not apply and merge must repeat the switch) |
tools/aidlc-swarm.ts |
SWARM_SOURCE_MERGED |
The immutable reviewed source for one current-attempt swarm Unit landed in main and extended the aggregate source chain | Timestamp, Batch number, Unit name, Stage, Run floor, Previous Source Fingerprint, Source Fingerprint, Source Commit, Merge commit, Repo (recorded selector or - for the workspace root) |
tools/aidlc-worktree.ts merge |
SWARM_UNIT_FAILED |
A swarm Unit failed the finalize re-verify (not claimed, claimed-but-red, or tampered) |
Timestamp, Batch number, Unit name, Reason | tools/aidlc-swarm.ts |
| SWARM_BATON_RETURNED | A swarm Unit returned the baton to the conductor for orchestrator-mediated coordination | Timestamp, Batch number, Unit name, Reason | tools/aidlc-swarm.ts |
| SWARM_COMPLETED | All Units in the batch finished (converged or failed); batch closed | Timestamp, Batch number, Converged count, Failed count | tools/aidlc-swarm.ts |
| SWARM_DEGRADED | AIDLC_USE_SWARM=1 was requested but the Workflow tool was unavailable, so the conductor ran the subagent floor (loud-degrade) | Timestamp, Batch number, Requested driver, Fallback driver | tools/aidlc-swarm.ts |
Hook-Generated Format
Hooks emit events through the same library emitter as orchestrator-driven emissions (appendAuditEntry from tools/aidlc-audit.ts). Hook-emitted events are first-class taxonomy members (ARTIFACT_CREATED, ARTIFACT_UPDATED, SUBAGENT_COMPLETED, all SESSION_*) — there is no longer a separate "free-form hook entry" format. A hook with no active workflow in cwd is a no-op; session events only append to a workflow's audit.md when one exists.
The public aidlc-audit.ts append CLI is a diagnostic escape hatch, not the canonical emit path: it refuses authority-bearing receipts (STAGE_COMPLETED, HUMAN_TURN, GATE_APPROVED, GATE_REJECTED, QUESTION_ANSWERED, REVIEW_REQUESTED, REVIEW_COMPLETED, PIPELINE_LINK_COMPLETED, ARTIFACT_REUSED, SWARM_STARTED, SWARM_UNIT_CONVERGED, SWARM_SOURCE_MERGED, AUTONOMY_MODE_SET, UNIT_OWNERSHIP_SET, UNIT_GATE_RHYTHM_SET, UNIT_STARTED, UNIT_PAUSED, UNIT_RESUMED, UNIT_COMPLETED, UNIT_MERGED, DOCUMENT_INDEXED, DOCUMENT_UPDATED, DOCUMENT_REMOVED), which only their owning tool or hook may emit. Field names must be printable single-line labels matching the audit field grammar; values have every line terminator escaped. append-raw likewise refuses a body carrying an **Event**: line naming a taxonomy event and refuses line-breaking headings.
Format Standards
- All timestamps: ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)
- Generate fresh timestamp for EACH entry via
date -u +"%Y-%m-%dT%H:%M:%SZ"(tools do this automatically) - Append-only — NEVER modify or delete existing entries
- No sensitive data (credentials, PII, secrets)
- Human decisions recorded verbatim — NEVER summarize
Entry Format
Standard Format
## [Event Heading]
**Timestamp**: [ISO timestamp]
**Event**: [Event type from table above]
**Stage**: [Stage slug — optional, context-dependent]
**Details**: [Event-specific content]
---
Error Format
## Error: [Brief Description]
**Timestamp**: [ISO timestamp]
**Severity**: [Critical/High/Medium/Low]
**Type**: [Parse error/Missing artifact/State corruption/Validation failure]
**Description**: [What went wrong]
**Resolution**: [Action taken]
---
Recovery Format
## Recovery: [Brief Description]
**Timestamp**: [ISO timestamp]
**Issue**: [What triggered recovery]
**Steps**: [Numbered recovery actions]
**Outcome**: [Successful/Partial/Failed]
---
Validation basis on STAGE_COMPLETED
Main-workflow STAGE_COMPLETED entries may include a compact schema-3 receipt:
**Validation Basis**: {"schema":3,"graphContract":"sha256:...","projectType":"brownfield","inputs":[{"artifact":"code-summary","producer":"code-generation","required":true,"instanceCount":12,"presentCount":12,"structureHash":"sha256:...","contentHash":"sha256:..."}],"outputs":[...]}
The resolver first computes the concrete runtime artifact-instance set using
the Bolt DAG, unit kinds, produces_kinds, and canonical filename aliases. The
receipt then stores deterministic stage-level aggregate fingerprints rather
than every Unit/path row. Optional inputs are included only when at least one
instance was present when completion was reported. This is a report-time
snapshot: it does not prove which bytes the stage actually read. "Observed"
dependency means recorded in this receipt, not runtime read instrumentation;
changes before capture become the baseline and changes after capture are
detectable.
If receipt capture is unavailable, the owning completion tool still appends a
receipt-less STAGE_COMPLETED with Validation Warning. That completion is
untracked and advisory rather than a reason to abort the state transition.
The latest receipt remains useful as dependency evidence after a stage is reopened, while only a completion in the current attempt counts as current tracking for the stage itself. Earlier schemas and receipt-less completions fail open until the stage completes with this schema. Schema 2 is deliberately untracked because it cannot distinguish its old zero-instance resolution from the stage-level zero-Unit resolution introduced with schema 3.