CLI 0.1.9 includes the selected harness's tier/model candidates in routing, caps each outgoing history window at 64 KiB, and streams history projections and SQL stats rows to reduce memory use. It fixes literal native task arguments, transient version probes, and inconclusive verifier outcomes, and preserves pending recordings during maintenance. Exported SQL snapshots remain restorable within the existing 8 MiB record limit.
Native contract tests use actual pinned Codex/OpenCode executables with local responses: reviewed hooks, cancellation, provider rejection, resume with a changed model, and OpenCode foreground subagents. They do not establish live-provider task-solving accuracy or every interactive/background workflow.
Record schema 6, SQL schema 1, configuration, and automatic history reuse are
unchanged; feedback and extra verification remain optional. Node SDK 0.1.3 stays
compatible without a new npm release. Rust core users should review the new
JevError::UnknownHarness variant when matching errors exhaustively.
CLI 0.1.8 fixes live Claude capture, adds preview-first Codex hook review and
harness health --require-events, and improves native startup and OpenCode
tool-failure recording. It also rejects special history inputs, bounds JSONL
records and provider responses, and improves recovery and cleanup performance.
Record schema 6, SQL schema 1, and recording/verification defaults are unchanged.
Node SDK 0.1.3 remains compatible; no SDK upgrade is needed for these CLI fixes.
Back up oversized history before explicit maintenance: streamed JSONL physical
lines are now limited to 8 MiB and are never silently skipped or truncated.
CLI 0.1.7 adds bounded-memory JSONL updates, consistent routing snapshots,
passive-history SQL indexes, bounded replay and lock waits, recording maintenance,
terminal-safe application output, routing explanations, and structured storage
checks. Node SDK 0.1.3 adds checkStorageReport() for CLI 0.1.7 or newer.
Record schema 6 and SQL schema 1 are unchanged; automatic recording/history use
and optional feedback/verification keep their existing defaults.
jevia runs record-execution <run-id> --json reads a single bounded JSON object
from stdin (harness, requested model, duration_ms, optional exit_code, and
optional events). Node SDK 0.1.2 exposes recordExecution() with the same fields
and requires CLI 0.1.6 or newer.
Call only after app-owned work has stopped. This is optional; it does not launch
an agent, run verification, or require feedback. jevia run already records its
own execution and must not be reported again through this API.
The operation records one completed application-owned attempt. Its outcome stays
unknown unless separately assessed; existing manual feedback remains unchanged.
Observations are explicitly sourced as application, not trusted native hooks.
An exact retry is idempotent; conflicting snapshots, legacy runs without an
explicit routed lifecycle, active runs, and existing native executions are
rejected. JSONL, SQLite, and PostgreSQL apply the same atomic storage contract.
Later routing automatically includes the passive summary and invalidates cached
decisions based on older history. No history plumbing or cache clearing is needed.
Inputs are limited to 256 events / 256 KiB, allowlisted identifier fields, safe
integer timestamps/duration, and an optional signed 32-bit exit code. Raw text,
tool inputs/outputs, arbitrary event fields, outcome labels, and verifier evidence
are rejected. The new application source uses record schema 6 (older schemas
remain readable); upgrade all readers/writers together. See the
SDK example.
Run jevia harness health codex (or claude / opencode, using your configured
adapter name). Add --json for the versioned, redacted report. It shows the current
capture mode/configuration separately from the most recent matching execution in
the last 100 stored runs: source, capture status, cumulative events, discarded
inputs, sampled-event timestamp, and actionable advice. ok means inspection
succeeded, not that capture is complete or the task succeeded.
This command reads your selected JSONL, SQLite, or PostgreSQL storage but never
launches a harness/version probe, contacts a model, replays journals, or runs
verification. jevia harness check remains the offline static preflight. An empty
window, legacy record, or no_events status is not proof of a broken adapter.
In particular, Codex hooks may need normal /hooks trust review; diagnostics do
not bypass it or claim to know that trust is the cause. Current config may differ
from the saved run. Raw prompts, events, model/session identifiers, commands,
credentials, and underlying storage error details are omitted.
Final journal read failures preserve the most recent checkpoint and mark capture partial. Terminal state writes cannot replace newer durable observations with an older snapshot. Unreadable, corrupt, or subsequently changed journals remain on disk for recovery; cleanup only removes a journal matching the saved snapshot. This does not infer task success or run additional verification.
Project-local .jevia/.gitignore rules cover history, caches, native journals,
loss markers, journal-checkpoint temporary files, event locks, and generated
adapter plugins. config.toml and the ignore file itself remain trackable so
policy can be reviewed. Before native capture creates artifacts, Jevia repairs
missing rules in older projects without requiring init --force or changing
configuration. Existing comments/custom rules are retained; cooperating writers
are serialized and updates are atomic.
If ignore-rule repair fails, native capture stays unavailable and process-level
recording continues; no native journal/plugin is created by that attempt.
Git ignore rules prevent ordinary accidental additions, not access to local data.
They do not untrack files already committed or staged, delete existing files, or
override explicit force-adds; custom Git rules can also negate exclusions.
Review any previously tracked .jevia runtime data
separately. Retained journals can contain allowlisted model/session/tool metadata
even though raw prompts and tool contents are not captured.
In CLI 0.1.6, jevia stats / jevia stats --json includes a separate
observations section over the same bounded history window. It reports coverage
(recorded, partial, no_events, unavailable, disabled, unsupported, or
legacy not_reported), active checkpoints, whole-session event counts, sampled
runs, and per-observed-model run/event counts. Requested aliases are never used
as attribution. Events lacking a reported model remain unattributed; models beyond
the 128-group report limit contribute to omitted-model counts. The report signals
group truncation and counters saturated at JavaScript's maximum safe integer.
Tool errors and model switches are operational facts, not task failure rates. Existing verified/manual outcome metrics are unchanged; there is no inferred per-model success score or latency attribution. No task text, session/agent IDs, commands, or transcripts enter the report. Reporting is read-only, including for live checkpoints, and uses whole-session totals when present (legacy samples remain supported). No feedback or extra verification is needed for these metrics.
CLI 0.1.8 jevia run enables native capture automatically for supported direct
executables (including .exe names). It probes --version with a five-second
deadline (15 seconds for the slower OpenCode launcher) before adding a session-local adapter. Probes own a process group/job,
accept at most 256 bytes of successful UTF-8 output, and stop descendants on
failure, timeout, or cancellation. Failed probes allow up to one additional
second for cleanup and never expose captured output. No user/project config is
rewritten. Set observations = "off" to disable native capture; process recording
stays on. Other harnesses, including Gemini, retain process facts only.
CLI 0.1.9: transient probe exit/read/wait/deadline failures are retried once, only after the first process group/job is confirmed stopped. Each attempt keeps the deadline above and up to one second for cleanup (at most 12 seconds for Claude/Codex or 32 for OpenCode). Missing or inaccessible executables, oversized or non-UTF-8 output, unsupported versions, and unconfirmed cleanup do not retry. Diagnostics identify the failure category without printing subprocess output. There is no persistent support cache: replacing an executable triggers a fresh check on the next run. A failed probe still preserves process recording, reports native capture as unavailable, and never invents events or a success outcome.
| Harness | Auto-detection contract | Capture and limits |
|---|---|---|
| Claude Code | 2.x >= 2.1.212 | Silent exec-form hooks; preserves custom --settings, --bare, and --safe-mode by skipping injection. Managed settings may disable hooks. Version 2.1.212 was verified with a real file-read task and session/tool/turn events. |
| Codex | 0.158.x stable or the tested 0.158.0-alpha.2, macOS/Linux | Inline session hook overrides. exec/review run locally; interactive launches get --no-daemon to isolate the journal environment. Existing -c/--config, --disable, remote/attach/server arguments skip injection. Windows stays process-only. |
| OpenCode | v1 >= 1.18.33, < 2 | Private dependency-free .mjs plugin appended through OPENCODE_CONFIG_CONTENT; existing valid JSON overrides and plugin entries are preserved. Invalid/JSONC inline overrides, --pure, and remote/attach/server launches stay process-only. |
Compatible wrappers can explicitly set observations = "claude_hooks",
"codex_hooks", or "opencode_plugin" in their harness table. These bypass the
version probe, not platform/config safety checks; the wrapper must honor the same
arguments, environment, and event contract. Unknown future Codex minors are
deliberately not auto-enabled until checked against the adapter contract.
Codex hook trust: review Jevia's hooks using /hooks before expecting native
events. Jevia never bypasses trust, enables disabled hooks, changes approval
policy, or installs global configuration. The command definition stays stable
across runs; changing Jevia's executable path can require renewed trust. Skipped
hooks can leave no_events even when process recording works. The
official hook contract describes trust and
event fields. Codex PostToolUse becomes neutral tool_completed, because it can
also fire for nonzero shell exits. Interrupt is turn_interrupted, not task
failure. Reported model IDs attach only to the event that contains them; no
cross-subagent model-switch inference is made.
For the standard Codex preset, use jevia harness review codex to preview the
review flow, then jevia harness review codex --launch in a terminal. This opens
a local read-only Codex session with the same Jevia hook definitions. Open
/hooks, inspect the capture-event commands and approve only those you accept,
then quit. Jevia submits no task, routes nothing, and does not save this review
session as task evidence. Only Codex persists your explicit trust choice. The
preview does not execute anything; custom presets and disabled capture are not
silently rewritten. Use the same installed Jevia binary for review and runs:
changing its path or hook definitions can require renewed review.
Regular Codex observation hooks allow five seconds for cold process startup;
SessionEnd and Interrupt use the harness's three-second maximum. Jevia never
adds --dangerously-bypass-hook-trust automatically. A live test using an
explicitly approved one-run bypass confirms adapter dispatch, not persisted
trust for later runs.
The run summary reports actual capture coverage (observations=recorded,
no_events, unavailable, partial, disabled, or unsupported) and the
observed event count. Saving process metadata does not mean native events
were captured. A zero-event run warns explicitly; it remains an unknown task
outcome, even when the process exits zero. recorded means some events arrived,
not proof of complete coverage or a successfully solved task.
After cargo build --release -p jevia, run the real-provider smoke check with
existing authenticated harness CLIs and TYPESAFE_API_KEY in the environment:
JEVIA_LIVE_TEST=1 node scripts/live-harness-smoke.mjs claude
JEVIA_LIVE_TEST=1 JEVIA_LIVE_CODEX_PROFILE=/path/to/isolated-profile JEVIA_LIVE_CODEX_MODEL=your-model node scripts/live-harness-smoke.mjs codex
JEVIA_LIVE_TEST=1 JEVIA_LIVE_OPENCODE_MODEL=provider/model node scripts/live-harness-smoke.mjs opencodeThis makes potentially paid API calls, uses a disposable synthetic project,
and prints the path to its actual runs.jsonl. It never injects synthetic
events or bypasses hook trust. A successful process with zero native events
fails the check. It requires both a tool event and turn completion, and
leaves the project and recording available for inspection. It checks harness
health and makes a second live classification to verify automatic history reuse
without feedback or extra verification. All tiers use the
same selected harness model to isolate capture behavior; this is not a model
quality benchmark. The Claude call has a $0.50 budget; all have a 90-second
harness deadline. The separate CI native-contract tests use loopback model
responses and are not evidence of a successful live-provider run.
For Codex, authenticate the isolated profile with your authorized credentials,
run the smoke script with --prepare, then open jevia harness review codex --launch in the printed project with CODEX_HOME pointing to that profile. Use
the same Jevia executable when reviewing and testing. Review the capture-event
commands, approve only those you accept, exit, and rerun without --prepare.
Do not use --ignore-user-config for this test: it also discards saved hook trust.
Neither the smoke script nor Jevia bypasses trust or approves hooks automatically.
OpenCode error tool parts produce tool_failed facts; repeated updates for the
same part are counted once. The adapter retains at most 1,024 opaque failed-part
IDs per session; beyond that it reports partial capture instead of guessing
counts. Error text, tool arguments, and tool output are not stored. These are
tool-level errors, not assessed task failures. Child PWD is synchronized with
the configured project directory for probes, interactive, and supervised runs.
Install CLI 0.1.9 with cargo install jevia --version 0.1.9 --locked and confirm
jevia --version. Alternatively, build this source with
cargo build --release -p jevia. The smoke script defaults to
target/release/jevia; set JEVIA_TEST_BINARY to the absolute installed binary
path to test that copy. Complete Codex's hook review with the same binary, run a
small real task, and then check the saved event coverage:
jevia harness health codex --require-events
jevia harness health claude --require-events
jevia harness health opencode --require-events--require-events exits nonzero when no matching execution exists or its capture
is empty, unavailable, disabled, unsupported, or partial. The saved recording must
also identify a native source (claude_hooks, codex_hooks, or opencode_plugin);
application/SDK events and records without a source do not satisfy this check.
SDK recording and feedback remain optional, and recorded application history
continues to inform routing. With --json, the
report schema stays unchanged: ok describes reading the report, while the exit
status additionally enforces the event requirement. This checks the latest saved
execution, not the current configuration, a fresh launch, all possible event
types, or task correctness. Inspect the run ID so an old successful recording
cannot be mistaken for the run you are demonstrating. Do not advertise a harness
as live-verified merely because its contract tests or process exit succeeded.
OpenCode uses its plugin API and
runtime config override. The adapter contract
is covered by fixtures against the
v1.18.33 hook types.
chat.params produces model_observed for the model selected for that request,
not proof of a provider completion. tool.execute.after produces neutral
tool_completed; tool output is never interpreted. Session created/idle/error
events and submitted messages provide activity boundaries; streaming message
updates are ignored to avoid counting each update as an attempt. There is no
guarantee of tool-error, subagent-completion, model-switch, or session-end coverage.
Private plugin files are removed after terminal persistence. A crash may leave
an inert jevia-observer-*.mjs file alongside the retained journal; replay does not
execute it. Native adapters are contract-tested with local fixtures, not a claim
of exhaustive live-provider coverage.
execution.observations contains a source, coverage status, the most recent 256
allowlisted events, and whole-session totals. Counters continue after the event
sample fills. totals.models attributes event counts only to models explicitly
reported on those events; missing models stay in unattributed_event_counts.
At most 32 model identifiers are retained. Further models contribute to
omitted_model_event_counts and set models_truncated, without unbounded growth.
When totals are present, each sampled event must fit its named-model,
unattributed, or omitted-model counter. Contradictory attribution is rejected by
history reads/imports and the Node SDK; it is never silently reassigned or repaired.
Legacy observations without totals remain readable.
Model switches are observations, not failures. Counts are observed activity, not
task scores; partial capture/legacy truncated journals provide lower bounds.
Supported events include session/turn boundaries, tool
success/failure or neutral completion, reported task completion, subagent boundaries, and session model
changes. A model is saved only when explicitly present in an event; configured
execution.model remains the requested model. No outcome is inferred from these
events. Tool success and an agent marking a task complete are not proof of a fix.
The Claude hook contract
does not report temporary per-turn fallback-chain substitutions via model-switch
hooks. Do not treat these observations as a complete model-attempt ledger, token
accounting, or proof of which model solved a task. recorded means some events
arrived, not that all activity was captured. unsupported, disabled,
unavailable, no_events, and partial expose other coverage states.
Hook envelopes are capped at 8 MiB, including trailing whitespace. Large tool
bodies no longer discard otherwise valid metadata merely for exceeding 64 KiB.
The decoder borrows raw field spans instead of allocating JSON trees for tool
content; only allowlisted identifiers of at most 256 ASCII bytes, event kinds, and
ingestion timestamps are retained. The envelope buffer is transient and bounded.
Prompts, assistant messages, tool arguments,
tool output, transcript paths/files, and error bodies are not stored. Malformed or
oversized envelopes (including duplicate metadata keys) are discarded and counted;
detected gaps mark capture partial. Invalid optional identifiers are omitted.
The raw event sample rolling over does not stop aggregation. Routing receives the
whole-session counts and bounded model identifiers, with summary_truncated when
the raw sample or model details were bounded. Journals are atomically replaced
under stable striped locks, so a torn replacement leaves the previous checkpoint.
Hooks never return agent instructions or deny permission. Lock contention, hook
timeouts, and asynchronous events after session exit can lose events: capture is
best-effort, not an audit log.
When a hook detects a failed write (including lock contention), it attempts to
create one private, empty .loss sidecar beside its journal. The next checkpoint
or replay reports partial coverage and adds one unconfirmed input to
discarded_inputs, regardless of repeated failures. This means at least one
capture attempt failed; a write may have reached disk before reporting an error,
so it is not an exact count or proof that an event is absent. Re-reading does not
increase that count; recorded events and task outcomes remain unchanged. No
raw input is queued. The marker and journal are removed only after the matching
snapshot is saved. If storage also prevents the marker, the hook emits a fixed,
redacted diagnostic and still exits zero. A killed hook or an event arriving after
cleanup can remain unobservable; this is not a guarantee of complete capture.
The OpenCode plugin also attempts this marker when its collector cannot start, exits unsuccessfully, loses its input pipe, or exceeds its 1.5-second timeout. A timed-out collector gets a short termination grace period before forced stop. Marker writes validate a bounded, regular OpenCode journal and never store the failed payload. If marking fails, the plugin warns once per session with a fixed, redacted message and still allows the agent to continue. Abruptly stopping the plugin/harness itself can prevent this accounting; capture remains best-effort.
A private journal under .jevia/jevia-events-<run-id>-*.jsonl is checkpointed into
the selected JSONL/SQLite/PostgreSQL run record while the harness runs (at most once
every two seconds when observations change), and saved again when it stops.
Checkpoint failures do not fail the harness; the synced journal remains available.
Pending checkpoints do not suspend process supervision: non-interactive timeouts
and cancellation continue to stop the owned process tree. JSONL checkpoints skip
a busy history lock and retry later; final history persistence can still wait for
that lock after the process has stopped. Delayed supervisor checkpoints cannot
overwrite a terminal run.
Before the next route/run, Jevia makes a bounded, best-effort replay attempt for
retained journals, skipping runs whose execution lease is still held. Replaying a
cumulative snapshot does not duplicate events, alter feedback, or mark a run
complete: loss of the supervisor is not proof its child stopped. Active journals
remain available for later events. Read-only stats/runs show do not replay.
runs recover also replays after its existing lifecycle safety checks (including
PostgreSQL's --confirm-stopped). Journals are removed only after terminal
persistence; corrupt, ambiguous, or unavailable journals are retained for inspection.
Replay retains at most 128 candidate runs (two journal names per run suffice to
detect ambiguity), with a two-second total budget before routing. It enumerates
the complete directory before acting, without a fixed directory-entry ceiling;
this is not an unbounded repair job.
The same budget applies to recovery replay. Busy journal/history locks are skipped
immediately, not waited on once per journal; an expired attempt retains its files
for a later invocation. File scanning and journal/history reads run off the async
task so the replay timer remains responsive.
Since CLI 0.1.7, a private atomic cursor in .jevia/replay-state/
rotates this candidate window between invocations, including past busy, corrupt,
or ambiguous attempts. Concurrent replay passes do not race the cursor; explicit
runs recover <id> does not move it. The two-second budget still applies.
Incomplete directory scans (including a read error or exhausted budget) defer replay
without deleting anything, because an unseen duplicate could make a journal
ambiguous. Slow directories may still require explicit inspection/maintenance; the cursor is
not an unbounded background repair service or a guarantee against slow storage.
Routing receives bounded event counts and model summaries, not session IDs/raw events.
In CLI 0.1.7, replay's JSONL workers also check the remaining budget between read chunks and records, after decoding, and before publishing a checkpoint rewrite. Expiry releases the history lock and discards unpublished temporary output; the journal remains available for retry. This is cooperative cancellation, not a hard real-time guarantee: a blocking filesystem call, decoding one large record, or an atomic publication already in progress cannot be preempted. Required routing history still validates completely; a replay timeout never substitutes partial history or invents an outcome. Ordinary readers reuse their line buffer as well.
Cache lock acquisition waits at most 500 ms per operation; a busy routing cache
falls back to a live request without overwriting that cache. JSONL history lock
acquisition waits at most two seconds per operation, then returns an explicit
run history busy error. Required history is never silently replaced by an empty
window. This also bounds lock acquisition for writes and maintenance; a failed
terminal write retains the journal and may require explicit recovery after the
other writer finishes. Locks are never force-unlocked or deleted.
These are lock-acquisition budgets, not whole-command, filesystem-I/O, SQL-query,
or harness deadlines. Cache expiry is checked after loading the locked cache.
New records use schema 6 (schemas 1–5 stay readable). Older CLI versions reject newer schemas rather than silently erasing metadata. Back up history and upgrade all clients sharing a store together to CLI 0.1.6 and Node SDK 0.1.2. SQL database schema 1 is unchanged. Do not downgrade clients against updated history.
Finished jevia run executions automatically inform subsequent routing even without
feedback or a verifier. Jev receives two separate, bounded windows: known outcomes
and passive execution observations (requested model, harness, elapsed time, process
exit, and lifecycle state). Each uses router.history_limit; pending and active
runs do not crowd out either window. Observations that change the supplied context
invalidate stale routing cache entries. Stored task text follows the existing privacy setting.
CLI 0.1.9: routing also limits each history window to 64 KiB of serialized
JSON (128 KiB combined, including array punctuation). Historical task text is a
UTF-8-safe prefix of at most 2,048 bytes, explicitly marked task_truncated
when shortened. Within each count window, newer records get priority; a record
that cannot fit is omitted, and smaller older candidates can still fit. No
records beyond router.history_limit are fetched to backfill omissions. Jev
receives history_budget counts and instructions not to treat missing context
as a failure. Both known outcomes and passive observations remain automatic.
The CLI reuses one bounded projection snapshot for routing, cache keys, and
diagnostics. JSONL still validates the full stream under one shared lock. Small
histories are projected in one pass; after a count window fills, only byte offsets
are retained for later candidates. Selected records are reread from the same open
file under the same lock. Projection work is capped at twice history_limit
per window, rather than scaling with all eligible records; validation remains
linear in retained history size. SQL streams selected rows from one consistent snapshot. Full task
text and feedback history are not retained in the routing windows. The existing
Rust slice-based APIs remain available, alongside RoutingCandidate,
RoutingHistory, route_with_history, and route_cache_key_with_history for
streaming integrations. See scripts/benchmark-routing-history.mjs for a
repeatable synthetic before/after memory check; it makes no live model calls.
scripts/benchmark-jsonl-projections.mjs compares release binaries on small and
large JSONL histories, alternates timed runs, and asserts identical provider
request bytes. It uses only a synthetic loopback provider.
This affects only outbound historical context, not saved history, the current task, or the prompt passed to a harness. It is not a cap on the entire request (current task/configuration are separate), storage record size, or memory needed to read stored records. The shared core projection applies to the CLI, Node SDK with the updated CLI, and Rust client.
In CLI 0.1.7, both windows come from one consistent history snapshot. Concurrent feedback cannot move an attempt between categories midway through the read. JSONL validates the full file under a shared lock and retains only the two bounded windows; SQL uses a read snapshot without holding a project write lock.
A process exiting zero or nonzero leaves task outcome as unknown; its exit code
is still recorded and returned by the CLI. A known outcome requires optional manual
feedback or an explicitly requested verifier. Historical process-derived labels
remain readable but are not promoted into quality evidence. The configured model
is labeled requested_model in passive routing context, not an observed model.
This is the complete CLI and operations reference. Start with the project README or the product documentation for the shorter installation and integration path.
CLI 0.1.7 escapes control characters in human-readable routing/run metadata, feedback confirmations, and harness names. Imported values cannot add terminal commands or spoof extra output lines through these displays. Stored values, harness arguments, and JSON/SDK responses retain their original contents; output streamed directly from a child harness is not filtered. Application error chains and cache warnings are escaped at their final rendering boundary, including unknown-harness names and filesystem errors. Human-readable project/backup/archive paths are escaped without changing the paths used for filesystem operations. Ordinary quotes, backslashes and Unicode stay readable in these diagnostics.
Jevia is an outcome-aware model router for coding agents. It asks Jev for a typed routing decision, applies a deterministic safety policy, and records the eventual result so later decisions can use evidence from earlier runs.
Jevia is experimental. The current milestones establish the CLI, routing contract, local outcome store, Jev integration, and generic harness execution. The managed control plane remains separate.
Most model routers classify a task and immediately forget what happened. Jevia closes that loop:
- describe stable capability tiers rather than hard-coding model names;
- ask Jev which tier should handle the current task;
- fall back to a configured safe tier when confidence is low;
- record the routing decision in the configured history store;
- automatically record execution facts and supported native events for
jevia run; - include passive history and optional known outcomes in future routing decisions.
The application owns the policy. Jev supplies a structured decision signal.
Jev routing responses are limited to 1 MiB, including chunked responses and responses without a content-length header. An oversized response fails safely without caching a decision or recording a routed run. Request timeouts still apply.
Use the copyable installer on the Jevia landing page. It downloads a checksum-verified prebuilt binary; Rust and Cargo are not required. On macOS, Linux, or WSL:
curl -fsSL https://jevia.dev/install.sh | sh
jevia --version
jevia init
export TYPESAFE_API_KEY="your-key"
jevia check
jevia route "investigate an intermittent distributed-lock failure"On native Windows, use PowerShell 5.1 or newer, then run the same jevia
commands:
irm https://jevia.dev/install.ps1 | iex
jevia --version
jevia init
$env:TYPESAFE_API_KEY = "your-key"
jevia check
jevia route "investigate an intermittent distributed-lock failure"jevia check makes one live Jev request and requires a valid API key. Use
jevia doctor for configuration/storage checks without a Jev API request.
PostgreSQL storage checks do connect to the configured database.
To install the exact crates.io release with Rust 1.92 or newer:
cargo install jevia --version 0.1.9 --lockedTo try unreleased development changes instead:
cargo install --git https://github.com/assistant-ui/jevia --locked jeviaAfter configuring your installed harness once, use
jevia run for the end-to-end flow:
jevia run codex "fix the failing test"
jevia runsJevia routes the task, launches the agent, and saves execution facts automatically.
No manual feedback or runs complete step is needed. Recorded observations
and optional known outcomes inform later routing. The name codex must match your configured adapter;
Jevia does not install or authenticate the agent for you.
CLI 0.1.6 default change: additional verification is now opt-in. Recording
still happens automatically. CLI 0.1.4–0.1.5 enabled test discovery by default;
CLI 0.1.6 only discovers tests when auto_verify = true is explicitly
configured. See automatic CLI pipeline
for detection, overrides, and verification limits.
jevia route (used in the connection quickstart above) selects a tier but does
not execute an agent or verify a task. If your integration knows the result of
work executed outside jevia run, it can optionally report that outcome:
jevia feedback <run-id> success
jevia runsMachine-readable output is available for integrations:
jevia route --json "fix a typo in the README"
jevia runs --json| Command | Purpose |
|---|---|
jevia init |
Create .jevia/config.toml and local store rules. |
jevia harness presets |
List the built-in Codex, Claude Code, OpenCode, and Gemini CLI command templates. |
jevia harness setup <name> |
Preview an explicit harness template; back up and save only with --apply. |
jevia harness check <name> [--json] |
Inspect configuration and local executable candidates without launching programs or calling APIs. |
jevia harness review <name> [--launch] |
Preview or explicitly open a read-only native Codex hook-review session; never auto-approve trust. |
jevia harness health <name> [--json] [--require-events] |
Inspect recent saved capture; optionally fail if native events are missing or partial. |
jevia route <task> |
Ask Jev for a tier and record the decision. |
jevia run <harness> <task> |
Route, launch, and record automatically; additional verification is opt-in. |
jevia runs |
Inspect recent records in the configured backend. |
jevia stats [--limit <records>] [--json] |
Summarize recent routing decisions, verified outcomes, manual feedback, and cache hits. |
jevia feedback <id> <outcome> |
Report externally verified work or manually correct an outcome; not required after run. |
jevia runs complete <id> <outcome> --confirm-stopped |
Explicitly finish external work with manual evidence. |
jevia doctor |
Validate configuration, credentials, and configured storage. |
jevia storage setup <sqlite|postgres> |
Preview database setup; explicitly apply after validation, backup, and optional JSONL import. |
jevia storage init |
Explicitly initialize an opt-in database schema and project. |
jevia storage check |
Check storage without needing a Jev API key. |
jevia storage check --deep |
Inspect all history records and SQL routing/order metadata without a write probe or repair. |
jevia storage import-jsonl [--from <file>] [--apply] |
Preview/import local history into a database without changing the source. |
jevia storage export --output <file> |
Export history to a new JSONL snapshot; never overwrite a file. |
jevia check |
Validate configured storage and complete a live Jev routing round trip without storing a run. |
jevia cache status |
Inspect routing-cache settings and entry counts. |
jevia cache clear |
Remove cached decisions without touching run history. |
Run jevia <command> --help for command-specific options.
The human-readable runs listing reports verification=pass only for a launched
verifier with exit code 0, and fail only for a launched verifier with a nonzero
exit code. Missing exit status (including timeout, cancellation, or a signal) and
launch failures remain unknown; no configured verification is none. This
display does not change saved outcomes, lifecycle state, or JSON output.
jevia stats
jevia stats --limit 500
jevia stats --jsonstats reads the configured JSONL, SQLite, or PostgreSQL history without calling
Jev, launching a harness, changing outcomes, or reading the decision-cache file.
It needs no Jev API key; PostgreSQL still requires its configured database
connection. Initialize an opted-in database with jevia storage init first.
This command requires v0.1.2 or newer.
The default window is the latest 1,000 records in append order, not a date
range or an all-time total. --limit accepts 1–100,000. The report says when older
records were excluded; archived records are not included. Stats aggregate each
record without retaining the window's full task, feedback, and event payloads.
SQL reads are project-scoped and paged in batches of at most 200 records within
one consistent snapshot. CLI 0.1.9 SQL stats decode and discard each row as it
arrives instead of materializing a whole page; bounded driver prefetch still
contributes to memory usage. JSONL counts nonblank lines, then scans and validates
the full file under the same shared history lock and file handle, decoding each
record once. Working memory depends on an input line/driver buffer and the
aggregate groups, not the combined payload size of the requested window. Tier
groups remain complete; reported model groups retain their existing 128 limit.
Run node scripts/benchmark-stats-memory.mjs BEFORE_BINARY AFTER_BINARY on Linux
or macOS for a synthetic, credential-free comparison. It measures peak RSS and
checks identical stats for JSONL and SQLite with 200 records containing 512 KiB
task strings. Results are local measurements, not a fixed memory guarantee.
Totals and per-tier groups use the selected tier recorded at routing time, including tiers since removed from configuration. Tiers are not concrete model identities: changing a harness's model mapping does not split historical groups. Each record counts once, using its current outcome and provenance:
- Verified success rate: verifier-backed successes divided by verifier-backed successes plus failures. Manual feedback, process-exit-only results, active runs, unknown outcomes, and legacy outcomes without provenance are excluded. A configured verifier's result is not a guarantee of task correctness.
- Manual feedback: separate success/failure counts. Correcting a verified outcome with manual feedback moves that record to the manual group; prior feedback events and the old verifier result are not counted again.
- Learning evidence: known, non-active verifier-backed or manual outcomes, using the same eligibility rule as routing. This is the eligible count in the stats window, not necessarily the smaller evidence window sent to Jev.
- Cache hits: recorded cached decisions divided by all records in the window,
not current cache occupancy or a count of API calls. Bypassed/disabled-cache
decisions still count in the denominator. Legacy records without a decision
source use the existing
livedefault. - Other outcomes: process-exit-only and unattributed known outcomes, plus active and unknown counts. Active takes precedence over unknown, so the outcome groups partition the records without double-counting.
Rates with no eligible observations display n/a, not 0%. The JSON report uses
schema_version: 1, storage, window (limit, order, has_older_records),
totals, and a tier-keyed tiers map. Rates are fractions from 0 to 1, or null
when their denominator is zero. verified, manual, process_exit, and
unattributed each contain successes and failures; active and unknown
are separate counts. Output excludes task text, run IDs, feedback notes,
execution commands, and connection URLs; historical tier labels are included.
These are descriptive, potentially small or biased samples—not a model ranking, a controlled benchmark, or proof that adaptive routing improves results. No cost savings are estimated because token/cost telemetry is not recorded.
jevia init leaves harness selection to you. Jevia includes shell-free command
templates for Codex, Claude Code, OpenCode, and Gemini CLI. List them, then preview
one with explicit model IDs for every configured tier:
jevia harness presets
jevia harness setup codex --preset codex \
--model fast=your-fast-model \
--model balanced=your-balanced-model \
--model strong=your-strong-modelThe built-in presets currently render these non-interactive argument arrays:
| Preset | Command and arguments |
|---|---|
codex |
codex exec --model {model} {task} |
claude |
claude --print --model {model} {task} |
opencode |
opencode run --model {model} {task} |
gemini |
gemini --model {model} --prompt {task} |
Presets do not choose model IDs, install the harness, alter its permission policy,
or bypass its prompts. Review the preview, ensure the selected harness version
supports the shown flags, then repeat with --apply. Use harness check afterward
to validate the local executable candidate without launching it.
For another harness or a different invocation shape, provide an explicit argument template instead:
jevia harness setup agent --command my-agent \
--arg=run --arg=--model --arg='{model}' --arg='{task}' \
--model fast=provider/small \
--model balanced=provider/standard \
--model strong=provider/frontierSubstitute your agent's actual executable, argument syntax, and accessible model
IDs. Repeat the same command with --apply after reviewing its TOML preview.
Setup never launches either
program, calls Jev, opens storage, or checks provider credentials/model access.
It works offline, including when a configured database is unavailable. There
is no interactive prompt or automatic agent installation. Quote placeholders as
shown and use --arg=--flag / --verify-arg=--flag for leading-hyphen arguments.
- Preview changes no files. Apply shares a configuration lock with database setup,
saves a private exact-byte backup in ignored
.jevia/config-backups/, then atomically replaces the config after checking for concurrent edits. It preserves unrelated settings, harnesses, and comments, and rejects symlink configs. Stop concurrent manual config editing; the lock only coordinates Jevia setup commands. - Changing an existing harness also requires
--replace. Reapplying identical settings does not rewrite the config or make another backup (apply may create the config lock sidecar). The selected harness entry is rewritten when changed. - Automatic test detection and persistent opt-out behavior are available in
CLI 0.1.4. Omitted verifier options preserve an existing verifier and automatic-detection
setting. Since CLI 0.1.6, new adapters default to recording without extra tests. Use
--no-verificationto disable both explicit and automatic checks, or--auto-verificationto remove a custom verifier and re-enable detection. Supplying--verify-commandreplaces its whole command and argument list (for example,--verify-command cargo --verify-arg=test). Without verification, process success alone is not eligible learning evidence. Missing/duplicate/unknown tier mappings and unsupported template placeholders are rejected before config replacement. - Commands, arguments, and model IDs appear in previews and committed config. Never put credentials in these flags or templates; let the agent inherit its credentials from the environment. Protect retained config backups, especially with appropriate directory ACLs on Windows. Nothing is shell-expanded by Jevia.
jevia harness check agent
jevia harness check agent --jsonPreflight validates the project config and selected adapter, renders its templates
for every configured tier, rejects NUL arguments, and checks file candidates for
the agent and configured or automatically detected verifier. It requires no
Jev/provider key or database
connection, does not read history/cache, and creates no files or locks. It never
executes even a --version probe. Missing executables, model mappings, or valid
templates produce a failing exit status. Verification disabled by choice/default
is a passing check; an explicitly requested check that cannot be detected is a
warning. Process success alone is not proof of task correctness.
The human report escapes the requested harness name. JSON reports use
schema_version: 1, harness, scope: "static", ok, checks (stable id,
status, code, and explanatory message), and limitations. Once a project
is found, failed checks also produce JSON and exit nonzero. CLI argument errors
and missing projects retain normal CLI diagnostics. Reports omit configured
command paths, arguments, model IDs, credentials, and raw parse/driver errors.
Lookup checks explicit paths or the inherited PATH; it does not expand shell
aliases, variables, ~, or PATHEXT. Unix relative paths/PATH entries are checked
against the project root, with regular-file and execute-bit checks. On Windows,
bare names may omit .exe; non-.exe extensions must be explicit. Preflight
requires absolute explicit paths and absolute PATH entries on Windows, and warns
that it does not search extra system/application directories. This intentionally
conservative check is not a complete reproduction of OS executable resolution;
use an absolute path if lookup is ambiguous. Windows batch wrappers get a warning
because Rust launches them through cmd.exe.
An ok result means static checks passed, not that an agent is authenticated
or will successfully launch. Binary format, interpreters, mount/ACL restrictions,
agent-specific flags, provider model access, and task correctness are not tested;
files and environment may change afterward. Preflight does not change jevia run
or the existing jevia check live routing probe.
Harness adapters are shell-free process templates. Add a harness to
.jevia/config.toml and map every capability tier to a concrete
model:
[harnesses.agent]
command = "my-agent"
args = ["run", "--model", "{model}", "{task}"]
[harnesses.agent.models]
fast = "provider/small"
balanced = "provider/standard"
strong = "provider/frontier"
# Optional: uncomment only if you want extra verification after execution.
# [harnesses.agent.verification]
# command = "cargo"
# args = ["test", "--workspace", "--all-features"]A complete ready-to-copy configuration is available at examples/jevia.toml.
Then route and run a task through that adapter:
jevia run agent "investigate the failing integration test"Extra harness arguments must follow -- and are appended without
shell interpretation:
jevia run agent "update the parser" -- --verboseFor a task beginning with a hyphen (for example, a pasted Markdown checklist), use the explicit equals form. The usual positional form remains supported:
jevia run claude --task="- Fix the parser" --non-interactive -- --verboseSupply either a positional task or --task=..., not both. Jevia's -- still
introduces extra harness arguments. For exact built-in Claude, Codex, and OpenCode
presets, all tasks are placed after the harness's option delimiter, so even words
such as attach, serve, or web cannot be mistaken for capture options.
Gemini uses --prompt=... for leading-dash tasks,
with extra options before the task. Custom wrappers/templates are not rewritten;
configure their own literal-argument convention. A standalone - can still mean
stdin to a native harness; use descriptive task text instead.
Templates support {task}, {model},
{tier}, and {run_id}. Jevia requires the task and
model placeholders, rejects unknown placeholders, launches the configured
executable directly, and mirrors its exit code. A non-zero harness exit skips
verification. Without a verifier or explicit feedback, both zero and non-zero
exits leave task outcome unknown, while retaining useful execution observations.
Jevia runs the configured or detected verifier only after the harness succeeds. A normal verifier exit of zero records success; a normal non-zero exit records failure. A verifier that cannot start, times out, or terminates by signal leaves the outcome unknown, preventing an inconclusive check from incorrectly training the router. Existing records are not rewritten. Verification arguments support the same placeholders and are also launched directly without shell interpretation.
Completed harness runs record the requested model, harness name, duration,
process exit code, optional verification, and available native observations.
Inspect jevia runs --json. A requested model or a passing verifier
does not establish which internal model attempt produced the fix.
Use the typed jevia npm package when a Node application or agent framework
owns harness execution. It calls the CLI's shell-free JSON interface, keeping
routing policy, storage, caching, and outcome handling in one implementation:
npm install jeviaimport { JeviaClient } from "jevia";
const jevia = new JeviaClient({ cwd: process.cwd() });
const task = "investigate the failing integration test";
const route = await jevia.route(task);
const model = {
fast: "provider/small",
balanced: "provider/standard",
strong: "provider/frontier",
}[route.tier];
const result = await runYourHarness({ task, model, runId: route.run_id });
// Optional: report a known result from your own adapter, without a verifier.
if (result.outcome === "success" || result.outcome === "failure") {
await jevia.feedback(route.run_id, result.outcome);
}
// Automatically uses eligible outcomes already in the project's storage.
const next = await jevia.route("investigate another integration failure");The adapter can call Codex, Claude Code, OpenCode, Gemini CLI, Cursor Agent,
Copilot CLI, Aider, Goose, Amp, or a custom harness. Jevia returns a capability
tier; the application maps that tier to a harness-specific model. Feedback and
verification are optional: route() works without either. If feedback is omitted,
the decision stays recorded with outcome unknown, and later routing still uses
other eligible outcomes. The optional result.outcome field above comes from your
own adapter; Jevia does not infer task success from a process or function return.
The CLI must already be installed and available on PATH; npm installation does
not run a binary downloader.
The SDK does not require Jevia's built-in verifier: your application decides how
to establish the outcome and records it. manual evidence means explicitly
reported by the application or user, not necessarily human-entered. Each
route() automatically loads recent eligible successes/failures from the
selected JSONL, SQLite, or PostgreSQL history before deciding. No history argument
or manual cache clearing is needed; the evidence is part of the cache key.
Finished process-only runs inform a separate observation window, even while their
task outcome is unknown. Active and routed-only runs are not execution observations.
The [router].history_limit setting bounds each window (default 20, maximum 100;
0 disables it). This supplies evidence to Jev, not model training. See the
SDK outcome loop
for provenance and privacy details.
The client exposes version, route, feedback, runs, and show. Record
responses are validated at runtime, including supported schema versions,
probabilities, timestamps, lifecycle state, execution evidence, and feedback.
Malformed or unsupported responses raise JeviaProtocolError without including
their contents.
setupStorage(target, options?) and checkStorage(options?) in jevia@0.1.1
provide the same explicit, preview-first SQLite and PostgreSQL administration as
the CLI. They require CLI 0.1.2 or newer. Apply
requires confirmStopped: true, JSONL import remains explicit, PostgreSQL accepts
an environment variable name rather than a URL, and deep checks do not write or
repair. See the Node.js package reference for
the complete typed examples and failure guarantees.
JeviaCommandError exposes a generic message, exit code, and signal for ordinary
logging. Raw command, stdout, and stderr are available only through explicit
getters for private debugging and may contain tasks or credentials; do not send
them to logs or telemetry.
After configuring your harness once, use the normal command:
jevia run codex "fix the failing test"Jevia routes the task, launches the agent, and records lifecycle, process facts,
and supported native events automatically. Later routing uses this history without
requiring a known task outcome. No manual feedback or runs complete step is
required. Optional feedback may report a known outcome or correct an earlier one;
external completion is for work executed outside the supervised CLI flow.
Additional verification is opt-in. When explicitly enabled, it runs once after the
agent process/session finishes successfully, not after each internal tool call.
Recording itself is language-independent: Python, Go, and mixed-language projects
need no test configuration for passive history. Optional checks can use explicit
commands such as python -m pytest, go test ./..., or your project's test script.
Task execution may still require the agent's normal permission prompts. Installing
the agent, supplying credentials/model mappings, and preparing project dependencies
are one-time prerequisites, not per-run feedback tasks. Jevia does not retry or
repair failed work automatically.
If you opt in with auto_verify = true and have no explicit verifier, Jevia
detects existing tests at the project root. The default in CLI 0.1.6 is false:
- Rust:
cargo test --workspacefor a root Cargo package/workspace. - Node: the existing
testscript, usingpackageManager, then an unambiguous lockfile, then npm. npm, pnpm, Yarn, and Bun are supported. Empty scripts and common placeholder/no-op scripts are not selected.
Automatic checks run with CI=true, no stdin, owned process-tree cleanup, and a
five-minute deadline even if the agent was interactive. To override the deadline,
use --non-interactive --verification-timeout-seconds <seconds>. Jevia does not
install a test runner or package manager. The existing Cargo/package-manager test
command may build/download dependencies as it normally does; use trusted projects.
An explicit [harnesses.<name>.verification] always wins. For mixed Rust/Node
roots, unsupported projects, invalid manifests, or conflicting lockfiles, Jevia
reports that automatic verification is unavailable instead of guessing. The run
is still recorded, but process-only results are not verified learning evidence.
Configure a suitable check only if you want extra verification. harness check <name> previews
detection and executable availability without running tests. Passing tests means
the selected checks passed—not a guarantee that every requirement was satisfied.
Test discovery is available since CLI 0.1.4. Since CLI 0.1.6, omitted
auto_verify means no extra tests; existing explicit true values and custom
verifiers remain honored. Earlier setup commands wrote auto_verify = true, so
use harness setup ... --no-verification --replace --apply or set it to false
and remove any custom verifier to stop those previously configured checks.
The Node SDK's route, feedback, and complete remain explicit and flexible;
they never launch an agent or run project tests automatically.
Execution progress is separate from task outcome. New records track routed,
running, verifying, completed, launch_failed, or interrupted, with start
and finish timestamps. A completed process may still have a failed task outcome.
jevia runs show <run-id>
jevia runs recover <run-id>show prints the complete record as JSON. recover explicitly marks a formerly
running/verifying execution as interrupted only if no Jevia supervisor holds its
per-run lease. It leaves the task outcome unknown and never reruns or terminates
processes. After a supervisor crash, inspect any surviving child processes and
workspace changes before starting new work. Legacy unknown outcomes are not
assumed to represent interrupted executions. Feedback on active runs is refused.
The CLI 0.1.7 JSONL lookup retains only the requested record while validating
the full history under its shared lock. runs show and journal replay no longer
load all records into memory. Reads remain linear in file size and still report
corrupt/unsupported records anywhere in the file; busy background replay defers
without waiting on a writer. This does not change stored history or SQL lookups.
New and updated records use schema version 6; versions 1–5 remain readable.
Older CLI versions refuse newer schemas rather than silently discard new metadata.
The ignored run-leases/ sidecars are retained so concurrent processes always
coordinate on the same lock file.
When you use route and run your own agent, ordinary feedback updates the
outcome but deliberately leaves the run pending. After all external work and
verification have stopped, explicitly finish it:
jevia runs complete <run-id> success --confirm-stopped
# A changed known outcome requires an explanation:
jevia runs complete <run-id> failure --confirm-stopped --reason "Tests still fail"Available in CLI 0.1.4, this command atomically records manual feedback and a
completed lifecycle in JSONL, SQLite, or PostgreSQL. The
finish timestamp is when completion was recorded; start time and harness evidence
remain absent because Jevia did not observe execution. unknown is also accepted
when work stopped but the result is inconclusive; it does not become learning evidence.
Only pending external records qualify. Active/terminal runs, supervised evidence,
held execution leases, and SQL supervisor ownership are refused. This command
does not stop processes, verify work, retry tasks, or bypass recovery. In the next
CLI release, identical completion retries (same outcome and trimmed reason) return
the saved external completion with its original timestamp and no duplicate
feedback. Conflicting retries and subsequent corrections are refused. A request
that races an active lease may need a later retry. Older CLIs require inspecting
runs show after an uncertain response. Completed records become eligible for normal preview-first archival;
other pending and active records remain protected.
For a headless harness, opt into owned process-tree supervision:
jevia run agent "fix the parser" --non-interactive --timeout-seconds 300 --verification-timeout-seconds 120Each deadline applies only to its execution phase, not the Jev routing request.
Both flags require --non-interactive and accept 1–86400 seconds. Unspecified
deadlines are unlimited. This mode disables stdin and uses a Unix process group
or Windows job object; stdout/stderr still stream normally. Ctrl-C (and SIGTERM
on Unix) stops the owned group/job and records cancelled; a deadline records
timed_out. Outcomes remain unknown, failed/cancelled harnesses skip verification,
and verification cancellation preserves the harness evidence. Exit codes are 130
for cancellation and 124 for timeout. Cleanup errors record interrupted instead
of claiming the process tree was stopped.
The main command exiting does not finish a supervised phase while background processes remain in its group/job. Jevia waits for them before starting verification or recording completion, and the phase deadline and cancellation remain active. The main command's exit code is preserved; background commands must report their own failures to the main command (or the verifier) if they should affect the outcome.
CLI 0.1.9: live recording checkpoints carry a one-second work budget into JSONL workers, including queued workers whose async waiter was cancelled. Slow scans or rewrites stop between chunks/records without publishing partial history; the journal remains the retry source. This prevents an abandoned background rewrite from monopolizing the history lock while the supervisor saves terminal state. Blocking operating-system I/O and decoding a single record are not preemptible; this is a cooperative work bound, not a hard filesystem-latency guarantee.
Without this flag, existing interactive terminal behavior remains unchanged. This is not a sandbox: descendants that deliberately escape a process group/job, SIGKILL of Jevia, and machine crashes cannot be handled reliably. Use explicit recovery and inspect the workspace in those cases; no work is automatically retried.
jevia run saves this evidence automatically. The manual feedback examples below
are for externally verified work, corrections, or legacy records—not a required
step after each CLI run.
Run records distinguish process_exit, verification, and manual evidence.
Legacy process-only success/failure remains visible, but only known outcomes from a
completed verifier or explicit application or human feedback are supplied to Jev as learning
evidence. Legacy outcomes without provenance are not silently promoted; confirm
them with feedback if you want them used in routing. runs reports the source
and whether the result is eligible as quality evidence. Finished executions can
still contribute passive observations independently of that quality label.
jevia feedback <run-id> success
jevia feedback <run-id> failure --reason "The integration test still fails"
jevia runs show <run-id>Changing an already-known outcome requires a nonempty --reason. Every feedback
operation retains the prior outcome/source, timestamp, and optional reason in a
audit trail in the selected backend; original execution evidence is preserved. Reasons are limited
to 4096 bytes and are never sent to Jev. Setting the outcome to unknown removes
it from the known-outcome window; any finished execution facts remain eligible as
passive observations. These records are not a tamper-proof audit log.
Use jevia route "task" --explain or jevia run agent "task" --explain to
inspect routing facts. This requires CLI 0.1.7 or newer. Explanation lines go
to stderr, before harness launch; --json stdout and saved run records keep
their existing format. No explanation is printed unless requested.
jevia: explain cache=miss:not_found coordination=acquired write=stored
jevia: explain known_outcomes=2 passive_observations=8 history_limit_per_kind=20 history_stage=candidates_before_byte_budget
jevia: explain source=live confidence=0.94 floor=0.65 fallback=not_applied elapsed_ms=120
known_outcomes counts the eligible outcome candidates within the count window,
before the byte budget. passive_observations counts the separate window of
finished executions without eligible outcome evidence, including process-only, unknown, and partial
capture. A run is not counted in both windows. Active/routed-only executions are
not passive history. Feedback and additional verification remain optional, and
recorded history is included automatically. On cache hits these are the inputs
considered when building the cache fingerprint, not a new provider request.
These are candidate counts, not a claim that every record was transmitted:
byte limits can omit records or shorten historical task text. The projection's
history_budget in the provider request reports included/omitted counts.
Cache status distinguishes hit, miss:not_found, miss:expired, disabled,
bypassed, unavailable, and key_unavailable. Coordination reports
not_needed, acquired, waited, timed_out, or unavailable; cache writes
report stored, skipped, or failed. A fingerprint miss cannot identify which
input changed. Confidence/floor and fallback=below_confidence_floor describe
the policy applied to the returned signal, not the model's internal reasoning.
Elapsed time includes startup replay and routing, but not harness execution.
Explanation lines contain only fixed labels and numeric facts: no task text, model/tier names, credentials, record IDs, session IDs, or cache fingerprints. This does not suppress ordinary CLI/harness output or change task-text storage and provider privacy settings. A failed route does not print a successful decision explanation or create a synthetic run.
CLI 0.1.9: jevia run <harness> supplies Jev with current_harness.name and
current_harness.tier_models, containing only that harness's configured models for
the declared tiers. This lets routing distinguish the current candidate models from
historical models with the same tier labels. Commands, arguments, verifier settings,
and unrelated harness definitions are not sent. Candidate names are not execution
evidence, pricing data, or proof of capability; confidence fallback is unchanged.
Both the provider request and cache fingerprint use this context. Changing a model
mapping invalidates the matching decision; existing entries safely miss once after
the cache fingerprint upgrade. No history is removed.
Plain jevia route (including SDK route()) remains harness-agnostic and does not
infer a harness from history. SDK run() receives the same context as CLI run.
Rust callers can opt in with JevClient::route_for_harness; the existing route
method keeps its signature and harness-agnostic behavior.
Jevia caches equivalent routing decisions locally so repeated work does not always require another network request. The default policy keeps up to 256 decisions for 15 minutes:
[cache]
enabled = true
ttl_seconds = 900
max_entries = 256A cache key is a SHA-256 fingerprint over the exact task, Jev endpoint and model, routing policy, tier definitions, selected harness mapping, and the recent outcomes and passive observations actually sent to Jev. A new observation, success, failure, verification result, policy change, model change, or harness change produces a miss when it changes these inputs. The fingerprint uses the same bounded history projection and budget metadata as live routing. Changes confined to omitted content or a truncated task's discarded suffix do not invalidate an otherwise equivalent decision. Pending outcomes also do not invalidate it. The byte-budget update advances the cache fingerprint version; existing entries safely miss once without deleting history.
Cache files contain the fingerprint and decision signal, not task text. Every
hit receives a fresh run ID and timestamp, and run records expose
source=live or source=cache. Use
--no-cache on jevia route or
jevia run when a forced live decision is needed.
Cache errors never block routing: Jevia reports the problem and falls through
to a live request. API errors are never cached, expired decisions are never
used as an offline fallback, and jevia cache clear provides an
explicit recovery path for a damaged cache.
Concurrent equivalent cache misses normally share one live routing request.
Waiters recheck both the cache and current learning evidence before using a
decision; they still receive independent run IDs. Coordination uses up to 256
stable lock stripes in the ignored cache-leases/ directory, so lock files do
not grow per task. Unrelated requests can occasionally share a stripe and wait.
No global history/cache lock is held during network calls. An OS lease is
released if its owner exits; failures are not cached, so another caller can try.
Waiting is bounded to the configured Jev timeout plus one second (at most 30
seconds). On expiry or a coordination error, routing proceeds live; duplicate
requests are possible in that fallback. --no-cache skips coordination too.
JSONL remains the default. SQLite and PostgreSQL are opt-in alternatives; changing
the backend does not synchronize or automatically move existing history.
The normal route, run, runs, feedback, doctor, and check commands use
the selected backend. These options require v0.1.2 or newer.
Streaming JSONL history, health checks, imports, and cache reads accept at most 8 MiB per physical line (including its newline; an unterminated final line must leave one byte for that newline). Oversized lines fail with a redacted error and are never truncated or skipped. JSONL appends and rewrites also reject oversized output before publication. Existing oversized history must be inspected and reduced explicitly; this does not bound the total memory of arbitrary SQL rows. CLI 0.1.9 JSONL repair/archive streams payloads but still keeps a set of unique run IDs for duplicate detection.
The guided CLI path avoids editing TOML by hand (run jevia init first):
jevia storage setup sqlite --path .data/jevia/history.db --import-jsonl
# Stop all Jevia writers/supervisors using this workspace, then:
jevia storage setup sqlite --path .data/jevia/history.db --import-jsonl --apply --confirm-stopped
jevia storage check
jevia statsThe first command previews without changing project files or contacting a database.
Guided SQLite and PostgreSQL setup stream history into a private temporary
snapshot that is removed on close. Memory scales with the largest record and
the set of run IDs needed to detect duplicates, rather than the entire history.
Apply imports only that validated snapshot and rechecks a streaming SHA-256
fingerprint of the original bytes before import and before switching config.
This detects source changes; it does not replace the requirement to stop writers.
Without --path, SQLite uses .jevia/jevia.db. --path accepts another
project-relative or absolute local file; relative paths are resolved from the
discovered project root even when invoked from a subdirectory. Protect and ignore
custom paths outside .jevia yourself. An empty JSONL project can omit
--import-jsonl; a nonempty one must include it to avoid silently abandoning
existing evidence. The source JSONL file is never deleted or rewritten.
Or configure manually:
Add to .jevia/config.toml:
[storage]
backend = "sqlite"
url = "sqlite://.data/jevia/history.db"Then explicitly initialize and optionally import your old JSONL history:
jevia storage init
jevia storage check
jevia storage import-jsonl
jevia storage import-jsonl --apply
jevia runsRelative file paths are resolved from the project root, not the current working
directory. SQLite is bundled into the binary. It uses WAL, full synchronous writes,
a five-second busy timeout, and private file permissions on Unix for new databases.
Use a local disk, not a shared/network filesystem. Default .db files, WAL/SHM
sidecars, and run locks under .jevia are ignored after init/storage init.
For custom paths/extensions, protect the directory and add your own ignore rules;
on Windows, protect the directory with the appropriate filesystem ACLs.
Provision a dedicated PostgreSQL database and put its connection URL in your
secret manager or environment as JEVIA_DATABASE_URL. Do not put passwords in
the project config or CLI arguments.
jevia storage setup postgres --project my-project --import-jsonl
# Stop all Jevia writers/supervisors using this workspace, then:
jevia storage setup postgres --project my-project --import-jsonl --apply --confirm-stopped
jevia storage check--url-env MY_DATABASE_URL selects a different environment variable name, not
a URL value. Preview does not resolve that variable or test connectivity. On apply,
the existing TLS and timeout rules apply; --allow-insecure-localhost is available
only for loopback development databases. The command creates the Jevia schema and
project, not a PostgreSQL server, database, or user.
The equivalent manual configuration is:
[storage]
backend = "postgres"
url_env = "JEVIA_DATABASE_URL"
project = "my-project"Run jevia storage init once with schema-creation permissions, then
jevia storage check. Normal operation needs read/write access to the
jevia_projects and jevia_runs tables and read access to jevia_schema,
not permission to create databases. Remote connections require certificate and
hostname verification (sslmode=verify-full); sslrootcert, sslcert, sslkey,
and application_name URL options are supported. Only local development can opt
into plaintext using allow_insecure_localhost = true and a loopback host.
Use a direct or session-pooled connection, not a transaction-mode pooler: execution guards use PostgreSQL session advisory locks. Each CLI invocation uses a small pool; running a harness also holds a dedicated guard connection.
Use the same project value across trusted workspaces to share evidence. This
namespace is not authorization or tenant isolation: anyone with access to the
database tables can access other projects. Separate database roles/databases or a
future authenticated managed API are needed for mutually untrusted users.
SQLite and PostgreSQL 16+ use a database-maintained partial index for finished executions without a known assessed outcome. The latest observation window is selected in SQL, then returned in append order. Pending/active runs and known outcomes do not crowd out these observations or require a full scan before a routing cache lookup. Feedback, lifecycle updates, imports, and archival update the index transactionally, including writes from older clients that can read the stored record schema. Automatic history use and optional verification/SDK feedback are unchanged; the index is not a new success signal.
New database setup creates the index. For an existing database, back up and run
jevia storage init during a quiet maintenance window with schema permissions.
This explicitly builds the index over existing rows without rewriting records,
ordering, ownership, or sequence counters. SQL schema 1 and record schema
6 are unchanged. Normal routing/diagnostics do not create indexes, and stores
without this index remain usable but may scan more rows. Building the index can
block writers and is subject to the existing five-second database timeout; a
failed initialization rolls back rather than switching storage or dropping data.
Resolve contention before retrying; a build that exceeds the timeout even while
idle needs a separately planned maintenance operation, not repeated routing calls.
PostgreSQL before 16 retains the compatible paginated lookup without this index.
In CLI 0.1.7, storage check, storage check --deep, doctor, and
check also report the passive index as present, missing, unavailable,
unsupported (PostgreSQL before 16), or not applicable (JSONL). Missing-index
guidance points to the explicit initialization above; diagnostics never build or
replace an index. Catalog checks also recognize the expected filtering predicate,
not just the index name/columns. Unexpected or unrecognized predicates report
unavailable; diagnostics never execute catalog SQL or silently rebuild indexes.
Recognition is conservative: a manually rewritten equivalent expression or a
new PostgreSQL catalog rendering may require inspection rather than report present.
This is not a proof of query-plan selection or a general SQL equivalence check. The
original storage health result remains separate: a missing performance index is
not data corruption. SDK checkStorage() returns the additional human-readable
line without changing its API.
Available in CLI 0.1.7 and Node SDK 0.1.3.
jevia storage check --json
jevia storage check --deep --jsonJSON mode emits one report on stdout, exits 0 when ok is true and 1 when a
check fails. Argument errors still use the normal CLI usage error (exit 2).
Report schema 1 contains backend (jsonl, sqlite, postgres, or null before
configuration is available), check (basic or deep), ok, records,
passive_history_index, and error. Unavailable counts/index status are null,
not zero or missing. Index statuses are present, missing, unavailable,
unsupported, and not_applicable; a missing/unexpected index does not itself
make a successful storage health check fail.
Failures use static messages and one of configuration_unavailable,
storage_unavailable, history_check_failed, or index_check_failed. Reports
contain no paths, project names, URLs, credentials, run IDs, or record contents.
They summarize sequential checks, not one atomic database-wide snapshot. The
existing basic/deep guarantees below apply; neither mode initializes storage or
repairs records/indexes, and no Jev credential or request is needed.
Node SDK 0.1.3 adds checkStorageReport({ deep?: boolean, signal? }).
It validates schema and report/exit-code consistency and returns typed healthy
or failed reports; check report.ok. Process, timeout, cancellation, and
protocol errors still throw. This method requires CLI 0.1.7 or newer;
older CLIs fail explicitly rather than falling back to parsing text.
checkStorage() remains the unchanged human-readable API.
Routing validates the selected SQL history windows, not every unrelated record.
Malformed JSON remains an index candidate and fails closed if selected. Use
jevia storage check --deep for full-store integrity validation; the optimization
does not replace that diagnostic or repair corrupt history.
storage setup is preview-first. Applying requires both --apply and
--confirm-stopped: stop all source writers and supervisors, including scheduled
jobs and other workspaces using the source file. Recover any active run records
before retrying; this command does not stop processes or recover runs for you.
Apply backs up the exact old config to a new .jevia/config-backups/config-*.toml
file, initializes/checks the destination, imports requested history transactionally,
then atomically replaces config last. Routing, privacy, cache, harness settings,
and unrelated TOML comments are preserved. Config permissions are retained;
new backups are private on Unix and added to local ignore rules. Backups are not
automatically removed. On Windows, protect the directory with appropriate ACLs.
Active, duplicate, malformed, unsupported, or conflicting imported records cause failure. Identical destination records are skipped for safe retries. Setup does not replace config on connection, schema, permission, or import failure. It serializes other setup invocations and checks for changes to the source/config before switching, but cannot prevent an editor or already-running supervisor from writing: the stop-writers requirement is not optional.
The database and filesystem are not one atomic transaction. A failed setup
can leave an initialized database, a config backup, or (if the final config save
fails) imported records. Inspect config, keep the original JSONL and backup, and
retry only after reconciling concurrent changes. A crash after replacement may
mean config was already switched; verify with jevia storage check. Never blindly
restore old config once new work has written to the database, since histories can
diverge. No automatic synchronization, rollback deletion, or backend fallback is
performed.
Once configured, repeat the same setup command without --import-jsonl to
initialize/check the same target without rewriting config or adding another backup.
Old JSONL files may be stale, so importing them from an already-SQL project needs
the separate explicit storage import-jsonl command. Changing between SQL targets
or back to JSONL is not supported by guided setup; use explicit export/import and
review the configuration change yourself.
Changing the value of the PostgreSQL URL environment variable can independently
change the destination; setup cannot detect which database it previously named.
- Database writes are transactional. Feedback history and its current outcome change together; project-scoped write locks prevent lost updates. Retention holds the same lock while saving recovery files; schedule it during a quiet period.
- Recent history and eligible evidence use indexed, bounded queries in append order. Complete versioned records preserve execution and feedback provenance.
storage checkverifies schema and CRUD permissions with a rolled-back probe; it does not insert fake evidence.doctor/checkinclude this access check. SQL records are not individually decoded by the default access check.storage check --deepinstead inspects the complete selected history without a write probe, automatic repair, Jev request, or cache access. JSONL validates record schemas and nonempty/unique run IDs under the shared history lock, streaming records while retaining an ID set (memory grows with the IDs). SQL streams records within 200-row keyset pages in one consistent read snapshot (without collecting page payloads) to validate record schemas, indexed run IDs, learning flags against current evidence rules, and positive append ordinals bounded by the project's append counter. Gaps left by retention are valid; the counter need not equal the newest retained ordinal. Only the configured PostgreSQL project is inspected. Ordinary SQL writers can continue, though a long scan may delay database cleanup/WAL recycling.- A deep-check failure exits nonzero and identifies the line or append-position where possible, without printing task text, IDs, or database credentials. Keep the current history and backups and investigate locally before making changes; no records or indexes are silently rewritten. Success means the inspected snapshot passed these logical checks, not that write permissions, physical database integrity, or task-outcome correctness were verified. Run the default access check separately when needed; database-native integrity checks and backups remain the operator's responsibility. Missing storage is not initialized.
- Database/record schema versions are checked; unknown versions are rejected.
Record timestamps, durations, and observation counters must be nonnegative
integers no greater than
9007199254740991(Number.MAX_SAFE_INTEGER), matching the Node SDK's JSON contract. Reads, deep checks, and imports reject values outside that range without rounding or rewriting the source history. Keep the original file/database and inspect invalid values locally before correcting them. Driver errors are redacted and database operations have five-second timeouts. An outage never silently switches history back to local JSONL. - Imports preview by default and commit all-or-nothing with
--apply. Identical run IDs are skipped; conflicting records, duplicate source IDs, active runs, or malformed/unsupported records abort the import. Stop source writers first. Keep the unchanged source as your backup; no automatic bidirectional sync or background replication is provided. storage import-jsonlvalidates and streams the source into a private unnamed temporary file before taking a database write lock. It holds the source's shared JSONL lock during capture, then imports only the captured records in one database transaction. Later changes to the source are not included; preview and apply capture independently. Both modes need temporary disk space for the normalized history in the OS temporary directory (use protected directory ACLs on Windows). Memory grows with the run-ID set plus the largest record, not all task bodies; the ID set is released before database writes. Snapshot failures prevent writes; later read errors or conflicts roll back all inserts and their ordering counter. The temporary file is removed on close/process exit, not kept as a backup. Imports still normalize known fields and omit unknown additive fields. Large imports hold the project write lock until commit/rollback (SQLite serializes all database writers); this is not a resumable or chunk-committed import. Guidedstorage setup --import-jsonlstill captures its migration source in memory.jevia storage export --output .jevia/snapshot.jsonlwrites a new private snapshot in append order. It validates and writes one JSONL or SQL record at a time, without collecting SQL page payloads. Driver prefetch buffers and the largest record still require memory. JSONL holds its shared history lock; SQL uses one consistent read snapshot across all pages (PostgreSQL repeatable-read/read-only, SQLite WAL snapshot) without taking the project write lock. SQL changes committed after the snapshot begins appear in a later export, not partway through this one. Very large records still require memory, and a long SQL snapshot can delay database cleanup/WAL recycling.- Export writes to a private temporary file beside the destination, validates all
records, flushes/syncs the file, and publishes without overwriting any existing
path, including symlinks. Handled read/write failures do not publish a partial
destination. The parent directory is synced on Unix; if that final sync fails,
the error says the complete file was already created. A process crash can leave
a private
.jevia-export-*.tmpfile. Protect and ignore exports and their output directory; they may contain task text. On Windows, use appropriate directory ACLs. Exports normalize known record fields, omit unknown additive fields, and are logical record snapshots, not exact-byte or physical database backups. - The decision cache and cache-miss coordination remain local. Every routing attempt fetches current eligible evidence before computing its cache key, so new shared outcomes invalidate affected decisions. Cross-machine request deduplication and offline write queues are not included.
- SQLite run locks sit beside the canonical database path. PostgreSQL guards
block recovery while the supervisor's database session is alive. Because a
lost session does not prove its subprocess stopped, PostgreSQL recovery also
requires
jevia runs recover <id> --confirm-stoppedafter inspecting and stopping the original supervisor and any surviving processes. Recovery is terminal and fences late writes from that supervisor; it never reruns work. There is no automatic lease expiration or remote process termination. runs archivesupports all three backends with preview-first, backup-first retention (see below).runs repairremains JSONL-only: database integrity repair and physical backups require database-native tooling.- Managed hosting, managed credentials, and a dashboard are not part of this integration. Data is stored locally or in the user's own database.
Project configuration lives in .jevia/config.toml and is intended to be
reviewed and committed. Run history lives in .jevia/runs.jsonl and is ignored
by the project-local .jevia/.gitignore because prompts and outcomes may be
sensitive. Jevia coordinates concurrent readers and writers through the
ignored .jevia/runs.lock sidecar so parallel agents cannot overwrite one
another's evidence.
Routing decisions live in the ignored .jevia/cache.jsonl file and use the
same locking and atomic-replacement guarantees through .jevia/cache.lock.
By default Jevia stores task text in the selected backend so it can supply useful examples to
future decisions. Set store_task_text = false under [privacy] to retain only
routing metadata.
In CLI 0.1.7, JSONL updates and basic health checks stream the complete history instead of retaining every record in memory. Updates still take an exclusive lock and atomically replace the file only after all records validate; a missing run, rejected change, malformed suffix, or write failure leaves the original file intact. This reduces memory use, not the linear scan/rewrite cost. Deep checks still retain run identities to detect duplicates.
In JSONL mode, jevia doctor validates the complete history and reports malformed records
without deleting or rewriting them.
Malformed configuration, history, and cache diagnostics omit raw values, including parser error chains. They report line/column positions where available and safe configuration guidance. This does not redact deliberately requested run/task output or stdout/stderr streamed by your configured harness and verifier.
Provider and transport failures also omit raw response values and endpoint URLs, including underlying error chains. Diagnostics retain safe failure categories, JSON positions where available, and HTTP status codes.
Routing HTTP requests never follow redirects, including same-origin redirects. Configure the canonical Jev API base URL directly. A 3xx response fails with its status code; its Location header and response body are not logged. This prevents redirects from forwarding current tasks, historical evidence, or credentials to another endpoint. Failed requests do not create routing decisions or cache entries.
Both maintenance commands preview by default. Inspect the report before repeating
with --apply; --json provides counts and saved paths for automation.
JSONL maintenance and routing-cache reads require regular files. Directories, named pipes (including links to them), and other special inputs are rejected without reading or replacing them. Missing files retain their empty-store behavior.
jevia runs repair
jevia runs repair --apply
jevia runs archive --keep 1000
jevia runs archive --keep 1000 --applyRepair is JSONL-only. It handles an incomplete, unterminated final JSON line after an interrupted write, or a valid final record missing its newline. It refuses malformed middle lines, complete invalid records, unsupported schemas, and duplicate IDs. It does not guess at missing fields or rewrite individual outcomes.
JSONL repair and archival use the same routing-decision validation as normal reads: identities, tiers, and model must be nonempty, and confidence/probability values must be finite and within 0–1. The 8 MiB physical-line limit also applies, including space for a final newline. Invalid complete records are refused even when a later tail is repairable. Preview and apply leave the original bytes untouched and create no backup/archive on validation failure.
CLI 0.1.9: JSONL maintenance streams one bounded physical line at a time. Preview retains only run IDs and counts, not full records or output buffers. Apply makes a second validated pass under the same exclusive history lock, streaming exact bytes to private recovery files and a temporary replacement. Both passes must have matching counts and a SHA-256 digest before recovery files are finalized and history is atomically replaced. Memory grows with unique run IDs and the largest record, not the combined history, backup, and archive sizes.
Archival works with JSONL, SQLite, and PostgreSQL. It keeps the most recently
appended --keep eligible terminal records (minimum one), plus every active,
routed/pending, or legacy-unknown record. SQL also retains any record with an
execution owner, even if its recorded lifecycle appears terminal. This command
does not recover runs, stop processes, or infer that old work has finished.
CLI 0.1.9: all backends also retain any run with a local pending recording journal
or loss marker in the invoking project's .jevia/, even if that run is terminal.
These protected rows do not consume the --keep allowance. Preview does not replay
or read recording contents; apply inventories recording names under the history/
project lock and rechecks before publishing, refusing changes if new owners appear.
Unreadable inventories fail closed. Corrupt, duplicate, or unsafe recording files
protect their owner too; archival is not a way to discard them. After a normal
route/run successfully replays and removes the journal, its terminal row can be
archived on a later invocation. PostgreSQL cannot inspect journals on other machines;
finish/recover remote recordings before running retention from a different host.
Older eligible records move to a separate JSONL archive. They no longer appear in
runs or stats, accept feedback, or inform routing. Routing fetches current
evidence before cache lookup, so removing relevant evidence changes the cache key;
archival itself does not clear or rewrite the local decision cache. Choose a
retention window large enough for the evidence you need. This is explicit
maintenance, not automatic pruning.
All backends save recovery files under the invoking project's
.jevia/history-backups/ and .jevia/history-archives/ on the CLI machine,
including when PostgreSQL is remote. Apply recomputes its plan under the history
lock. Preview (and a no-op apply) removes no records and creates no recovery files.
- JSONL: repair and archival back up the exact original file before atomic replacement. Archived record bytes, including additive metadata, are preserved.
- SQL: archival holds the selected project's write lock, validates all records in bounded pages, and saves a full project-record snapshot plus an archive of the selected rows before any deletion. A private temporary journal bounds memory while deletion batches commit in one transaction. Saved JSON preserves additive fields but flattens physical line breaks into JSONL; it is not an exact-byte or physical database backup. SQL project/ordinal/owner metadata and other projects are not included. There is no database schema change.
SQL rejects malformed/unsupported records and mismatched indexed IDs, rechecks the snapshot against its plan, and conditions deletions on the saved row values. Jevia writers serialize with retention; long operations can make other commands hit their database timeout. Coordinate external SQL writers too, since they may bypass Jevia's project lock. A snapshot failure prevents deletion. A deletion failure rolls back all batches and leaves any finalized recovery files. If a connection fails while committing, the result may be ambiguous: inspect active history and the reported files before retrying or restoring. Never assume a failed response means nothing committed.
These directories are ignored local data and may contain sensitive prompts. New snapshot files/directories use private permissions on Unix; on Windows, protect the project directory with appropriate filesystem ACLs. Jevia syncs files before deleting, and also syncs snapshot directories on Unix. Backups and archives are never overwritten or automatically removed. Total disk use can increase; SQL archival does not vacuum or compact the database.
For SQL restoration, first stop writers, export the current state to a new file, and review the chosen archive before explicitly importing it:
jevia storage export --output .jevia/before-restore.jsonl
# Replace sql-runs-UUID.jsonl with the archive path printed by `runs archive`.
jevia storage import-jsonl --from .jevia/history-archives/sql-runs-UUID.jsonl
jevia storage import-jsonl --from .jevia/history-archives/sql-runs-UUID.jsonl --applyImport keeps run IDs, outcomes, and known provenance, skips identical records, and aborts on conflicts. It appends restored records as newest, not at their original SQL positions, which can change the routing evidence window. Unknown additive JSON fields remain in the archive but are not retained by typed import. A full pre-archive snapshot can contain active records and is not suitable for blind import. For JSONL restoration, stop writers and save current history before manual replacement; an older backup would otherwise discard newer runs. SQL snapshots do not replace a database-native disaster-recovery backup strategy.
jevia recordings inspect --json
jevia recordings cleanup --json
# Only after all local/remote harnesses and hook processes have stopped:
jevia recordings cleanup --apply --confirm-stopped --jsoninspect counts local journal, loss-marker, generated-plugin, and temporary
checkpoint filenames. It does not read their payloads, parse configuration or
history, contact providers/databases, replay events, or change files. It reports
aggregate counts, not run IDs or event data. Project discovery still requires a
.jevia/config.toml file. Explicit inspection/cleanup inventories all directory
entries, including directories larger than 4,096 names. Unrelated names are not
retained in memory; inventory memory scales with artifact filenames, not payloads.
A read error aborts rather than treating a partial inventory as complete. Apply
still refreshes the complete journal/marker inventory before each move. These
operator-requested commands do not use automatic replay's two-second budget.
cleanup without --apply is an advisory preview using the configured JSONL,
SQLite, or PostgreSQL history. It may open normal storage/locking sidecars, but
does not alter history or create an archive. Apply additionally requires
--confirm-stopped, repairs private ignore rules, and rechecks each run under
its execution lease. For PostgreSQL this uses the shared session advisory lock;
the explicit confirmation covers remote or orphaned children that Jevia cannot
prove have stopped. Preview is not a reservation: the applied count may change.
Cleanup never moves journals or loss markers, infers outcomes, or deletes history. Active/routed runs, unknown owners, missing/unreadable history, pending journals/markers, unsafe files, and unmatched contents are retained with aggregate reason counts. A temporary checkpoint must exactly match the saved observation snapshot of a terminal run; a generated OpenCode plugin must match the current bundled plugin and a terminal OpenCode recording. JSONL cleanup reads one fully validated history snapshot per batch of up to 32 run owners, holding their execution leases throughout apply. SQL retains indexed single-owner lookups and at most one execution-lease connection. Busy owners are retained, and a failed history scan cannot authorize any move in that batch. Cleanup still rechecks journals and each artifact's contents before moving it. New auxiliary filenames retain the owning run UUID; older unowned files are intentionally left for manual review. Symlinks are rejected; Unix hard-linked files are also retained. This is cooperating-process maintenance, not a sandbox against arbitrary filesystem writers. Keep the project directory protected with filesystem permissions/ACLs.
Cleanup avoids rescanning the directory for artifacts already known to be ineligible. Every possible archive move still checks freshly for that owner's journal/loss marker, rechecks file contents, and holds its execution lease. Large batches of eligible files can still require repeated directory reads; the optimization does not remove these safety checks.
Eligible files are moved, not deleted, into a unique ignored
.jevia/recording-archives/cleanup-* directory. The report includes the archive
path. Files already moved remain recoverable even if a later operation fails;
inspect this directory after an error. To restore, stop writers, review the
archive, and move selected files back to .jevia/ only when their original names
are absent. Archives are never overwritten or automatically pruned; cleanup
reduces loose artifacts, not total disk usage. No extra verification or feedback
is required, and recorded history continues to inform routing automatically.
crates/jevia-corecontains configuration, typed API contracts, policy, and outcome records.crates/jevia-clicontains JSONL/SQLite/PostgreSQL persistence and terminal commands.websitecontains the Farm.js product site and getting-started guide.
Dashboard code does not belong in this repository. The managed dashboard is a separate private project with a separate security boundary.
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-featuresRun the website separately:
cd website
pnpm install
pnpm devInstallers replace existing regular Jevia binaries, but refuse directories,
symlinks, Windows junctions, and other non-regular entries at the binary path.
Choose a different JEVIA_INSTALL_DIR or inspect the conflicting entry yourself;
the installer does not delete it. Failed checksum checks preserve the old binary.
The site serves /install.sh and uses the current page's origin in its copyable
install command: localhost during development and the deployed domain in
production. The script downloads the pinned GitHub release binary, verifies its
SHA-256 checksum, and installs it to ~/.local/bin by default. It does not need
Rust or Cargo and does not modify shell configuration. Run pnpm test in
website to check the installer without installing anything.
See CONTRIBUTING.md for the contribution and commit conventions and architecture.md for component boundaries and routing invariants.
MIT