Every event the Vinaya process writes to the Log: the header on every line, the ten families and all their fields, how each maps to a generic event, and the rules for reading them back.
Partial
10 families
Header schema 3
Generic mapping
Reference
Header fields
These fields are on every line. The harness fills them; a caller cannot set them.
Field
Type
Since schema
Meaning
kind
family name
all
One of dispatch, dev_review_loop, forge_write, gate, operation, usage, role_attempt, handoff, effect, custom. Closed list. command and tokens are refused by name (they became operation and usage).
event
string
all
The event within the family.
duration_ms
number ≥ 0, optional
all
How long the act took. On gate · summary, the run's total time.
payload
{}
all
Always an empty strict object. Families carry their content in named fields.
meta.schema
1 | 2 | 3
all
Header version. New lines are always 3; 1 and 2 exist so old lines keep parsing.
meta.ts
string
all
ISO 8601, UTC, millisecond precision.
meta.run_id
string, ^[A-Za-z0-9_.-]{1,128}$
all
VINAYA_RUN_ID, else a random id generated once per process. A dispatched child inherits its parent's run_id.
meta.seq
integer ≥ 0
all
Per-process counter from 0. Readers sort by it, never by file position.
meta.repo
string | null
all
owner/name from the origin remote; null when it cannot be resolved.
meta.vinaya
string
all
The CLI version that wrote the line.
meta.doctrine
string
all
aeg-root@<sha> for a source checkout, the package version for a bundle, unknown when git cannot be reached.
meta.host
hook | ci | cli | loop
all
ci when GITHUB_ACTIONS is set; else hook or loop from VINAYA_HOST; else cli.
meta.machine
string
all
sha256 of the hostname, never the name.
meta.event_id
string, not empty
2
Stable identity of this event, generated once per write. The key for removing duplicates.
meta.process_id
string, not empty
2
Opaque per-process id, distinct from run_id.
meta.actor_id
string | null
2
Opaque, unchecked actor claim from VINAYA_ROLE. Not checked against the role list. Empty or absent reads null.
meta.lineage.run
string | null
2
VINAYA_RUN; the loop driver sets it to its loop_id. Defaults to the process's own run_id.
meta.lineage.attempt
integer | null
2
VINAYA_ATTEMPT; role dispatch sets it to the dispatch attempt. Else null.
meta.lineage.parent
string | null
2
VINAYA_PARENT_EVENT: the event_id this event continues. Planned; written as null.
meta.input_versions.manifest_version
2 | null, optional
2
Generation of the review-input manifest. New lines write 2; older lines may leave it out. Any other number is rejected.
meta.input_versions.objectives_version
string | null
2
Objectives version, from the review-input manifest.
How far the attribution can be trusted. env_correlated when VINAYA_ROLE or VINAYA_TASK is set, else unavailable, and always unavailable when subject.issue came from the branch. Only a caller that asserts it can set a stronger value. See Redaction and trust.
meta.work.ref
string | null
3
The unit of work, opaque and never parsed. VINAYA_WORK_REF, else subject.issue as text, else null.
meta.work.repo
string | null
3
Same value as meta.repo.
meta.work.change
string | null
3
The pull request, as text, when VINAYA_PR is set; else null.
meta.work.revision
string | null
3
The commit checked (git rev-parse HEAD), on gate events; else null.
meta.flow.id
string | null
3
The way of working. VINAYA_FLOW; unset reads vinaya.
meta.flow.version
string | null
3
VINAYA_FLOW_VERSION, else null.
meta.runtime
string | null
3
VINAYA_RUNTIME, else null.
meta.source
string | null
3
VINAYA_SOURCE, else null.
subject.issue
integer | null
all
VINAYA_TASK; else the Issue the checked-out branch names (task/issue-<n> or task/<tranche>/<n>, confirmed with the forge; in CI, GITHUB_HEAD_REF); else null.
subject.pr
integer, optional
all
VINAYA_PR, a positive integer. The loop driver sets it once a pull request exists.
subject.sha
string, optional
all
Gate events only: the 40-hex HEAD of the working directory. Absent when it cannot be resolved. In pull-request CI this is the merge commit, not the pull request's head.
VINAYA_ROLE when it is one of the roles, else unattributed. A caller never declares its own.
subject.round
integer, optional
all
VINAYA_ROUND.
subject.objectives_version
string, optional
all
sha256 hex of the objectives block.
input_versions is filled only when a caller passes it: the loop's reviewer dispatch passes it from its review-input manifest. Otherwise every part is null.
Schema 3 is a new version, not extra fields on 2, so a server that knows only 1 and 2 keeps a schema 3 line as an unknown-version record instead of rejecting it.
Which code may write each family is enforced by tests; see Redaction and trust.
dispatch
A role dispatch, seen from the parent. In the loop, Developer, Code Reviewer and Security turns are dispatched this way; vinaya dispatch <role> reaches it for any role.
Event
When it fires
Main fields
Generic family
dispatched
A role is about to be launched
prompt_hash
execution.started; for reviewer roles also review.requested
outcome_received
The child exited cleanly
outcome, usage
execution.completed
dispatch_failed
A refusal before launch, a crash at launch, a timeout, or a non-zero exit
reason, usage_limit, usage
execution.failed
dev_review_loop
The Developer and reviewer loop of one task. Every event carries loop_id (string). Process part: Executing. See The loop.
Event
When it fires
Main fields
Generic family
loop_started
A loop begins
task, policy
run.started
round_started
A round begins
round, base_head
decision.recorded (round outcome, paired with round_ended)
gate_result_read
The loop reads the gate result, on every read, including the second read after a re-ask
Round assessment builds loop_started, round_started, gate_result_read, verdicts_read, findings_compared, stop_condition_met, paused, round_ended and journal_finalized. The loop driver writes them, and writes resumed, cancelled, unpushed_work_resume, infrastructure_retry, driver_heartbeat and driver_exited itself. The driver's own round assessment and live check also build stop_condition_met, paused, round_ended and journal_finalized.
forge_write
Kept only so lines posted long ago still parse. Nothing writes this family, and all three events are exempt from the producer test. The Log is never written to the forge. Process part: none. Generic family: none.
Event
When it fires
Main fields
Generic family
validated
A payload passed its schema check
none beyond the shared fields
None
refused
The write failed or was refused
reason (string)
None
written
The forge accepted the write
comment_ids (string[]): comment ids the forge returned
One run of the checks. Process part: Gates. Every gate event carries subject.sha when it can be resolved. A run writes one summary plus one checked for each check that did not pass. See Gates.
A check ends with an outcome other than pass or skip, including a check stopped by SIGINT or SIGTERM (cancelled)
check, outcome, reason, input_fingerprint
gate.evaluated
operation
A normalized operation or tool call: from the CLI, the broker, the Operator's tools, vinaya log emit, or sandbox setup. One event. Process part: Harness.
The fields a refused custom event concerned. Never values.
Operations written:
operation
When
target, result, error_class
cli_command
Every vinaya <command> exit
target: the command name from a fixed list (help, unknown, log selftest, task run, …). result: ok (exit 0), refused (exit 2), error (other). error_class: the exit code as text.
authenticate-invocation
A Worker or Operator invocation is authenticated
target: task:<n>. ok, or refused with the error class.
The request's own operation name
The broker checks an effect request's grant, target or replay
From the request; ok or refused.
task_cancel
The Operator's cancel handler runs
—
task_resume
The Operator's resume handler runs
—
log.emit
A custom event was refused
target: the name if it is name-shaped, else null. refused. error_class: the refusal reason. field_names set.
claude-sandbox-confinement
Claude's sandbox could not be set up
target: the missing tools. unavailable.
linux-sandbox-probe
The Linux sandbox probe failed
target: the agent. unavailable.
log.selftest
vinaya log selftest sends its test event straight to the server, not through the normal path
A marker so readers leave self-test traffic out.
cli_command does not record vinaya log send, a process ended by a signal, or a parent that hands off to the author repository's own source.
usage
Token use of one dispatched turn, written once per attempt on every exit path. Process part: Executing.
Event
When it fires
Main fields
Generic family
observed
A dispatched turn ends, however it ends
model, source, semantics, units, unknown_reason
execution.usage
Field
Type
Meaning
model
string | null
Model.
source
string
The vendor (claude, codex, gemini), or claude-transcript when read from Claude's session transcript.
semantics
cumulative | delta
A dispatch always writes cumulative.
units.input
number ≥ 0 | null
Input tokens; null when unknown, never 0.
units.output
number ≥ 0 | null
Output tokens.
units.cache
number ≥ 0 | null
Cache tokens (Claude: creation plus read; Codex: cached input).
unknown_reason
string | null
Why the units are unknown. Gemini always reports null units with a reason.
role_attempt
The normalized outcome of one role attempt. Process part: Executing.
Event
When it fires
Main fields
Generic family
attempted
Once per dispatch attempt; once more when a reviewer or security report fails to validate (incomplete or infrastructure_failed, with usage: null)
A hand-off to a human, when the loop pauses. Process part: Executing. See Pauses and rulings.
Event
When it fires
Main fields
Generic family
raised
The escalation record and the paused state are durably written; not again for an idempotent rerun of the same pause
class, reason, requested_decision
handoff.raised, human.intervened
resolved
A resume decision is durably consumed; never for cancel, never twice for one escalation
class, reason, resolution, resolved_by
handoff.resolved, human.intervened
Field
Type
On
Meaning
class
authority | strategy | product
both
Kind of hand-off, derived from the pause reason.
reason
string
both
The pause reason.
requested_decision
string | null
raised
The decision asked for, cleaned the same way as the public pause comment.
resolution
string | null
resolved
The recorded decision.
resolved_by
string | null
resolved
Who authenticated it.
effect
The final outcome of a governed external write. Pause and escalation comment posts go through it. Process part: Executing.
Event
When it fires
Main fields
Generic family
verified
Once per write call, including an idempotent replay
effect_id, target, outcome
effect.committed / reconciled
attempted
Nothing writes it; kept in the schema
effect_id, target
Not mapped
observed
Nothing writes it; kept in the schema
effect_id, target, outcome
Not mapped
Field
Type
Meaning
effect_id
string
The key of the write in the control store; the same across crash, retry and replay.
target.kind
string
The operation of the effect.
target.ref
string
The target of the effect.
outcome
success | failure | uncertain
failure when the post threw; uncertain when reconciliation was ambiguous or the record was corrupt.
custom
An event your team declared in logs.events in vinaya.config.json, emitted by Vinaya code or by vinaya log emit <event>. Valid only under a schema 3 header. It sits outside the Vinaya process parts. See Custom events for the declaration rules and refusals.
Event
When it fires
Main fields
Generic family
recorded
A declared event is emitted with valid fields
name, fields
Namespaced process event
Field
Type
Meaning
name
string ≤ 64, ^[a-z][a-z0-9_]*\.[a-z][a-z0-9_.]*$
The declared name.
fields
record of field name (^[a-z][a-z0-9_]*$, ≤ 64) → string ≤ 500 | finite number | boolean; at most 20
The values, flat.
Generic mapping
Vinaya's families are named for the process's own acts. Each maps to the generic families every process must report; see Process contract.
Not in the mapping: dev_review_loop · unpushed_work_resume, all of forge_write, and effect · attempted and observed.
Generic families without an event of their own
Reading rules
Rule
What it says
Order
Sort a process's lines by meta.seq, never by file position.
Identity
An event is its meta.event_id; a schema 1 line is <run_id>:<seq>. The same event seen in two places is one event.
Liveness (ten-minute rule)
For one Issue's dev_review_loop lines in time order: running when the newest line is under ten minutes old and no driver_exited is newer; finished, paused or exited when the newest line is a driver_exited (its reason says which); stale, presumed dead when the newest line is over ten minutes old with no driver_exited. Ten minutes is twice the heartbeat interval. meta.machine says where it runs.
Unknown, never zero
A field a line's schema never had reads unknown with a reason, never a default. null usage units are unknown, never 0.
Low trust
A line from a CLI older than 0.33.0, or with an unreadable meta.vinaya, is low trust whatever its header says.
Passing checks
A passing or skipped check has no checked line; it is only counted in summary.
Usage
Per run and model, only the last cumulative observation counts; delta observations add up; never add one kind to the other. A dispatch line and a role_attempt line with the same effect_id are one attempt.
Finding ids
A finding id is stable only within one round's comment. Read recurrence from findings_compared.recurring, never from an id appearing again.
Effects
Expect one effect · verified per forge write.
Self-test
Leave operation · log.selftest out of real telemetry.
Unknown versions
A meta.schema other than 1, 2 or 3 is kept word for word as an unknown-version record, not a row.
Not control state
The Log never authorizes, resumes or recovers a run.