Doramagic Project Pack · Human Manual
loom
Agent-first browser automation runtime — deterministic Chromium sessions with replay-equal hash chains, MCP-native tools, and a content-addressed action store.
Project Overview & Architecture
Related topics: Core Action Surface, Determinism & Replay, MCP Server, SDKs & Schema Validation, Security, Operations & Failure Modes
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Core Action Surface, Determinism & Replay, MCP Server, SDKs & Schema Validation, Security, Operations & Failure Modes
Project Overview & Architecture
Purpose and Scope
Loom is a browser-automation and recording platform originally extracted from Mentiora's code-pipeline project. Its public pre-1.0 release is tagged as 0.9.0 (2026-05-04), with the current patch at 0.11.1 (2026-06-11). The system is designed around three concerns: deterministic browser capture, a tamper-evident per-session manifest, and an MCP (Model Context Protocol) surface for agentic consumers.
The repository is organized as a Rust workspace plus a TypeScript SDK. The Rust workspace contains multiple purpose-specific crates, and loom-core is the central library that re-exports the major subsystems:
pub mod error_types; pub mod exporters; pub mod importers; pub mod manifest_writer; pub mod observability; pub mod profile_registry; pub mod receipt_builder; pub mod replay_engine; pub mod session_manager; pub mod session_scope; pub mod startup_manager; pub mod vault;
Source: loom-core/src/lib.rs:1-15
The system aims to deliver two headline properties: (a) a hash-chained manifest.jsonl whose replay equality is a cross-run "did anything change?" oracle (NFR-DET-01), and (b) an MCP server that exposes every schema-driven RPC method as a loom.* tool, with an implicit session auto-created on first call.
High-Level Architecture
The runtime is split into several layers that share no implicit state. The MCP layer receives tool calls from clients; an RPC client forwards them to a daemon; the daemon drives a Chromium session via CDP and writes a JSONL manifest through loom-core. A loom-shims boundary encapsulates platform IPC.
flowchart LR
subgraph Client["Agent / MCP Client"]
TS[TypeScript SDK<br/>typescript-sdk/]
end
subgraph MCP["loom-mcp (stdio)"]
Dispatch[McpDispatcher]
Cache[ToolCache<br/>loom.* prefix]
end
subgraph Daemon["loom-host daemon"]
RPC[RpcClient]
Shim[loom-shims IPC]
CB[Chromium CDP]
end
subgraph Core["loom-core"]
SM[session_manager]
RB[receipt_builder]
MW[manifest_writer]
RE[replay_engine]
DH[determinism_harness]
V[vault]
EX[exporters]
OBS[observability]
end
TS -->|JSON-RPC over stdio| Dispatch
Dispatch --> Cache
Dispatch --> RPC --> Shim --> CB
CB -->|DOM/SS/Network| RB
RB --> MW
MW -->|manifest.jsonl + CAS blobs| Core
RE --> MW
DH -. validates .-> RE
V --> RB
EX --> MW
OBS -. spans/logs .-> DispatchThe dispatcher is the only entry point that holds the implicit-session lifecycle and the cancellation token used for clean shutdown:
/// Cancelled when shutdown is requested — by the MCPshutdownmethod or the process signal task. … actually terminates the server (itsAtomicBoolpredecessor was stored into but never read by anything).
Source: loom-mcp/src/mcp_dispatcher/mcp_dispatcher.rs:25-32
Core Subsystems
Manifest Writer and Hash Chain
ManifestEntry is a tagged enum serialized via JCS, where every line is hash-chained to the previous one. The header carries session_id, started_at_ms, prev_hash: Option<String>, optional budgets, optional capture_policy, and a determinism seed so replay reconstructs the same in-Chromium Math.random/Date.now values rather than silently defaulting to Seed(0):
/// settle-capture (D3): the determinism seed this session was created with. Recorded so replay reconstructs the SAME seed … which diverged the in-Chromium Math.random/Date.now for any --seed N session.
Source: loom-core/src/manifest_writer/manifest_writer.rs:38-44
Receipt Builder and Error Codes
The receipt layer is the per-action outcome surface. ReceiptCode is a stable 22-code enum serialized as snake_case; WebActionCompleted is the explicit OK sentinel. Click/hide-miss/timeout scenarios each carry their own discriminator so callers can branch without parsing strings:
/// Stable 22-code receipt status/error discriminator. …WebActionCompletedis the sentinel used by OK receipts across all action tiers.
Source: loom-core/src/error_types/error_types.rs:18-25
Receipt shapes differ per tier: click receipts carry hash fields and no inline blob, while navigate receipts carry blob refs because the DOM snapshot is too large to inline. This split is regression-pinned by interface tests:
click_receipt_has_hash_fields_not_blob_fieldsandnavigate_receipt_has_blob_fields_not_hash_fields
Source: loom-core/src/receipt_builder/interface_tests.rs:20-35
Replay Engine and Determinism Harness
The replay engine consumes a closed manifest and reissues actions against a fresh Chromium, refusing to proceed when source artifacts are dirty or when non-deterministic captures are detected. The harness sits above it and is the public entry point used by CI to assert "two independent runs produce identical manifests":
//replay_engine— see crate root.…pub use impl_replay::{collect_content_refs, non_deterministic_refusal, unclean_source_refusal};
Source: loom-core/src/replay_engine/mod.rs:1-5
Cross-run equality (field_diffs=0 between two fresh recordings of the same actions) shipped in 0.10.1 (2026-06-10), turning the hash chain into a true cross-run oracle rather than just a self-replay check.
Vault and Budget Enforcer
The vault holds session credentials and refuses any grant unless the operator has acknowledged the threat model document. OAuth-style credentials are accepted; API-key credentials are explicitly rejected. The grant options are validated against a required set of headings in vault_threat_model.md:
grant_rejects_api_key_type—err.code == LoomErrorCode::VaultRejection; contextvault_credential_type_unsupported.
Source: loom-core/src/vault/impl_local.rs:118-134
budget_enforcer complements this by capping per-session resources (wall-clock, actions, bytes) so a runaway page cannot outlive its intended kill deadline while still appearing budgeted:
// budget_enforcer — see crate root.
Source: loom-core/src/budget_enforcer/mod.rs:1-5
Observability and Exporters
Observability provides span lifecycle helpers, a redaction layer (so secret-tagged LogField values are never written), and fail-open metric counters. The interface test span_start_returns_handle_carrying_supplied_name pins the basic handle semantics:
Observability::new(PathBuf::from("/tmp/loom-test/loom.log"), false)andobs.span_start("session.create", vec![])returning a handle whose.namematches.
Source: loom-core/src/observability/interface_tests.rs:14-25
exporters reads the WAL plus content-store blobs and produces JSON, gzipped tarball, or HAR 1.2 artifacts:
//export_json: JSON manifest withmanifest+content_blob_indexkeys.
Source: loom-core/src/exporters/exporters.rs:14-25
MCP Surface and Tool Cache
The MCP server speaks protocol_version: "2024-11-05" over stdio. Every schema-driven RPC method is exposed as a tool whose name is the method prefixed with loom. — for example, action.web.click becomes loom.action.web.click. The cache uses a single constructor (tool_from_method) and the MCP wire format requires inputSchema (camelCase), which the Tool struct serializes correctly:
assert!(s.contains(""inputSchema""), "got {s}");
Source: loom-mcp/src/tool_cache/interface_tests.rs:50-66
The dispatcher keeps an implicit_session that is lazily created on the first tool call, since most MCP clients never call a session-creation RPC first. A recreated_count atomic tracks transparent re-creations triggered by eviction, so determinism-pinning clients can detect, rather than blindly trust, self-healing:
/// Process-local observability surfaced byloom.session.infoso determinism-pinning clients can DETECT a transparent recreation rather than trust it; it is never part of the manifest/hash chain, and resets to 0 on MCP-process restart.
Source: loom-mcp/src/mcp_dispatcher/mcp_dispatcher.rs:55-64
Release and Failure-Mode Highlights
The community context shows several recurring failure surfaces that have driven recent releases:
- Schema validation regressions (v0.11.1): the daemon validated per-method schemas from files that
loom postinstallnever shipped, producing misattributedschema_violationerrors on documenteduntil/timeout_msargs. - MCP screenshot delivery (v0.9.9): captured PNGs were double-encoded as
CBOR{data:base64}envelopes with no MCP image content type; never reached consumers as renderable bytes. - Linux enablement (v0.9.2):
loom doctorreportedchromium binary not foundafterpostinstall, and everyweb.*action surfaced assurface_trapbecause the shim's IPC socket raced Tokio's I/O driver on fd 3. - Scheduled e2e real-world runs (issue #179): continue to fail intermittently on
ubuntu-latestandmacos-latest; artifacts underreal-world-results-ubuntu-latestcarry the daemon log and per-site results.
The TypeScript SDK (typescript-sdk/package.json) targets Node with TS 5.7, uses tsx for tests, and exposes the same loom.* tool surface for JS/TS agent hosts:
"test": "node --import tsx/esm --test 'tests/**/*.ts'","keywords": ["browser", "automation", "loom"]
Source: typescript-sdk/package.json:7-12, 19-23
Mocks are co-located with their owning crates and gated by #[cfg(any(test, feature = "mock"))], which avoids a synthetic crate that would have to depend on every system simultaneously:
loom-core = { workspace = true, features = ["mock"] }
Source: mocks/README.md:6-12
See Also
- Determinism Harness & Cross-Run Hash Equality
- Manifest Writer and Hash-Chained WAL
- MCP Dispatcher and Tool Cache
- Vault Threat Model and Credential Lifecycle
- Receipt Builder and Error Type Reference
Source: https://github.com/mentiora-ai/loom / Human Manual
Core Action Surface, Determinism & Replay
Related topics: Project Overview & Architecture, MCP Server, SDKs & Schema Validation
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Project Overview & Architecture, MCP Server, SDKs & Schema Validation
Core Action Surface, Determinism & Replay
Loom is a browser-automation daemon whose public contract is the web.* action surface exposed over RPC and MCP, paired with a deterministic recording and replay pipeline. The action surface, the determinism harness, and the replay engine form a single coherent subsystem: every recorded action is hash-stamped under a virtual clock and seeded RNG, and every replay consults that hash chain to detect drift. This page documents how those three layers fit together.
Architecture at a Glance
loom-core is the only crate that owns execution semantics. CoreApiFacade is the single entry point and the only type that escapes the crate; loom-host and loom-rpc interact with the daemon exclusively through it. Source: loom-core/src/core_api_facade/core_api_facade.rs. The facade holds Arcs of nine internal modules, including SessionManager, DeterminismHarness, ReplayEngine, ManifestWriter, BudgetEnforcer, ContentStore, Vault, StartupManager, and Observability. Source: loom-core/src/lib.rs.
flowchart LR
MCP["MCP Dispatcher<br/>(loom.web.* tools)"] --> RPC["loom-rpc"]
RPC --> Facade["CoreApiFacade"]
Facade --> SM["SessionManager<br/>(per-session task)"]
SM --> DH["DeterminismHarness<br/>(vclock + RNG + JCS)"]
SM --> TAP["SideEffectTape"]
TAP --> RE["ReplayEngine"]
SM --> RB["ReceiptBuilder"]
RB --> MW["ManifestWriter<br/>(hash-chained WAL)"]
Facade --> OM["Observability<br/>(OTel + redaction)"]The Core Action Surface
The action surface is the set of web.* methods that agents and tests call. Each method maps to a RpcMethodSchema whose doc-comment becomes the MCP tool description, and whose name is transformed into a loom.-prefixed MCP identifier. Source: loom-mcp/src/tool_cache/interface_tests.rs. The TOOL_NAME_PREFIX is fixed to loom., and the helper rpc_to_mcp_name enforces it. Examples include web.click, web.navigate, web.screenshot, web.wait_for, web.set_input_files, and web.evaluate. The MCP dispatcher enforces protocol version 2024-11-05 and dispatches tools/list, tools/call, resources/list, resources/read, and prompts/list. Source: loom-mcp/src/mcp_dispatcher/mcp_dispatcher.rs.
Each action produces a receipt. The stable outcome discriminator is ReceiptCode, a 22-variant enum whose wire form is snake_case. Source: loom-core/src/error_types/error_types.rs. The sentinel for a successful action is WebActionCompleted; surface errors include WebNavigationFailed, WebSelectorNotFound, WebEvaluateThrew, WebActionTimeout, and ElementNotHitTestable (a SemVer-minor addition emitted when DOM.querySelector succeeds but the element has no usable hit-test geometry). Adding a variant is SemVer-minor; removing one is major.
Determinism Harness
DeterminismHarness is the single home for all determinism mechanisms. Source: loom-core/src/determinism_harness/determinism_harness.rs. It exposes five mechanisms:
- Virtual clock —
clock_nowreturns a monotonically advancing u64 of nanoseconds since session start. Wall-clock reads are banned during normal operation; the--no-virtual-clockflag switches it to pass-through mode. - Seeded RNG —
rng_nextconsumes from a ChaCha20 stream seeded at session creation (rand_chacha::ChaCha20Rng), satisfying the BC HARD #5 determinism invariant. - JCS canonicalization —
canonicalizeusesserde_jcs(RFC 8785) and is the ONLY canonicalizer inloom-core.clippy::disallowed_methodsforbids directserde_json::to_stringin manifest/receipt paths. - Side-effect tape — every clock read, RNG draw, network response, and blob ref is recorded as a
TapeFrameon theSideEffectTape. - Replay-mode vtable swap —
install_replay_mode(tape)swaps the host-fn vtable so thatclock_now,rng_next, andnet_requestresolve against the tape, not live sources.
The harness is constructed once at session creation and lives inside the per-session tokio task owned by SessionManager. Source: loom-core/src/session_manager/session_manager.rs.
Replay Engine
The replay engine consumes a recorded manifest and re-executes its actions, comparing each receipt against the stored one. Source: loom-core/src/replay_engine/mod.rs. It refuses to reproduce certain traces before execution even starts:
- Aborted sessions — a session that ended via
abort()is never replayed, because its trace is abandoned, not abandoned-and-recoverable. Source: loom-core/src/replay_engine/impl_replay.rs. - Non-deterministic sources — recordings taken with
--no-determinism(real clock, unseeded RNG) return a typedNotReplayableerror rather than degrading to a request-shape error. - Unclean sources — covered by
unclean_source_refusal, which bothreplay()andvalidate()consult to keep the refusal set consistent.
collect_content_refs walks a receipt for (sha256, kind) blob references so the replay engine can resolve them from the content store.
Receipts and Capture Profiles
ReceiptBuilder produces typed receipts per action: build_click_receipt returns a click receipt with dom_after_hash set and dom_after_blob_ref left None; build_navigate_receipt does the inverse, embedding the after-snapshot as a blob ref. Source: loom-core/src/receipt_builder/receipt_builder.rs and the interface test at loom-core/src/receipt_builder/interface_tests.rs.
Capture profiles control which fields reach the wire. The single source of truth for "keep or drop" is keep_field(scope, profile, field) in capture_policy.rs, exhausted over all (CaptureScope, CaptureProfile, CaptureField) triples and guarded by a test. Source: loom-core/src/receipt_builder/capture_policy.rs. The Minimal profile strips all *_blob_ref fields and downgrades the navigate blob-after refs into hash-only fields; Full is a no-op because the caller has already set the before-refs directly on the struct. Source: loom-core/src/receipt_builder/impl_capture.rs. Both the receipt-side and the wire-side enforcer consult the same keep_field table to prevent drift between layers.
Common Failure Modes
| Symptom | Likely cause | First check |
|---|---|---|
schema_violation on loom.web.navigate | Per-method schema on disk is stale or missing — loom postinstall did not regenerate embedded schemas. | Re-run loom postinstall; see v0.11.1 release notes. |
surface_trap on every web.* action (Linux) | Shim IPC socket raced Tokio I/O on fd 3. | Upgrade to ≥ 0.9.2. |
Replay returns NotReplayable | Source recording used --no-determinism or was aborted. | Re-record with determinism enabled. |
| Drift after self-replay | Side-effect tape was not honored, or clock/RNG host-fn was not swapped. | Verify install_replay_mode ran. |
See Also
- Determinism contract: loom-core/src/determinism_harness/determinism_harness.rs
- Replay refusal logic: loom-core/src/replay_engine/impl_replay.rs
- Capture policy truth table: loom-core/src/receipt_builder/capture_policy.rs
- MCP tool naming: loom-mcp/src/tool_cache/interface_tests.rs
- Release context: v0.11.0 Hardening Sweep, v0.10.1 Cross-Run Determinism
Source: https://github.com/mentiora-ai/loom / Human Manual
MCP Server, SDKs & Schema Validation
Related topics: Project Overview & Architecture, Core Action Surface, Determinism & Replay
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Project Overview & Architecture, Core Action Surface, Determinism & Replay
MCP Server, SDKs & Schema Validation
Overview & Role
The loom-mcp crate is a Model Context Protocol (MCP) server front-end that exposes loom's deterministic browser-automation verbs (e.g. web.click, web.navigate, web.set_input_files, web.screenshot) and session-control verbs (e.g. session.reset, session.info) to agentic clients such as Claude Code. It implements MCP protocol version 2024-11-05 and serialises responses as standard MCP text and image content blocks (Source: loom-mcp/src/mcp_dispatcher/mcp_dispatcher.rs).
The server speaks JSON-RPC 2.0 over stdio, routes incoming requests through a centralised McpDispatcher, and proxies them to the loom daemon over its local IPC socket via an RpcClient. The dispatcher owns a cached tool list, a resource tracker, a structured-observability handle, a cancellation token, and an implicit session that is auto-created on the first tool call (Source: loom-mcp/src/mcp_dispatcher/mcp_dispatcher.rs).
Architecture
flowchart LR
A[MCP Client<br/>e.g. Claude Code] -->|stdio JSON-RPC 2.0| B[StdioTransport]
B --> C[McpDispatcher]
C --> D[ToolCache<br/>loom.* tool list]
C --> E[ResourceTracker<br/>loom://session/<id>/manifest]
C --> F[McpObservability<br/>tracing + redaction]
C --> G[ImplicitSession<br/>lazy, self-healing]
G -->|CBOR over Unix socket| H[RpcClient]
H --> I[loom-daemon<br/>CDP / shim]The dispatcher advertises tools, resources, and prompts capabilities during initialize, with listChanged flags and resources.subscribe enabled (Source: loom-mcp/src/mcp_dispatcher/mcp_dispatcher.rs). The ToolCache mirrors the daemon's rpc.schemas registry locally and transforms RPC method names by prepending the loom. prefix (e.g. action.web.click → loom.action.web.click) (Source: loom-mcp/src/tool_cache/tool_cache.rs).
Tool Surface, Resources & Schema Validation
The dispatcher exposes five MCP methods: tools/list, tools/call, resources/list, resources/read, and prompts/list (Source: loom-mcp/src/mcp_dispatcher/mcp_dispatcher.rs). Tool definitions are built from the daemon's RpcMethodSchema records and tagged with the loom. prefix constant TOOL_NAME_PREFIX (Source: loom-mcp/src/tool_cache/tool_cache.rs). Session-level verbs (loom.session.*) are not registered through rpc.schemas; the dispatcher injects them as built-in tools so MCP consumers can call session.reset, session.info, session.diff, session.validate, and session.export directly. These built-in tools accept a budget object (e.g. {"session_walltime_ms": 30000}) to cap runaway pages with error.kind = "budget_exceeded" (Source: loom-mcp/src/mcp_dispatcher/mod.rs).
Schema validation is the contract gatekeeper between MCP clients and the daemon. As of v0.11.1 the daemon validates tools/call arguments against an embedded schema registry rather than per-method files on disk, fixing a v0.11.0 regression where loom.web.navigate was rejected with a misattributed schema_violation (field 'params' expected field_unknown got object) while web.wait_for accepted the same until/timeout_ms parameters. The embedded-first approach ensures postinstall cannot leave the daemon with missing or stale schemas (Source: release notes v0.11.1).
Resources are addressed by URI scheme. Session manifests are exposed as loom://session/<id>/manifest with a default cache TTL of 30 seconds, and binary blobs are addressed as loom://blob/<sha256-hex> (Source: loom-mcp/src/resource_tracker/resource_tracker.rs). Content blocks are restricted to the standard MCP text and image variants; JSON payloads are stringified into a text block to avoid tripping strict client validators (e.g. Claude Code's Zod schema). Screenshot-producing verbs emit a base64-encoded image block alongside a text receipt that still carries the screenshot_after_hash for wire-contract parity (Source: loom-mcp/src/error_mapper/error_mapper.rs).
Error Mapping, Observability & SDKs
The ErrorMapper is the single conversion point from LoomError to an MCP ToolResult { isError: true, content }. JSON-RPC protocol errors follow the spec-defined codes: -32700 (parse), -32600 (invalid request), -32601 (method not found), -32602 (invalid params), and -32603 (internal) (Source: loom-mcp/src/stdio_transport/interface_tests.rs). The observability layer emits mcp_request_start and mcp_request_end spans carrying the MCP method, optional tool name, outcome, error code, and latency in microseconds (Source: loom-mcp/src/mcp_observability/mod.rs).
Two redaction paths protect vault material in logs and responses. When redact_vault is enabled, arguments for tools in REDACTED_TOOL_NAMES are replaced with the string "[REDACTED]", and cookie tools (COOKIE_REDACTED_TOOL_NAMES) have only the value field of any nested cookies array stripped while names and structure remain visible for auditability (Source: loom-mcp/src/mcp_observability/mod.rs). The implicit session is recreated transparently on eviction using the env-derived SessionOptions baseline (LOOM_MCP_SESSION_SEED, LOOM_MCP_SESSION_CLOCK_ANCHOR, LOOM_MCP_SESSION_PROFILE), and a recreated_count counter exposed via loom.session.info lets determinism-pinning clients detect transparent recreation (Source: loom-mcp/src/mcp_dispatcher/mod.rs).
The TypeScript SDK is the canonical out-of-process consumer; its package.json defines tsc --project tsconfig.json as the build step, node --import tsx/esm --test 'tests/**/*.ts' for tests, and depends on @types/node ^25.6.0, tsx ^4.19.2, and typescript ^5.7.3 (Source: typescript-sdk/package.json). The crate-level mock harnesses are gated by #[cfg(any(test, feature = "mock"))] and live inside the owning crate (e.g. loom-mcp/src/mocks.rs) so each stub stays co-located with the types it replaces (Source: mocks/README.md).
See Also
- Determinism & Replay Engine
- Daemon IPC & Shim Protocol
- Vault & Cookie Lifecycle
Source: https://github.com/mentiora-ai/loom / Human Manual
Security, Operations & Failure Modes
Related topics: Project Overview & Architecture, Core Action Surface, Determinism & Replay, MCP Server, SDKs & Schema Validation
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Project Overview & Architecture, Core Action Surface, Determinism & Replay, MCP Server, SDKs & Schema Validation
Security, Operations & Failure Modes
This page describes how Loom protects credentials, manages long-lived operations, and surfaces failures across its daemon, MCP, and shim boundaries. It consolidates the threat model, observability, session/ budget controls, and the stable error taxonomy that downstream consumers (such as agentic-test-studio) depend on for trust.
Vault & Credential Security
The vault module (loom-core/src/vault/mod.rs) is the single boundary for storing and granting secrets used by web sessions. Granting a credential is gated by two explicit security checks inside loom-core/src/vault/impl_local.rs:
- Threat-model acknowledgement. A grant request with
threat_model_acknowledged = falsereturnsLoomErrorCode::VaultRejectionwith context codevault_threat_model_missing. Operators must confirm they have read the threat-model document that ships with the binary — its required headings are asserted in tests (Attacker Classes,Security Goals,Trust Boundaries,Abuse Cases). - OAuth-only enforcement.
CredentialType::ApiKeyis rejected withvault_credential_type_unsupported; onlyoauth2is in the allowed list. This narrows the credential surface and aligns replay with token-refresh semantics.
Audit payloads are JCS-canonical DTOs embedded in ManifestEntry::AuditEntry::canonical_bytes (loom-core/src/vault/audit_payloads.rs). The on-wire shape is hash-chain-load-bearing — reordering a field breaks NFR-DET-01 cross-run determinism. To minimise secret exposure, extract_cookie_names parses the raw vault blob but never returns raw values; on parse failure it returns an empty vector and lets the typed CDP-encode error surface to the caller.
Session Lifecycle, Budgets & Observability
Each session runs as a finite-state machine owned by SessionManager (loom-core/src/session_manager/session_manager.rs):
stateDiagram-v2
[*] --> Created
Created --> Active: warm_create (ULID + dir + WAL fsync + task spawn)
Active --> Closed: normal completion
Active --> Aborted: operator abort()
Active --> Killed: BudgetEnforcer kill-callback
Active --> Crashed: task panic
Closed --> [*]
Aborted --> [*]
Killed --> [*]
Crashed --> [*]The warm_create path performs no WASM, Chromium, or network work — only ULID generation, directory creation, WAL header append + fsync, and a tokio task spawn. Abort propagation uses Arc<Notify> plus Arc<AtomicBool>; host-fn entries poll the bool and tokio::select! against the notify. A kill-callback Arc<dyn Fn(SessionId, KillReason)> is registered into BudgetEnforcer so a budget breach can interrupt a specific session's task without creating a cycle (see loom-core/src/budget_enforcer/mod.rs).
For long-lived daemons, the session reaper (added in 0.10.1) closes idle sessions and supports the loom session reap operator command surfaced by ErrorMapper::to_tool_result (e.g. concurrent session cap reached (2/2) with structured {active, cap, hint} context, loom-mcp/src/error_mapper/interface_tests.rs).
Observability (loom-core/src/observability/interface_tests.rs) exposes three contract surfaces: a redaction layer, a span lifecycle (span_start returns a handle carrying the name; span_end consumes it), and a BudgetSnapshot that is integer-only. LogField carries an explicit secret: bool flag so the redactor can scrub PII before write.
The MCP dispatcher (loom-mcp/src/mcp_dispatcher/mcp_dispatcher.rs) adds an implicit session auto-created on the first tool call, reused for the MCP server's lifetime, and transparently recreated after idle eviction. recreated_count is surfaced via loom.session.info so determinism-pinning clients can detect a transparent recreation; it is not part of the manifest/hash chain and resets on MCP-process restart.
Failure Modes & Error Taxonomy
Loom deliberately separates two error families:
| Family | Module | Purpose | Stability |
|---|---|---|---|
ReceiptCode | error_types (loom-core/src/error_types/error_types.rs) | Public action-outcome discriminator in every receipt | Stable 22-code enum; SemVer-minor to add, major to remove |
LoomErrorCode | internal | Daemon-level infrastructure errors | Internal |
ReceiptCode::WebActionCompleted is the OK sentinel; as_wire() matches serde output (snake_case) and tests verify parity. Adding a variant is a minor change — consumers parse the string form, not the variant index. A new variant, WebElementNotVisible, was added recently and remains a SemVer-minor addition.
Known Historical Failures
- 0.9.1 daemon-stall. A bug fixed post-0.9.0 caused the daemon to stop accepting requests; the patch also added
daemon.health({deep: true}). - 0.9.2 Linux postinstall regressions (loom-core/src/lib.rs module surface). Fresh Linux installs would
postinstallcorrectly then fail in two ways:loom doctorreportedchromium binary not found, and everyweb.*action surfaced assurface_trapbecause the shim's IPC socket raced Tokio's I/O driver on fd 3. 0.9.2 fixed both. - 0.11.1 schema regression. A v0.11.0 regression made MCP
tools/callreject the documenteduntil/timeout_msargs onloom.web.navigatewithschema_violation(field 'params' expected field_unknown got object) whileweb.wait_foraccepted the same params. Root cause: the daemon validated against per-method schema files on disk thatloom postinstallnever embedded; v0.11.1 switched to embedded-first validation.
MCP Error Mapping Contract
ErrorMapper::to_tool_result (loom-mcp/src/error_mapper/interface_tests.rs) returns a ToolResult whose single content block is the standard MCP text content type with the TypedReceipt JSON-serialised inside. This was a v1.0.1 fix so strict MCP clients (Claude Code) accept the payload. Internal helpers (from_rpc_io, from_hello_mismatch, from_unknown_tool, from_schema_parse) map every wire failure to a stable LoomErrorCode — no inline code invention. Tool names use the loom. prefix and snake_case dotted signatures (loom-mcp/src/tool_cache/interface_tests.rs).
Hardening & Replay Integrity
The replay engine (loom-core/src/replay_engine/mod.rs) enforces non_deterministic_refusal and unclean_source_refusal, and collect_content_refs is the single point that walks a manifest to enumerate its content-store dependencies. Together with DeterminismHarness (loom-core/src/determinism_harness/mod.rs) and the JCS-canonical manifest chain (loom-core/src/manifest_writer/manifest_writer.rs), these guarantees make the manifest hash a true "did anything change?" oracle across independent recordings (NFR-DET-01, delivered in 0.10.1). The v0.11.0 hardening sweep (~100 audit findings) was regression-pinned via interface tests, with mocks co-located per crate and gated by #[cfg(any(test, feature = "mock"))] (mocks/README.md).
Operational checklist for failure investigation:
- Run
loom doctor— confirms the chromium binary and post-install schema embed (post-0.9.2 fix path). - Run
daemon.health({deep: true})to probe the shim and IPC socket. - Inspect the receipt's
codefield — match against the 22-codeReceiptCodeenum. - For session caps, parse
data.active,data.cap,data.hintand runloom session reap. - For determinism drift, compare manifest hash chains across two independent fresh recordings (
field_diffs=0⇒ no change).
See Also
- Vault & Credentials
- Session Manager & Lifecycle
- Error Taxonomy & Receipt Codes
- Replay & Determinism
- MCP Integration
Source: https://github.com/mentiora-ai/loom / Human Manual
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
Doramagic Pitfall Log
Found 8 structured pitfall item(s), including 1 high/blocking item(s). Top priority: Runtime risk - Runtime risk requires verification.
1. Runtime risk: Runtime risk requires verification
- Severity: high
- Finding: Project evidence flags a runtime risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: community_evidence:github | https://github.com/mentiora-ai/loom/issues/179
2. Configuration risk: Configuration risk requires verification
- Severity: medium
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.host_targets | https://github.com/mentiora-ai/loom
3. Capability evidence risk: Capability evidence risk requires verification
- Severity: medium
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.assumptions | https://github.com/mentiora-ai/loom
4. Maintenance risk: Maintenance risk requires verification
- Severity: medium
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/mentiora-ai/loom
5. Security or permission risk: Security or permission risk requires verification
- Severity: medium
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: downstream_validation.risk_items | https://github.com/mentiora-ai/loom
6. Security or permission risk: Security or permission risk requires verification
- Severity: medium
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: risks.scoring_risks | https://github.com/mentiora-ai/loom
7. Maintenance risk: Maintenance risk requires verification
- Severity: low
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/mentiora-ai/loom
8. Maintenance risk: Maintenance risk requires verification
- Severity: low
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://github.com/mentiora-ai/loom
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using loom with real data or production workflows.
- e2e-real-world: scheduled run failed - github / github_issue
- 0.12.0 — 2026-06-19 — Video Capture + Per-Action Deadlines - github / github_release
- 0.11.1 — 2026-06-11 — Embedded-First Schema Validation - github / github_release
- 0.11.0 — 2026-06-11 — Hardening Sweep: Determinism, Protocol, Security + - github / github_release
- 0.10.1 — 2026-06-10 — Cross-Run Determinism + Session Reaper - github / github_release
- 0.10.0 — 2026-06-08 — Network Entries + Readiness-Gated Capture - github / github_release
- 0.9.9 — 2026-06-04 — MCP Screenshot Delivery - github / github_release
- 0.9.8 — 2026-06-03 — File Uploads - github / github_release
- 0.9.2 — 2026-05-18 - github / github_release
- 0.9.1 — 2026-05-11 - github / github_release
- 0.9.0 — 2026-05-04 - github / github_release
- Configuration risk requires verification - GitHub / issue
Source: Project Pack community evidence and pitfall evidence