Skip to main content

Module runtime

Module runtime 

Source
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_patch engine — parser, graduated fuzzy matcher, and applier — adapted from OpenAI Codex’s apply-patch crate.
approval
atomic
Atomic file writes.
checkpoint
client
daemon
hardening
Best-effort process hardening, applied as early in main as possible.
plugin
policy
protocol
Typed daemon control protocol.
sandbox
Optional OS sandboxing for model-driven shell commands.
storage

Structs§

ActionRequest
ApprovalRecord
ApprovalReplayResult
ApprovalsRepo
CheckpointFile
CheckpointManifest
CheckpointOrigin
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).
CheckpointRecord
CheckpointsRepo
CompactionRecord
CompactionsRepo
HookGate
Combined verdict across all responding hooks for one event.
HookResponse
One enabled hook’s parsed response to a hook event. Most hooks print nothing and exit 0 — that’s an HookDecision::Allow with no extras, so pre-contract hooks keep working unchanged.
MessageRecord
MessagesRepo
NewApproval
NewCheckpoint
NewCompaction
NewMessage
NewOutcome
NewPluginInstall
NewProcess
NewProviderProbe
NewSession
NewTask
NewToolRun
OutcomeRecord
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); outcomes records how good it was and who says so (source) — the enrichment that turns logs into a training set for the self-improving loop.
OutcomesRepo
PairingTokenRecord
PairingTokensRepo
PluginCapabilityPreview
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).
PluginInstallRecord
PluginManifest
PluginsRepo
PolicyEngine
PolicyOverride
ProcessRecord
ProcessesRepo
ProviderProbeRecord
ProviderProbesRepo
RuntimeStore
SQLite-backed durable runtime state.
SandboxPolicy
What the caller asked the OS to confine. Both dimensions are independent; an all-off policy enforces nothing (and enforce is a no-op for it on every platform).
SessionRecord
SessionsRepo
TaskRecord
TaskTimelineEvent
TasksRepo
ToolRunRecord
ToolRunsRepo

Enums§

Enforcement
How the platform enforced a SandboxPolicy — the contract between enforce and the __sandbox-exec launcher.
FloorLevel
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 order Allow < Auto < Ask < Deny). Default Auto: the intent classifier vets the call against the user’s request — aligned runs silently, off-task escalates — even in full_access. allow restores the old unconditional-allow behavior per knob.
HookDecision
Allow-or-deny verdict parsed from a hook’s stdout / exit status.
OpenIntent
What kind of access an open_beneath call needs.
PolicyDecision
PolicyOverrideDecision
ProcessStatus
RiskClass
SafetyMode
TaskPriority
TaskStatus
Durable task state. A task is the daemon-level work unit; a chat transcript is just one artifact linked to it.
ToolCategory

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 0 opts 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 (like tool_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) and user (human edit/accept/reject) are the signals that can actually improve a model; model is self-judged and must never be trained on unfiltered; system is 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 of READ_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 (see PolicyEngine::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_input wins, 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 local mermaid pair CLI 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 -p for a root-relative directory path: creates each missing component beneath root, refusing to descend through a symlink that escapes (#77). On Linux: mkdirat + openat2(RESOLVE_BENEATH) per component; otherwise the contain_within_canonical + std::fs fallback.
daemon_socket_path
data_dir
deny_approval
enforce
Enforce policy for the command argv. Called from single-threaded launcher code. Any Err means 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-exec exists, false everywhere else. Like network_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): removes checkpoints/<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_command path: callable before the policy engine to short-circuit obviously destructive commands. Splits the command into the segments sh -c would run and reports true if 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 command is 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-exec exists, false everywhere else (Windows AppContainer is a follow-up). Used by mermaid self-test and the exec tool as a safe, fork-free probe — it installs nothing.
open_beneath
Open root-relative rel for intent without ever traversing out of root — 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 returned File is bound to the exact inode the confinement resolved, so subsequent reads/writes can’t be redirected.
pairing_expiry_from_now
RFC3339 expiry ttl_days from now, or None when ttl_days <= 0 (never expires). Shared by the daemon pair command 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 under RESOLVE_BENEATH and unlinkats the leaf, so a swapped-in symlink parent can’t redirect the delete outside root.
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 via aggregate_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 terminal result) — request_daemon_json reads exactly one line and closes. auth.token is injected from MERMAID_DAEMON_TOKEN like 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 held File on success (keep it alive to hold the lock), or None if another process already holds it. flock releases automatically when the file is dropped OR the process exits/crashes, so a dead holder never wedges the lock the way an O_EXCL pidfile 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 bytes to path atomically: 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 bytes to root-relative rel without ever traversing out of root. The temp file is created and renameat-swapped beneath the same confined directory fd as the destination (Linux openat2(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 + WriteTruncate gives the first guarantee but not the second. Falls back to contain_within_canonical + by-path crate::write_atomic on non-Linux / pre-openat2 kernels (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 permission mode (e.g. 0o600) so the renamed destination is never even briefly world-readable. mode is ignored on non-Unix, where directory ACLs scope the file. Use this for secret-bearing files such as the config.
write_plugin_lockfile