libra agent
Command reference for `libra agent`
Manage external-agent capture for Claude Code, Codex, and OpenCode.
Synopsis
libra agent status
libra agent list [--schema-version <1|2>] [--json]
libra agent import (--session <id> | --path <path> | --since <rfc3339> | --all) [--agent <name>] --yes
libra --json agent graph <session> [--repo <path>]
libra agent enable [--agent <name>]...
libra agent add [<name>...]
libra agent disable [--agent <name>]...
libra agent remove [<name>...]
libra agent session <subcommand>
libra agent checkpoint <subcommand>
libra agent skill <subcommand>
libra agent clean [--all]
libra agent doctor [--repair]
libra agent workspace list [--limit <n>] [--cursor <token>] [--state <state>]...
libra agent workspace show <workspace-id>
libra agent push [--remote <name>] [--force-rewrite]
libra agent rpc <subcommand>
libra agent bridge --stdio
Description
libra agent manages Libra's external-agent capture surface. It installs and
removes provider hooks, reports captured session/checkpoint state, exposes
read-only diagnostics, and can push refs/libra/traces to a remote.
The supported roster is claude-code, codex and opencode (first batch),
and all three are hook-installable: claude-code writes .claude/settings.json,
codex writes user-level $CODEX_HOME/hooks.json plus Libra-managed trust
entries in $CODEX_HOME/config.toml (untrusted Codex hooks are skipped
silently, so trust entries are part of the install), and opencode writes the
Libra-managed plugin .opencode/plugin/libra-hooks.js (note: opencode --pure
disables all external plugins, including capture).
gemini was demoted out of the supported roster and is uninstall-only:
libra agent remove gemini removes previously installed Libra-managed hooks
(idempotent), captured sessions stay readable, and add/enable for it — or
for any other non-roster agent — return an actionable unsupported error.
The OpenCode parser targets the audited 2.0.26 vocabulary. Its current
lifecycle inputs are session.created, user session.inbox.delivered,
session.execution.succeeded, session.execution.failed,
session.execution.interrupted, session.deleted, and
session.compaction.ended; tool.execute.after is a separate observation hook.
Delivery requires role="user" and a prompt string, including an empty string.
Only user, superseded, and inactivity interruptions end a turn; shutdown
keeps restart continuity. An enqueue is merged by the plugin and is never a
standalone lifecycle input.
Compatibility inputs are session.status(idle), message.updated,
session.compacted, and server.instance.disposed with a tracked session ID.
Busy/retry status frames are rejected. The parser requires a prompt string for
legacy message.updated; an empty string and an omitted role are accepted,
and a declared role must be user. Neither message nor user_prompt fills a
missing prompt. The deprecated session.idle alias remains accepted, with a
content-free legacy_event_alias tracing warning.
The managed plugin uses the OpenCode 2.0.26 setup(ctx) API, a
location-scoped event subscription and an observe-only tool hook. Refresh it
with libra agent enable --agent opencode: status reports old or edited
templates, and duplicate managed copies, as not installed until refreshed.
Node and Bun use the same node:child_process transport with the pinned
absolute Libra filename and shell:false. Session/turn boundaries run
synchronously; tool and compaction observations run asynchronously and never
change host arguments or return context/control output.
User inbox enqueue/delivery pairs open one turn per classified inbox ID within
the bounded live history window. Frames also carry a stable message_id for
Libra’s existing bounded receipt ledger; this is not an unlimited historical
replay guarantee. Legacy
user messages pair with their first text part, or send an explicit empty string
before the next unrelated event or cleanup. Assistant step events supply the
model. Buffers are bounded: 64 tracked sessions process-wide, 128 pending prompts, 128 early
text parts, 256 classified inbox/message IDs and 16 observation children;
prompts are limited to 16,384 UTF-16 units without a split surrogate. Capacity
or unavailable text produces a fixed, content-free diagnostic at most once per
reason per plugin instance; truncated
prompts carry prompt_truncated=true. ID history is a rolling 256-entry window and is pruned when a session ends;
new prompts keep flowing after the window fills. When the session window fills,
the least recently observed session is flushed with server.instance.disposed
and the new session is admitted. A later observation can reopen an evicted
session; this closes Libra tracking only and does not delete or stop the OpenCode
session. Early text also uses a rolling window.
Cleanup and process exit flush all tracked sessions using one shared deadline
per cleanup or process exit, respectively. Forwarding is best effort and fails
open for the OpenCode host. Nonzero child exit or timeout emits only a fixed
forward_failed / forward_timeout diagnostic, at most once per reason per plugin instance. Each child has the current export deadline plus
15 seconds (currently 45 seconds), with SIGKILL at timeout. Install checks both
plugin layouts, rejects symlinks and special files before reading, preserves
user-owned files and rolls back its canonical update if managed duplicate
removal fails. These checks assume stable directory names; concurrent directory
relocation and edits after the final ownership check remain deferred.
opencode --pure / OPENCODE_PURE=1 disables all external plugins and hook
capture. Local Node/Bun tests use synthetic events and a controlled exporter;
real OpenCode content capture and native reasoning proof require their separate
acceptance gates.
OpenCode 2.0.26 export metadata uses user.text, assistant model.id,
tokens and successful file tools. The assistant token total is
input + output + reasoning + cache.read + cache.write; cached tokens are
cache.read + cache.write. Session-level totals are not added again. Classic
info/parts exports remain compatible: assistant aggregate tokens take
precedence over deduplicated step-finish details. User model fields are ignored.
Modified files combine successful edit/write/patch paths and snapshot files,
with validated patch move sources and destinations. Output paths are project
relative with forward slashes; location-relative tool paths use the session's
proven location, while snapshots already use the project root. Missing history,
external or invalid paths, unsupported shapes, invalid token numbers and
collection limits produce partial metadata with content-free warnings.
Idle, model/agent switches, synthetic/system/skill messages, shell and compaction
are recognized metadata and do not become human prompts. Internal ID, path and
alias limits also mark partial; at the ID cap later messages are omitted.
Extraction does not read files or archive reasoning content, and synthetic
fixtures do not prove real macOS content capture or native reasoning origin.
OpenCode coverage normalization accepts native 2.0.26 messages and classic
info/parts. Each human message starts its own stable logical turn. A valid
native idle settles all pending human splits, including failed/interrupted
outcomes; Complete describes captured representation, not task success.
Semantic messages after the last valid idle stay Incomplete. Unknown/malformed
content and reasoning stay Incomplete and are never repaired by idle. The nine
classic metadata parts (step-finish, patch, step-start, snapshot, retry,
compaction, agent, subtask, file) are recognized without semantic projection.
Native user attachments, skill text, and tool file results are unsupported:
they mark Incomplete without copying attachment bytes or URIs into records.
Valid agent/skill metadata, model/usage and provider state do not change the
digest. Native tools use name/id/state.input and text state.content; an error
without content projects only its structured error.message, never response.body.
No reasoning bytes or provider state establish trusted native origin here.
OpenCode user prompts pass through the same reminder filter for native/classic
coverage and native/classic/flat-JSONL metadata extraction. Exact literal
<system-reminder>...</system-reminder> blocks, including nested blocks, are
removed wherever they occur; text outside them stays byte-for-byte unchanged.
An injection-only message adds no user prompt or user semantic record. The
filter also runs before skill matching; independent token metadata is retained.
An unfinished block suppresses its tail and marks partial/Incomplete; a stray
closing tag is retained and marks partial/Incomplete. Idle cannot clear these
violations. Only user text is filtered, and other providers keep their existing
semantics. This is a literal marker filter, not proof of producer origin.
OpenCode extraction is fail-visible for empty input, invalid JSON, and illegal
export shapes: extraction.partial=true and fixed payload-free warnings are
recorded. Valid independent flat model/token fields remain projected even when
the role is missing or unsupported. A valid empty session export is distinct
from missing transcript bytes (extraction.present=false). Noncritical
extraction errors do not block an otherwise admissible checkpoint; malformed
exports do not replace an existing checkpoint. Coverage, authorization, and
native-origin gates remain required.
The default OpenCode export budget is 30 seconds; the export lease and plugin
forwarding timeout derive a 15-second margin (45 seconds). Run
libra agent add opencode again to refresh an older installed plugin. Schema v2
importable and export_bridge require a trusted exporter and a successful
platform sandbox probe: Seatbelt on macOS, the existing trusted bwrap probe on
Linux. Availability reports those prerequisites; it does not prove that OpenCode
boots, that a session exports successfully, or that reasoning fields have a
trusted native origin. Timeout still rejects partial output and preserves the
existing metadata-only fallback; the 16 MiB export cap is unchanged.
On macOS, OpenCode export requires a Required Seatbelt server/export pair.
Both processes deny process-fork, use private HOME/XDG roots and a pinned
binary copy, and communicate only on one authenticated loopback port.
Cancellation and the absolute deadline terminate their owned process groups;
Libra never signals a group after reaping its leader. Trust, containment,
readiness, output-cap or shutdown failure remains metadata-only, with no
unsandboxed fallback. To enable the exporter, register the directory containing
the verified
opencode binary and then pin it: libra agent rpc trust --dir <path>
followed by libra agent rpc trust opencode. Neither step opens the
external-RPC surface (agent.external_agents.enabled stays untouched); the
binary is resolved only from registered trusted directories, never $PATH.
Linux content export additionally requires a trusted bwrap that passes
Libra's descriptor-native --bind-fd safety probe. Unsupported or legacy
bwrap is reported unavailable and fails closed to metadata-only capture;
install or upgrade the system bwrap package rather than enabling an
unsandboxed fallback.
For legacy OpenCode checkpoints, ordinary checkpoint export and the bound
metadata reader remove metadata.anthropic.signature,
metadata.openai.reasoningEncryptedContent and legacy encrypted_content
from reasoning parts and reserved export/checkpoint metadata. Readable reasoning,
other metadata and arbitrary tool input or user JSON remain intact. Provider
classification uses the checkpoint's session catalog; a present metadata kind
must agree. Missing session bindings, inconsistent metadata, duplicate keys,
malformed or unsupported OpenCode JSON, and truncated nonempty exports are
refused with a payload-free diagnostic. Empty transcripts remain valid.
--raw --allow-raw keeps the original bounded bytes and the existing audit;
checkpoint show remains a fixed safe summary. Stored objects are not rewritten,
and future fixes must retain this ordinary-output protection. This legacy
reader does not establish native provenance or implement the newer state.*
reasoning artifact channel.
The macOS local content gate is local_capture_smoke_opencode_macos in
agent_local_capture_smoke_test. It requires an explicit local-agent opt-in,
pins OpenCode 2.0.26, selects volcengine-agent-plan/glm-5.3-flash, and checks
the disposable project before requesting a single fixed file write. The gate
checks captured prompt/model/tokens/files against the source projection,
persisted file metadata, stopped sessions, doctor and uninstall retention.
A failed or timed-out preflight is a failure, with no model request started.
On the current acceptance machine, OpenCode's private server did not report
readiness; real content acceptance is deferred as DEFER-OG-OPENCODE-BOOT-01.
The harness and synthetic tests do not prove real content or native reasoning.
OpenCode exporter core limits
The trusted OpenCode export bridge runs a bounded subprocess.
On Unix, the exporter subprocess and its descendants run with both soft and
hard RLIMIT_CORE set to zero. This suppresses core files for intentional
limit enforcement and unexpected exporter crashes when the system core
handler honors that limit; signal events may still appear in system logs.
Libra retains the exporter exit status and bounded stderr diagnostics. This
child-only setting leaves the parent Libra process and system configuration
unchanged.
Subcommands
| Subcommand | Description |
|---|---|
status |
Report captured external-agent session status |
list |
List agents with their capability matrix (roster, hooks, install state) |
import |
Discover and import historical external-agent transcripts after explicit consent |
graph <session> |
Inspect the read-only capture graph; requires global --json or --machine (the interactive TUI was removed) |
enable |
Enable one or more external agents and install hooks |
add |
Alias of enable: add <name> ≡ enable --agent <name> |
disable |
Disable one or more external agents and uninstall hooks |
remove |
Alias of disable: remove <name> ≡ disable --agent <name> |
session list |
List captured sessions |
session show <id> |
Show a captured session |
session stop <id> |
Mark a captured session as stopped |
session resume <id> |
Mark a stopped captured session active again |
session derive-tool-calls <id> |
Derive tool-call records from a captured session |
checkpoint list |
List captured checkpoints |
checkpoint show <id> |
Show checkpoint metadata |
checkpoint rewind <id> |
Inspect or apply a working-tree rewind for one checkpoint |
checkpoint export <id> |
Export a checkpoint's transcript. Redacted by default (no authorization); raw (un-redacted) export requires --allow-raw --raw and is recorded in the append-only agent_audit_log (LBR-AGENT-013 when refused without it) |
skill search / skill list / skill registry |
Search captured skill events or inspect the curated skill registry |
clean |
Clean up temporary checkpoints from stopped sessions (prune fails closed while a checkpoint write is in flight or the traces ref reaches uncataloged commits; also drops object_index rows made unreachable) |
doctor |
Diagnose hook installation and capture state; detect (and with --repair fix) checkpoint-store inconsistencies. The additive, read-only legacy_code_residue JSON field (human: "Frozen Code residue") reports existing .libra/sessions/code/, .libra/code/, and libra/intent ref residue without deleting or rewriting it |
workspace list / workspace show <id> |
Inspect the read-only workspace registry and lease state |
push |
Push refs/libra/traces to a remote (--force-rewrite for the non-fast-forward push after a clean prune, using force-with-lease) |
rpc list |
List discovered libra-agent-* binaries on PATH (with trusted/quarantined state); requires the external-agents opt-in |
rpc trust <slug> |
Trust a discovered binary — records path + sha256 + device/inode/mtime provenance (refused when its directory is world-writable) |
rpc untrust <slug> |
Revoke binary trust; OpenCode also revokes native issuers atomically (see native-origin rotation and revocation below). Always available, even while external agents are disabled |
rpc invoke |
Invoke one JSON-RPC method on a trusted libra-agent-* binary |
bridge --stdio |
Run the repository-scoped DeepSeek Harness bridge over JSON-RPC 2.0 NDJSON. It is separate from the removed libra code --control surface |
Common Options
| Flag | Subcommand | Description |
|---|---|---|
--agent <name> |
enable, disable |
Select agent names; omit to target the supported roster (add/remove take the names positionally) |
--schema-version <1|2> |
list |
Select the frozen legacy row or version 2 with method availability |
--repo <path> |
graph |
Read capture metadata from another Libra repository |
--limit <n> |
session list, checkpoint list |
Maximum rows per page (default 50, hard cap 500 — larger values clamp with a stderr note; 0 is treated as 1) |
--cursor <cursor> |
session list, checkpoint list |
Opaque keyset cursor from the previous page's next_cursor; do not construct by hand |
--extract-transcript <path> |
session show |
Copy the captured transcript path from session metadata to a local file |
--all |
clean |
Clean all stopped-session checkpoints instead of only the most recent |
--repair |
doctor |
Repair detected checkpoint-store inconsistencies (rebuild stale/missing catalog rows from refs/libra/traces, re-enqueue missing object_index rows); detection-only when omitted |
--remote <name> |
push |
Select the remote used for pushing agent trace refs |
--force-rewrite |
push |
Allow the non-fast-forward push that follows a local clean prune (the traces ref is Libra-managed and rewritten as a whole chain); uses force-with-lease against the last tip this repository pushed — never an unconditional force — so a remote rewritten elsewhere still fails closed |
--dry-run |
checkpoint rewind |
Show the impact without modifying files; this is the default |
--allow-raw / --raw |
checkpoint export |
Authorize + request a raw (un-redacted) export; without --allow-raw a --raw request is refused (LBR-AGENT-013) and audited |
--justification <text> / -o <path> |
checkpoint export |
Audit justification and output file for a raw export |
--gc / --retention-days <n> |
clean |
Retention GC: drop checkpoints from stopped sessions older than agent.retention.transcript_days (default 90; override with --retention-days); never touches agent_audit_log |
--apply |
checkpoint rewind |
Restore the working tree for the selected checkpoint |
Scoped checkpoint resume
review --checkpoint <id> and investigate start --checkpoint <id> materialize ordinary checkpoint files, read-only, under the run directory checkpoint-input/. investigate continue writes that saved spec again only when the repository catalog's ordinary leaves still have the same paths and blob ids. A path reasoning/encrypted/<64 hex> is not ordinary input: it is not written, and a saved spec that names it is refused before the previous input directory is cleared. A saved id that is not a blob, or whose bytes do not hash to that id, is refused before that directory is cleared. If the catalog cannot be opened, queried, or closed, a paused continue returns the existing store error and leaves that run's state and input bytes unchanged. A zero review setup budget ends as the existing infrastructure error and does not launch reviewers; cancel ends as cancelled. No new stable error code is added. Ordinary payload bytes stay capped at 64 MiB per file and 256 MiB total. Each catalog tree read is capped at 16 MiB.
JSON Output
Subcommands that support structured output use the global --json and
--machine envelope. For example:
libra --json agent status
libra --json agent list
libra --json agent graph <session-id>
libra --json agent checkpoint list
libra --json agent rpc list
agent list --json carries a stable schema_version plus one row per known
agent (slug, agent_kind, stability, supported, support_wave,
registered, transcript_readable, hook_installable, installed,
launchable_review, launchable_investigate, external_binary,
config_paths, protected_dirs, capabilities). The row shape is a frozen
contract for automation.
agent session list --json and agent checkpoint list --json return one
page per call: data carries a schema_version, the rows under sessions
/ checkpoints (per-row shape unchanged), and next_cursor — an opaque
token to pass back via --cursor, null once the listing is exhausted.
Pages are ordered newest-first (started_at / created_at descending,
with the row id as tiebreaker).
agent checkpoint show --json additionally reports a layout summary
(e4-libra, legacy-v1 for pre-AG-20 checkpoints, or unknown when the
checkpoint tree is not locally readable) with the manifest roles, the
transcript parts in manifest order, a content_hash format check, and a
transcript availability flag (present/missing/unknown) — derived
without reading transcript blob bodies.
Examples
# Show captured-session counts and recent checkpoint summary
libra agent status
# Show the agent capability matrix (supported roster, hooks, install state)
libra agent list
# Inspect a captured session's read-only graph
libra --json agent graph <session-id>
# Enable Claude Code capture and install its hooks (alias of enable)
libra agent add claude-code
# Enable Claude Code capture and install its hooks
libra agent enable --agent claude
# Enable every supported agent at once
libra agent enable
# Disable Claude Code capture and uninstall its hooks (alias of disable)
libra agent remove claude-code
# Remove legacy gemini hooks (uninstall-only channel; idempotent)
libra agent remove gemini
# Disable Claude Code capture and uninstall its hooks
libra agent disable --agent claude
# List captured sessions
libra agent session list
# Show a session and copy its captured transcript
libra agent session show <session-id> --extract-transcript /tmp/session.jsonl
# Stop a captured session
libra agent session stop <session-id>
# Resume a stopped captured session
libra agent session resume <session-id>
# List captured checkpoints
libra agent checkpoint list
# Page through checkpoints (default 50 per page; JSON carries next_cursor)
libra agent checkpoint list --limit 100
libra agent checkpoint list --cursor <next_cursor>
# Show a single checkpoint by id
libra agent checkpoint show <id>
# Replay a checkpoint as a JSONL transcript
libra agent checkpoint rewind <id>
# Drop temporary checkpoints from the most recent stopped session
libra agent clean
# Drop temporary checkpoints from every stopped session
libra agent clean --all
# Diagnose hook installation and capture state
libra agent doctor
# Read the additive legacy_code_residue diagnostic without changing objects or refs
libra --json agent doctor
# Push refs/libra/traces to the default remote
libra agent push
# Push refs/libra/traces to a named remote
libra agent push --remote origin
# Re-push after `libra agent clean` rewrote the traces chain (force-with-lease)
libra agent push --force-rewrite
# Discover libra-agent-<name> RPC binaries on PATH
libra agent rpc list
# Invoke a single JSON-RPC method on a libra-agent-<slug> binary
libra agent rpc invoke <slug> <method> --params '<json>'
# Run the repository-scoped DeepSeek Harness bridge over stdio
libra agent bridge --stdio < bridge-initialize.ndjson
# Structured JSON envelope for agents
libra agent --json status
The same banner is rendered by libra agent --help so the doc and the
CLI surface stay in sync (cross-cutting --help EXAMPLES rollout, see
docs/development/commands/_general.md item B).
Notes
-
External
libra-agent-*agents are disabled by default. Opt in withlibra config set agent.external_agents.enabled true(repo-local); until thenrpc list/rpc trust/rpc invokerefuse withLBR-AGENT-002(rpc untruststays available — revoking trust only tightens security). Discovered binaries stay quarantined untilrpc trust <slug>records their provenance (trust is refused for a binary in a world-writable directory), every invoke revalidates it (drift revokes trust,LBR-AGENT-005), the child environment is cleared to an allowlist, and stderr is captured/capped/redacted — never inherited. Invoke timeouts, broken pipes and malformed frames map toLBR-AGENT-012; IO hard-cap violations map toLBR-AGENT-007. -
The top-level
agent hooksentry is hidden and intended for hook configs installed bylibra agent enable; users normally do not call it directly. -
checkpoint rewind --applyrestores working-tree files only; the agent's own transcript file is not rewritten. -
Hook and capture diagnostics are best-effort and are designed to report actionable installation state rather than silently ignoring missing providers.
Doctor checkpoint-store repair (--repair)
libra agent doctor scans the checkpoint store for three inconsistency
classes (AG-20 repair matrix); without --repair it is strictly read-only
and reports what --repair would do:
inconsistency_type |
Meaning | --repair action |
|---|---|---|
stale_catalog_row |
An agent_checkpoint row's traces_commit/tree_oid/metadata_blob_oid disagree with the checkpoint still reachable from refs/libra/traces |
Rebuild the row's OID columns from the ref (idempotent UPDATE) |
missing_objects |
Checkpoint objects genuinely missing from the store (and the ref cannot rebuild them) — the check covers the full E4 tree: manifest.json, events/lifecycle.jsonl, transcript/<agent_kind>.jsonl incl. chunks, redaction_report.json, content_hash.txt, the intermediate trees, and every manifest-declared blob |
None — reported manual_required; doctor never takes destructive action (try libra fsck --heal or a cloud/backup restore) |
missing_catalog_row |
A checkpoint reachable from refs/libra/traces has no catalog row (crash window B) |
Re-INSERT the row via the writer's probe-first idempotent path, reconstructed from the commit's metadata.json (v1 and v2 shapes) |
missing_object_index |
Checkpoint objects missing from object_index (invisible to libra cloud sync) — covers the traces commit plus the full E4 object set |
Idempotent re-insert with the writer's row semantics (trees as tree, transcript blobs as agent_transcript, sidecars as blob) |
Additional rules:
- Legacy-v1 checkpoints (pre-AG-20 layout without
manifest.json) are counted inlegacy_v1_checkpoints, never enter the three classes, and are never rewritten by--repair. - Checkpoints named by a live traces in-flight marker are writers mid-flight, not inconsistencies, and are skipped.
- A session without checkpoints is legal (an active session before its first stop) and is never flagged; only checkpoint-without-session counts as an orphan.
- Captured gemini rows stay readable and are never flagged; leftover
gemini hook configuration produces a hint pointing at the
uninstall-only channel (
libra agent remove gemini). - All repairs are idempotent — running
doctor --repairtwice performs no work the second time. With--repair, oneagent.doctor.repairtracing span is emitted per repair attempt (inconsistency_type,repaired,manual_required); transcript content never reaches the log.
Private native-origin issuer registration (macOS)
Ordinary agent rpc trust opencode pins an exporter binary; it does not register an issuer or prove native reasoning. The native path requires the separately installed, reviewed 2.0.26-libra-native.1 macOS arm64 producer. Enable the OpenCode observer with the actual Libra executable, then prepare a fresh owned installation using that private bundle's initialization instructions. Global OpenCode remains independent.
libra agent rpc trust --dir /absolute/approved-private/bin
libra agent rpc trust opencode
libra agent enable --agent opencode
libra agent rpc trust opencode \
--native-origin-manifest /absolute/private-installation/installation.json \
--native-origin-expected-epoch 0
The two native options must be supplied together and only with the literal opencode slug. Initial registration expects epoch 0; later registration requires the current repository registry epoch. Inspect libra config --get agent.native_origin.opencode.v1 locally before an explicit retry. A conflict refuses without changing trust or registry. The registry includes local installation paths and should remain local.
The public descriptor must be a regular, non-symlink installation.json, owned by the current user with mode 0600 in a canonical owned 0700 directory, at most 64 KiB and in the private producer's closed minimal JSON format. Libra does not read the private key. Existing exporter trust, actual approved producer bytes, the current canonical Libra executable path and exact installed .opencode/plugin/libra-hooks.js bytes must match. A descriptor or export cannot authorize its own path, public key, endpoint or build.
The actual producer must successfully answer a new random, domain-separated Ed25519 challenge within 30 seconds, with at most 4096 stdout bytes and bounded captured stderr. Child output is withheld on failure. After the challenge, one write transaction rechecks current exporter trust and trusted directories, performs expected-epoch CAS, and writes one complete registry row. Duplicate rows, case aliases, encryption, malformed records and size overflow refuse without repair. Limits are 64 KiB and 128 issuer records; revoked history is never removed to make space.
A new independent installation key becomes active; earlier active keys become verify-only. Existing issuer keys cannot be reactivated by registration or ordinary binary re-trust. Historical records remain immutable. Successful registration proves installation key/binary association only. Receipt signature, current issuer permission, source coordinates and original native field checks remain required before any archive admission; unknown or unproven sessions stay partial. JSON registration output includes the transient current Libra executable SHA256 for local audit; this measurement is neither a signed policy field nor a pinned historical Libra version.
OpenCode native-origin rotation and revocation
To rotate an installation key, prepare a new independent private installation and explicitly register it with the current epoch. The earlier active issuer becomes verify-only. Verify-only and revoked issuers cannot authorize new native capture, import or pending replay. The current permission reader requires one transaction snapshot, fresh independently measured producer provenance, matching exporter trust and a trusted directory; it returns installation data, not a verified receipt or native artifact.
libra agent rpc untrust opencode now removes OpenCode exporter trust and revokes every remaining active or verify-only issuer in one bounded write transaction. It preserves all records and already stored artifacts. It remains available while external RPC is disabled. Malformed or duplicate registry rows, capacity/epoch failures and write faults refuse without a partial trust or registry update. Check and preserve the local registry before retrying; it is never automatically repaired. A repeated successful untrust is idempotent and does not advance an already revoked registry epoch.
JSON retains slug and removed (removed means an exporter trust row was removed). OpenCode additionally returns native_revoked (the number newly revoked) and native_epoch (the resulting epoch, or null when no registry exists). Other slugs retain their existing output and behavior.
If combined untrust refuses because the registry is damaged, suspend exporter access with libra config unset agent.trust.opencode. This removes binary trust only and preserves the registry, including all tombstones. A still-active issuer can regain permission after the same approved binary is explicitly retrusted. Repair the registry while preserving its records, then successfully run combined libra agent rpc untrust opencode for permanent native revocation.
Automatic provenance revalidation after an unreadable or changed binary or withdrawal of its trusted directory still removes only exporter trust. Native admission pauses while that trust is absent or mismatched; it leaves the issuer registry unchanged. Explicitly trusting the same reviewed build again can restore an active issuer that was never explicitly revoked. Ordinary binary trust never restores a verify-only or revoked issuer. Re-registering an old issuer is refused: rotation requires a fresh independent key. Registration/revocation do not rewrite historical receipts, private installation descriptors or immutable artifacts. Successful lifecycle operations do not prove native field origin; unproven content stays partial.
Current private OpenCode acceptance baseline (NPR-18)
The unique macOS arm64 acceptance build is 2.0.26-libra-native.1, build
bac21cc4027896b8d1836133c347d20f, SHA-256
547c36eb928da163ef61d019bad669860d519f2da0b67737c9a3920e831c9196
and 187635570 bytes. It is based on official OpenCode 2.0.26 commit
9b4ec5714d481559990db0a816d5dec19541a814. That commit identifies the official
base; the separate source, patch, lock and build-input digests identify the
patched build. The public native-origin-build.json descriptor contains those
reviewed identities and no installation policy, issuer or private key.
Set LIBRA_OPENCODE_NATIVE_BINARY to the absolute path of that independently
installed private opencode before macOS local capture acceptance. The harness
requires the reviewed version, build digest and size before login or any model
request, bounds the version and login probes to 30 seconds, and puts the same
private binary directory first in each capture/export child's PATH. Missing
opt-in or drift fails the gate; it never falls back to global OpenCode.
The official global installation and existing observer ABI remain separate.
NPR-12's SOURCE_READY_GO covers this reviewed darwin-arm64 build and the current
OpenAI Responses transport mechanism. The existing official source record,
event/export fixtures and synthetic receipt/signature vectors remain historical
and unchanged. Source A is UNPROVEN: deterministic tests, a version string,
registration and this descriptor do not prove real native provider fields or
permit reasoning archival. Failed readiness or quota gates stay partial; the
only authorized paid smoke model is volcengine-agent-plan/glm-5.3-flash, with
no alternate-model fallback. This card makes no new model calls. Linux local
functional acceptance remains with the operator.