Skip to main content

Audit and history

Two complementary surfaces:

  • orca audit — operator decisions. Every confirmed @dangerous CLI verb writes a row here. Works against both backends.
  • orca ops-history — per-execution operations archive: the TrackingRecord rows 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 @dangerous operation (PHYSICAL or OPERATOR danger level).
  • --force / --yes bypasses the interactive prompt but does NOT bypass the audit row.

Pitfalls

  • audit list does NOT include workflow-driven actions. A shake inside a @orca.action is 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.

FlagEffect
--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-history works 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 --help text still labels it "cloud-only" — that string is stale.)
  • search filters 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 ones orca labware journey / labware history accept.
  • Records are append-only. If a record is wrong, that's the record. The fix is in code, not in the archive.