Expand description
Compatibility re-export for the internal runtime crate.
New daemon, CLI, and TUI code should depend on the
mermaid-runtime crate boundary. The mermaid_cli::runtime module is
retained so existing call sites and downstream code do not need a
flag-day import rewrite.
Re-exports§
pub use protocol::DaemonRequest;pub use client::*;
Modules§
- apply_
patch - Pure
apply_patchengine — parser, graduated fuzzy matcher, and applier — adapted from OpenAI Codex’sapply-patchcrate. - approval
- atomic
- Atomic file writes.
- checkpoint
- client
- daemon
- hardening
- Best-effort process hardening, applied as early in
mainas possible. - plugin
- policy
- protocol
- Typed daemon control protocol.
- sandbox
- Optional OS sandboxing for model-driven shell commands.
- storage
Structs§
- Action
Request - Approval
Record - Approval
Replay Result - Approvals
Repo - Checkpoint
File - Checkpoint
Manifest - Checkpoint
Origin - Provenance of a checkpoint: which runtime task and (for interactive
sessions) which conversation position the checkpointed mutation belonged
to.
Default= fully unanchored (manual/checkpoint, headless runs). - Checkpoint
Record - Checkpoints
Repo - Compaction
Record - Compactions
Repo - Hook
Gate - Combined verdict across all responding hooks for one event.
- Hook
Response - One enabled hook’s parsed response to a hook event. Most hooks print
nothing and exit 0 — that’s an
HookDecision::Allowwith no extras, so pre-contract hooks keep working unchanged. - Message
Record - Messages
Repo - NewApproval
- NewCheckpoint
- NewCompaction
- NewMessage
- NewOutcome
- NewPlugin
Install - NewProcess
- NewProvider
Probe - NewSession
- NewTask
- NewTool
Run - Outcome
Record - A verifiable outcome / reward signal attached to a trajectory (a task, and
optionally a specific tool run). The other durable tables record what
happened (messages, tool_runs, checkpoints=diffs);
outcomesrecords how good it was and who says so (source) — the enrichment that turns logs into a training set for the self-improving loop. - Outcomes
Repo - Pairing
Token Record - Pairing
Tokens Repo - Plugin
Capability Preview - A summary of what a plugin declares it will do, shown before install/enable.
These are advisory disclosures for informed consent, not an enforced sandbox
(see
PluginManifest::capabilities). - Plugin
Install Record - Plugin
Manifest - Plugins
Repo - Policy
Engine - Policy
Override - Process
Record - Processes
Repo - Provider
Probe Record - Provider
Probes Repo - Runtime
Store - SQLite-backed durable runtime state.
- Sandbox
Policy - What the caller asked the OS to confine. Both dimensions are independent;
an all-off policy enforces nothing (and
enforceis a no-op for it on every platform). - Session
Record - Sessions
Repo - Task
Record - Task
Timeline Event - Tasks
Repo - Tool
RunRecord - Tool
Runs Repo
Enums§
- Enforcement
- How the platform enforced a
SandboxPolicy— the contract betweenenforceand the__sandbox-execlauncher. - Floor
Level - Enforcement floor for actions whose blast radius exceeds the project:
write-shaped MCP tools (
external_writes) and machine-scoped package operations (system_installs). Safety mode alone never authorizes them: the mode’s decision is strengthened to at least this level (severity orderAllow < Auto < Ask < Deny). DefaultAuto: the intent classifier vets the call against the user’s request — aligned runs silently, off-task escalates — even in full_access.allowrestores the old unconditional-allow behavior per knob. - Hook
Decision - Allow-or-deny verdict parsed from a hook’s stdout / exit status.
- Open
Intent - What kind of access an
open_beneathcall needs. - Policy
Decision - Policy
Override Decision - Process
Status - Risk
Class - Safety
Mode - Task
Priority - Task
Status - Durable task state. A task is the daemon-level work unit; a chat transcript is just one artifact linked to it.
- Tool
Category
Constants§
- DEFAULT_
PAIRING_ TTL_ DAYS - Default lifetime for a freshly minted pairing token. Tokens expire so a
leaked or forgotten token can’t be replayed indefinitely;
--ttl-days 0opts out for long-lived automation. - OUTCOME_
LABEL_ ACCEPTED - OUTCOME_
LABEL_ FAILURE - OUTCOME_
LABEL_ PARTIAL - OUTCOME_
LABEL_ REJECTED - OUTCOME_
LABEL_ SUCCESS - Graded result of an outcome. Stored as free-form
TEXT(liketool_runs.status) so the taxonomy can grow without a migration; these constants are the canonical spellings so callers don’t drift. - OUTCOME_
LABEL_ UNKNOWN - OUTCOME_
SOURCE_ MODEL - OUTCOME_
SOURCE_ SYSTEM - OUTCOME_
SOURCE_ USER - OUTCOME_
SOURCE_ VERIFIER - Provenance of an
OutcomeRecord— the axis that separates a genuine external training signal from model self-judgement.verifier(compiler, tests, runtime) anduser(human edit/accept/reject) are the signals that can actually improve a model;modelis self-judged and must never be trained on unfiltered;systemis bookkeeping (e.g. a task’s terminal status). - PLAN_
DENIAL_ MARKER - Marker embedded verbatim in every plan-mode policy-denial
reason(the policy gate rewrites the read-only mode-default deny to a plan-flavored one while a plan is being drafted). Sibling ofREAD_ONLY_DENIAL_MARKER: the message-history layer matches"blocked by policy: "+ this marker to neutralize denials once plan mode ends. - READ_
ONLY_ DENIAL_ MARKER - Marker embedded verbatim in every read-only policy-denial
reason(seePolicyEngine::decide). Exposed so the message-history layer can detect a denial that a since-loosened safety mode has superseded, without re-hardcoding the wording in a second place.
Functions§
- aggregate_
hook_ responses - Aggregate hook responses: first deny wins, last
updated_inputwins, contexts concatenate in order. - approve_
and_ replay - clamp_
pairing_ ttl_ days - Clamp a client-supplied pairing TTL so a daemon socket caller can’t mint a
never-expiring token by sending
ttl_days <= 0: non-positive input becomes the default TTL, positive values pass through. The localmermaid pairCLI deliberately does not call this — its--ttl-days 0“never expires” opt-out is an owner-only choice with no privilege boundary (#65). - create_
checkpoint - create_
checkpoint_ for_ task - create_
dir_ all_ beneath - Confined
mkdir -pfor aroot-relative directory path: creates each missing component beneathroot, refusing to descend through a symlink that escapes (#77). On Linux:mkdirat+openat2(RESOLVE_BENEATH)per component; otherwise thecontain_within_canonical+std::fsfallback. - daemon_
socket_ path - data_
dir - deny_
approval - enforce
- Enforce
policyfor the commandargv. Called from single-threaded launcher code. AnyErrmeans the requested confinement could not be applied — the caller MUST fail closed (exit 126), never run unconfined. - fs_
confinement_ available - Whether filesystem write-confinement is really available on this platform:
Linux when the Landlock ruleset assembles, macOS when
/usr/bin/sandbox-execexists,falseeverywhere else. Likenetwork_killswitch_available: a safe probe that restricts nothing. (On Linux enforcement remains best-effort at apply time — a pre-Landlock kernel builds the ruleset but cannot enforce it.) - gc_
old_ checkpoint_ dirs - Best-effort GC of on-disk checkpoint directories older than
retention_days(#130): removescheckpoints/<id>/whose mtime is past the window so the tree can’t grow without bound, while keeping recent (still-restorable) checkpoints. Returns the count removed; never fails the caller (a bad entry is skipped). - generate_
pairing_ token - hash_
pairing_ token - install_
plugin_ from_ path - is_
destructive_ command - Defense-in-depth pre-check for the
execute_commandpath: callable before the policy engine to short-circuit obviously destructive commands. Splits the command into the segmentssh -cwould run and reportstrueif any segment is a destructive operation (contains_destructive_pattern), a raw network listener / reverse-shell primitive (nc -l,socat …-listen:…), or a remote download piped straight into a shell (curl … | sh). Tokenized and segment-aware — not a substring match — so spacing, case, quoting, flag bundling, and chaining can’t trivially evade it (#114). Over-blocking is the safe direction; the authoritative boundary is still deny-by-default + the policy engine, which this mirrors without changing its semantics. - is_
plan_ safe_ build_ command - True when
commandis a build/test invocation plan mode auto-allows even though it spawns processes: every segment is either read-only or a known build tool running a known build/test subcommand. Grounding a plan in a real compile or test run makes plans materially better, and these commands only write build caches (target/, test artifacts) — not the sources the plan is about. - network_
killswitch_ available - Whether the network kill-switch is really available on this platform:
Linux when the seccomp filter assembles (supported arch), macOS when
/usr/bin/sandbox-execexists,falseeverywhere else (Windows AppContainer is a follow-up). Used bymermaid self-testand the exec tool as a safe, fork-free probe — it installs nothing. - open_
beneath - Open
root-relativerelforintentwithout ever traversing out ofroot— closing the check-then-write TOCTOU where an intermediate directory is swapped for a symlink after a lexical path check but before the operation (#77). The returnedFileis bound to the exact inode the confinement resolved, so subsequent reads/writes can’t be redirected. - pairing_
expiry_ from_ now - RFC3339 expiry
ttl_daysfrom now, orNonewhenttl_days <= 0(never expires). Shared by the daemonpaircommand and the local CLI so both honor the same TTL semantics. - plugin_
capability_ preview - remove_
file_ beneath - Confined unlink of a
root-relative file (#77): opens the parent underRESOLVE_BENEATHandunlinkats the leaf, so a swapped-in symlink parent can’t redirect the delete outsideroot. - request_
daemon_ json - request_
daemon_ text - restore_
checkpoint - run_
plugin_ hooks - Run every enabled plugin’s hooks for
event, returning their parsed responses (empty when no plugin responds — most events, most hooks). Callers that gate on the result aggregate viaaggregate_hook_responses; fire-and-forget callers keep ignoring the return value. - snapshot_
field_ from_ daemon - subscribe_
daemon_ lines - Open a STREAMING daemon connection: send one JSON line, return a
line-iterator over the responses. Used by
subscribe_task, whose connection stays open (ack line, then NDJSON events until the terminalresult) —request_daemon_jsonreads exactly one line and closes.auth.tokenis injected fromMERMAID_DAEMON_TOKENlike the one-shot path. - try_
exclusive_ lock - Acquire an exclusive, auto-released advisory lock on
path— a process singleton guard for the daemon (#131). Returns the heldFileon success (keep it alive to hold the lock), orNoneif another process already holds it.flockreleases automatically when the file is dropped OR the process exits/crashes, so a dead holder never wedges the lock the way anO_EXCLpidfile would. Holding it across the socket probe → unlink → bind closes that TOCTOU: two daemons can’t both decide a stale socket is theirs to rebind. - validate_
plugin_ manifest - write_
atomic - Write
bytestopathatomically: temp file in the same directory →sync_all→ rename over the destination. The rename is atomic on the same filesystem (and replaces an existing target on both Unix and Windows). - write_
atomic_ beneath - Atomically write
bytestoroot-relativerelwithout ever traversing out ofroot. The temp file is created andrenameat-swapped beneath the same confined directory fd as the destination (Linuxopenat2(RESOLVE_BENEATH)), so a parent dir swapped for an escaping symlink after a path check can’t redirect the write (#77), AND a crash/kill/disk-full mid-write leaves the previous file intact instead of a truncated one —open_beneath+WriteTruncategives the first guarantee but not the second. Falls back tocontain_within_canonical+ by-pathcrate::write_atomicon non-Linux / pre-openat2kernels (the same best-effort posture as the other helpers). - write_
atomic_ with_ mode - Like
write_atomic, but create the temp file with the given Unix permissionmode(e.g.0o600) so the renamed destination is never even briefly world-readable.modeis ignored on non-Unix, where directory ACLs scope the file. Use this for secret-bearing files such as the config. - write_
plugin_ lockfile