Audit and history
Two complementary surfaces:
orca audit— operator decisions. Every confirmed@dangerousCLI verb writes a row here. Works against both backends.orca ops-history— per-execution operations archive: theTrackingRecordrows the runtime emits per action (which labware moved, which device operation ran). Works against both backends (the local daemon binds the ops-history operations; Swarm exposes the same surface).
orca audit — operator decisions
The audit log captures every CLI verb that required confirmation: who ran it, what they did, what reason they gave, and what the result was.
orca audit list # most recent first
orca audit list --limit 50 # cap the number of rows
orca audit list --action-name labware.edit-location # filter by action
The audit surface is a single list verb. It takes only --action-name (filter to one action) and --limit (max rows). There is no audit get, and no --since / --verb / --execution filters.
Output
TIMESTAMP ACTION LEVEL REASON
2026-05-26T14:22:03 labware.edit_location physical moved to shaker manually
2026-05-26T14:24:11 thread.skip_method physical sealer pre-heating
2026-05-26T14:30:05 recoverable_timeout.extend operator drive recovered, still spinning
Each row carries the timestamp, the action name, its danger level, and the operator's reason. --json returns the full entries for scripting.
What gets audited
- Every confirmed
@dangerousoperation (PHYSICAL or OPERATOR danger level). --force/--yesbypasses the interactive prompt but does NOT bypass the audit row.
Pitfalls
audit listdoes NOT include workflow-driven actions. Ashakeinside a@orca.actionis in the operations archive (ops-history), not the audit log.- The local audit ring buffer is bounded (most-recent entries); the durable mirror is a rotating log file on disk. Cloud deployments inherit Swarm's retention.
orca ops-history — operations archive
Per action the runtime tracks a TrackingRecord: which labware was affected, which device operation ran, the source, and the timestamp. ops-history reads that archive per execution and searches across executions.
orca ops-history get <execution-id> # all records for one execution
orca ops-history search --labware <name> # records touching one labware
orca ops-history search --device <name> # records touching one device
orca ops-history search --execution-id <id> --operation <op>
orca ops-history search --thread-id <id>
get output
Every TrackingRecord archived for one execution. Use --json for scripting; the table form is for sanity-checking.
ACTION_ID THREAD_ID METHOD_ID SOURCE TIMESTAMP OPS AFFECTED_LABWARE_IDS
3f1c... a4b2... 9d8e... observed 2026-05-26T14:00:12 2 7a3f1c0e-...
3f1d... a4b2... 9d8e... observed 2026-05-26T14:00:42 1 7a3f1c0e-...
search filters
All filters AND-combine.
| Flag | Effect |
|---|---|
--execution-id <id> | Filter by owning execution. |
--action-id <id> | Filter by action id. |
--thread-id <id> | Filter by thread id. |
--method-id <id> | Filter by method id. |
--source <s> | Filter by tracking source (observed / declared / driver_observed). |
--operation <op> | Records containing at least one op of this DeviceOperation value. |
--labware <name> | Records that touched this labware NAME. |
--device <name> | Records that touched this device NAME. |
There is no --labware-id, --kind, --since, --until, or --limit filter on search.
Pitfalls
ops-historyworks against both backends. The local daemon binds the ops-history operations; Swarm exposes the same surface under/api/operations/.... (Note: orca-core's own sub-app--helptext still labels it "cloud-only" — that string is stale.)searchfilters by NAME for labware/device, not by id. Use the labware or device name as it appears in the topology, not a UUID. The affected-labware UUIDs in each record's last column are the onesorca labware journey/labware historyaccept.- Records are append-only. If a record is wrong, that's the record. The fix is in code, not in the archive.