All docs

Glossary

The terms Eunice uses, and how to tell apart the ones that sound alike: Kit and corpus, primitive and tool, Skill and app.

Every project-specific term that could trip up a new developer. Alphabetical. Each entry is one definition followed by disambiguation from adjacent terms and a pointer to the file where the term is actually defined.

Cross-references: Engine, Fabric, Shared Layer, Tool System, Runtime Flow, Database Schema.

A

AsyncExecutionService Platform infrastructure for durable execution of long-running tool jobs. Lives in infrastructure/async_service.py. Owns job lifecycle (submit → queue → run → terminal), cancellation, timeout enforcement, per-tenant quotas, circuit breakers (one per tool_type), and dead-letter capture. Backed by the WAL (infrastructure/wal.py) so in-flight jobs survive process restart. Delegates actual work to a pluggable ExecutorBackend (infrastructure/backends/). The OOM that hit the first AWS deploy was unbounded terminal-job retention here; DEFAULT_MAX_TERMINAL_JOBS = 10_000 caps it now.

Artifact A card that renders in the side panel instead of inline in the chat stream. Frontend routing uses an ARTIFACT_CARD_TYPES set: data_profile, model_recommendation, training_results, shap_explanation, peer_review, classification_result, extraction_result, workflow_run, workflow_preview, file_download, map_display, chart. Not every card is an artifact. file_download and chart render in BOTH the side panel and inline, the user wants the download button or rendered figure visible in the chat flow.

C

Capability A permission string checked by @requires(...) on FastAPI endpoints. Defined in shared/capabilities.py with role mappings stored in the role_capabilities table. Examples: conversations.create, knowledge.upload, admin.system. Disambiguation: a model capability is a feature flag on ModelConfig.capabilities (e.g., web_search, vision, structured_output) that the engine uses to filter tools and emit prompt guidance. Unrelated namespaces.

Card A structured payload carried in ToolResult.cards (or Ok.effects.cards under the Uniform Tool Contract) and rendered by a frontend card component. Each card has a type string and a data dict. The frontend decides routing (artifact panel vs. inline) via ARTIFACT_CARD_TYPES. See frontend/src/constants.ts for the icon/colour maps.

Catalog (ConversationCatalog) The per-conversation in-memory data registry. Lives in fabric/catalog.py. Tracks loaded DataFrames, documents, exports, and snapshots that tools have produced or referenced during the current chat session. The hot path for analyze_data, preview_data, query, and train_model. Backed by the catalog_entries table for cross-conversation lookup. Not the same as a Kit (cross-conversation semantic grouping) or a Corpus (RAG document collection).

Catalog Entry A row in catalog_entries. Represents a dataset, document, export, or materialized snapshot. The entry_type integer references catalog_entry_types. Columns cover dataset metadata (columns, dtypes, row count), document metadata, export metadata, and semantic-layer fields (contextual signals, intelligence, searchable summary, embedding). See Database Schema for the column list.

Compaction LLM-based summarization of older conversation messages when history exceeds the token budget. Implemented in engine/history.py. The budget comes from model_config.history_token_budget (default 40K). The compaction-role LLM summarizes older turns; the summary is cached on the Conversation row; the most recent turns (default 6) are kept verbatim.

Connector (ConnectorService) The protected boundary for external REST API calls. Lives in shared/connector.py. Handles auth injection, rate limiting, retry, and response normalization for DataSource rows. Not a database driver. The Knowledge Layer Contract envelope is currently planned to extend through this surface but is not yet active here.

Corpus A collection of documents for RAG search. Lives in knowledge/. Each corpus is tenant-scoped. User-facing corpora hold uploaded PDFs/Word/Excel files. System corpora (system=True, hidden from the UI) hold operational patterns and behavioural signals; the engine queries them via the Knowledge-Is-Routing pre-fetch path before building the prompt. Not the same as Kit or Catalog.

ConversationEvent A single immutable telemetry row in the conversation_events table. Captures every SSE event, tool call, tool result, LLM turn, and error in temporal order so a conversation can be replayed by SELECT ... ORDER BY sequence. Defined in shared/database.py. Event types include user_message, llm_request, status, thinking, tool_call, tool_result, progress, text_delta, card, done, error. Payloads larger than 32 KB overflow into conversation_event_blobs via ConversationEventBlob. Rows are written by the EventRecorder in a single batch INSERT at stream end.

D

DataSource An external REST API registration in the datasources table. Represents an API, not a dataset, e.g., EPA ECHO, NOAA, USGS. Carries base URL, auth config, rate limits, known endpoints, response normalization strategy, and (usually) a linked API-documentation corpus. Probed on a schedule by scripts/datasource_probe.py; status, consecutive_failures, and last_error update in place.

Dataset A pandas DataFrame loaded into a conversation’s catalog. Origins: user upload, derivation in analyze_data, tool export, materialization from an external API, or workflow output. Stored as Parquet on disk and tracked in catalog_entries. Not the same as a DataSource (which is an API).

DisplayEvent The wire-format event from the Display Protocol. Carries routing metadata: type, channel, scope, verb (append/update/replace/clear), priority, and display_id (for in-place updates). Defined in shared/display.py. Event types: text_delta, text_complete, reasoning, tool_call, tool_result, busy, idle, status, progress, card, error, warning, cost, done.

DisplayFactory Creates DisplayHandle instances, owns the event queue, and drains the queue as SSE. One factory per chat request. Bridges synchronous tool code to the async SSE stream. Also tees each event to the EventRecorder for telemetry. Lives in shared/display.py.

DisplayHandle A scoped, resilient interface for tools and agents to emit display events. Every method is fire-and-forget, thread-safe, and wrapped in try/except. A handle is scoped to a specific emitter (tool:analyze_data, delegate:child, etc.) and tags every event with its scope, channel, and group.

Dispatcher The tool-dispatch module (engine/dispatcher.py) extracted from the legacy orchestrator. Public surface: dispatch_tool_call(tool_use, runtime, state, ...) and dispatch_tool_calls(blocks, runtime, state, ...). Runs realtime policy checks, computes an args_hash for repeat detection against state.failed_approaches, executes the tool via the registry, and emits per-call telemetry. Module-level caches (_conversation_tool_history, _conversation_policy_counts) are the legacy storage that TurnState will replace as the migration progresses.

Dream Cycle Periodic analysis that rebuilds the relationship graph, discovers Kits, prunes stale edges, and extracts operational knowledge from telemetry into the system corpora. Lives in fabric/dream_cycle.py. Runs as a separate process via scripts/background_jobs.py (or on demand via Admin > System). Reads dataset_activity, conversation_events, and observations; writes kits, kit_memberships, relationship_edges, and corpus chunks.

E

Effect Under the Turn Contract, a typed data object representing one side-effect the turn produced. Sum-type root in engine/turn_types.py; three concrete kinds: PersistAssistantMessage (write the ChatMessage row at end of turn), TelemetryEvent (append a ConversationEvent row; also carries behavioural-observation writes), StreamChunks (a batched list of SSEChunk produced by the turn). Adding a fourth kind requires updating the closed-catalog lint. Distinct from the side-effect channels on Ok.effects in the Uniform Tool Contract (cards/datasets/exports/cost), which are persisted by _persist_effects in the contract decorator, those are tool-boundary effects, the Effect catalogue covers turn-boundary effects.

EffectAccumulator The recording-proxy layer in engine/effect_accumulator.py. _RecordingRecorder wraps the real EventRecorder and _RecordingDisplay wraps the real DisplayHandle. Every recorder.record(...) or display emission inside the loop body now (1) builds a typed TelemetryEvent or SSEChunk, (2) appends it to the shared effects list, and (3) calls apply_effect(effect, ctx). The accumulator preserves call order; apply_effect (in engine/effects.py) is the only code that writes to the outside world. Tests mock it; replay drives it with synthetic effects to reconstruct a run. Structural reality: today the proxies call apply_effect synchronously to preserve streaming UX; the spec’s “record-only, apply at end of turn” mode is a flag-toggle away once the runner owns the final flush.

Entry Type Classification of a CatalogEntry. Six types: UPLOAD (1, durable), EXPORT (2, durable), DOCUMENT (3, durable), DERIVED (4, not durable), WORKFLOW_OUTPUT (5, durable), MATERIALIZED (6, not durable). Durable entries survive conversation cleanup; non-durable ones can be removed when their conversation goes cold. Defined in shared/entry_types.py.

Eunice The user-facing name of the platform, after Eunice Newton Foote. Source code retains the internal codename Catalyst for module names, config prefixes, and database names. Treat “Eunice” and “Catalyst” as the same product wearing different hats. Which occurrences of “Catalyst” in the documentation are load-bearing and which are not is inventoried in Catalyst references.

EventRecorder The telemetry accumulator for a single conversation turn. Lives in shared/telemetry.py. Holds events in an in-memory list during streaming (zero DB writes on the hot path) and flushes everything in a single batch INSERT into conversation_events at stream end. Text deltas and thinking chunks are coalesced via internal buffers (record_text_delta, record_thinking) so the wire-rate trickle becomes a handful of rows per turn. The EffectAccumulator’s _RecordingRecorder proxy wraps this object so every recorded event also becomes a typed TelemetryEvent effect.

Executor engine/executor.py. The per-turn execution path lifted out of the legacy orchestrator. Runs the streaming LLM call, emits text_delta / thinking chunks, hands tool blocks to the dispatcher, and produces the messages/effects/errors the runner consumes. The single largest engine module by line count; the executor body still reads several module-level dicts directly while the migration to TurnState proceeds.

F

Fabric The data-lifecycle module. Lives in fabric/. Owns the conversation catalog, Kits, temperature scoring, data intelligence, semantic relationships, the user behavioural profile, knowledge extraction, and the dream cycle. The organizational layer above individual tools and conversations. See Fabric Module.

FinOps (Financial Operations) Cost tracking and budget management for LLM and infrastructure spend. Lives in shared/finops.py (calculation helpers, calculate_cost, get_model_price) and shared/finops_router.py (HTTP surface). Backed by the usage_log, model_config, and budget_alerts tables. Surfaced at /finops in the UI. The cost field on Ok.effects flows here via _persist_effects; the rollup-cost ToolSpec flag prevents delegate parents from double-counting leaf charges.

H

HintException Internal-only sentinel raised by resolver helpers (engine/contract_resolvers.py) and translated to a Hint envelope by the @uniform_contract decorator. Does not subclass any other error type. Catching it before the generic Exception block is what gives the model recoverable corrections instead of opaque platform errors. See Uniform Tool Contract.

I

Intelligence Semantic metadata about a dataset computed by fabric/intelligence.py and stored on CatalogEntry.intelligence. Includes column-role analysis (identifiers, measures, categories, timestamps), data-quality warnings, domain detection (EPA-RCRA, EPA-SDWA, etc.), and analysis suggestions. Injected into the system prompt for active datasets.

J

JWT (JSON Web Token) The signed bearer token format used by the local auth system. Issued by shared/auth_router.py on login/register/refresh; validated by middleware in app.py which resolves user, tenant, and capabilities onto the RequestContext. Dev bypass mode (CATALYST_AUTH_DEV_BYPASS=true) accepts expired tokens to preserve user identity during local work. See also: Capability, RBAC.

K

Kit A semantic grouping of datasets, cross-conversation. Created by users (pinned) or by the dream cycle (system). Members carry a reason field explaining why they belong. Membership is append-mostly (soft delete only). Temperature drives display priority. Not a folder, not a tag, and not the same as a Corpus.

Kit Membership A row in kit_memberships linking a dataset to a Kit, with reason. Append-only: removing a dataset sets deleted_at, never hard-deletes.

Knowledge-Is-Routing The rule that any “how does the LLM discover X?” question is answered by querying the corresponding system corpus via vector search, not by adding keyword matchers or recency dumps. Hard-coded in CLAUDE.md. Backs the Knowledge Layer Contract (planned) and shapes how resolve_catalog_entry and resolve_dataset rank candidates.

M

MaterializedSnapshot A catalog entry created by calling an external API via the ConnectorService. Carries freshness metadata (retrieved_at, freshness_expires_at) and can be refreshed. Stored as entry type 6 (MATERIALIZED, non-durable).

MCP (Model Context Protocol) An open protocol for connecting AI assistants to external tool servers. Eunice connects to MCP servers (stdio or HTTP) via shared/mcp_client.py. MCP tools are registered with prefix mcp_{connection}_{tool} and tool_type="mcp".

O

Observation An atomic factual statement about how a user works. Stored in observations. Seven categories: domain, workflow, data_preference, correction, temporal, friction, policy_violation. Each carries a confidence score, evidence count, and optional failure-mode classification from an 18-item taxonomy. Feeds the [USER_CONTEXT] block in the system prompt and drives adaptive routing rules. Under the Turn Contract, an observation write becomes a TelemetryEvent(event_type="behavioral_observation", ...).

P

Plan A recorded approach for a multi-step task, captured by the plan tool and surfaced as state.active_plan. Carries steps with dependencies and success criteria. An automatic post-turn review (engine/review.py) checks completion against evidence on heavy turns, replacing the retired verify_plan tool. Replanning is allowed (no cap), it consumes the same turn budget as any other action.

PolicyRule A machine-readable behavioural policy row in the policy_rules table. Defined in shared/database.py. Each rule names a trigger (tool name or task type), a precondition that must hold, a check_method (e.g., tool_called_before, row_count_compared), a failure_mode drawn from the failure taxonomy, and a severity of warning or violation. Checked in real time after each tool execution; violations create an immediate Observation with category policy_violation. Distinct from a RoutingRule (adaptive, learned), policy rules are operating policy the platform asserts up front.

Primitive A tested workflow building block with defined input/output schemas, pre/postconditions, and verified code. Four levels: atomic (load_csv, count_rows), operation (append_rows_to_sheet), task (analyze_data), workflow. Created by the PrimitiveFactory via a write-test-verify convergence loop in workflow/factory.py. Not the same as a tool, primitives are sandboxed data transformations, tools can mutate system state.

PrimitiveContract The typed I/O contract for a single primitive. Dataclass in skills/primitive_runtime.py (its former home, workflow/primitives.py, was deleted with the Workflow feature in 2026-07). Carries name, version, input/output schemas, preconditions, postconditions, tested code body, and provenance (who wrote it, what data it was verified against). The Executor enforces the postconditions at run time.

PrimitiveExecutor The sandboxed runtime that runs a primitive’s code body against typed inputs. Lives in skills/primitive_runtime.py. Imposes timeouts, captures stdout/stderr, validates postconditions after the body returns, and surfaces a structured failure rather than letting an exception escape the sandbox. Not the same as PrimitiveFactory (which writes the code) or PrimitiveRegistry (which stores it).

PrimitiveFactory The write → test → verify convergence loop that creates new primitives via an LLM. Lives in workflow/factory.py. Generates a candidate code body from a description, runs it through the PrimitiveExecutor against real input data, classifies the failure if any, and iterates. On success the resulting PrimitiveContract is persisted via the PrimitiveRegistry. Bounded by a turn budget and a cost budget.

PrimitiveRegistry The store/lookup surface for primitives. Lives in skills/primitive_runtime.py. Persists PrimitiveContract records in the primitives table, exposes find (vector-search over description_embedding), get (by name + version), and registration helpers. Version-aware: an existing primitive can be evolved without breaking callers that pin a prior version.

R

RAG (Retrieval-Augmented Generation) The pattern of querying a vector index for relevant chunks and supplying them to the LLM as grounding context, rather than relying on the model’s parametric knowledge. In Eunice, RAG runs over Corpora: user-facing corpora hold uploaded documents; system corpora (operational patterns, behavioural signals, data catalog, API docs) back the Knowledge-Is-Routing pre-fetch path. Implementation in knowledge/ and shared/knowledge_service.py. search_documents returns both an LLM-synthesized answer and raw source excerpts so downstream reasoning sees real content, not just a summary.

RBAC (Role-Based Access Control) The authorization model: users hold roles (system_admin, security_auditor at the user level; admin, member, viewer at the tenant level via TenantMembership); roles map to Capabilities in the role_capabilities table; endpoints check capabilities via @requires("..."). The mapping is DB-stored and runtime-adjustable. See shared/capabilities.py and shared/auth.py.

RelationshipEdge A typed edge in the cross-conversation dataset relationship graph. Row in the relationship_edges table; ORM model in shared/database.py. relationship_type is one of co_occurrence, lineage, schema_affinity, or user_affinity. Edges are written by fabric/semantic.py (SemanticExtractor) and pruned/rebuilt by the Dream Cycle. Feeds Kit discovery, the catalog graph view, and the get_dataset_relationships tool.

RoutingRule An adaptive routing rule generated by the dream cycle from observation patterns. Row in the routing_rules table; ORM model in shared/database.py. rule_type is one of tool_selection, validation_gate, default_parameter, workflow_template, or output_format. Rules are proposed at low confidence and earn their way up through observed outcomes. Distinct from PolicyRule (asserted up front, machine-readable operating policy), routing rules are learned, mutable, and can be user-, region-, or globally scoped.

Runner engine/runner.py. The contract surface around the turn loop: constructs TurnState and TurnConfig at request entry, calls populate_state_from_persistent_store(state) to mirror the legacy module dicts (_conversation_namespaces, _session_states, _conversation_tool_history) onto typed fields, then hands off to _execute_agentic_turns. Read-through wiring today; the executor still reads/writes module dicts directly. The future end-state is: runner is the only thing that builds state, executor is the only thing that mutates it.

S

Session State Ephemeral in-memory working memory per conversation. Lives in engine/session_state.py. Tracks active goal, task stage, active datasets, verified keys, and failed approaches. Not persisted. Injected as [SESSION_STATE] in the system prompt. Distinct from conversation history (persisted) and user profile (cross-session). The Turn Contract migrates these fields onto TurnState; the module-dict storage remains today as the canonical store while consumers move over.

SSE (Server-Sent Events) The HTTP streaming protocol the chat endpoint uses to push events from the backend to the frontend. The DisplayFactory drains the per-request event queue as an SSE stream; the frontend consumer parses the event: / data: framing and routes by DisplayEvent.type. Distinct from WebSockets, SSE is one-way (server → client) and survives most corporate proxies. Frontend consumer lives in frontend/src/lib/attachStream.ts and frontend/src/hooks/useDisplayEvents.ts.

SSEChunk Pure data in engine/turn_types.py, {event, data}. Carried inside the StreamChunks Effect. The wire layer can flush the chunk list incrementally; the executor produces one StreamChunks per turn for replay readability.

T

Temperature A score from 0-100 computed from recency, frequency, and breadth of dataset usage. Hot (≥70) datasets get full context in the prompt; warm (≥30) get a summary; cold (<5) are excluded. Computed in fabric/temperature.py. Drives display ordering on the Fabric page. Dataset temperature, not LLM inference temperature.

Tenant An organizational boundary. All data is tenant-scoped. Default tenant is epa-default. Users belong to tenants via TenantMembership. Enforced via tenant_id columns and TenantContext in request middleware.

ToolBuilder The agent that uses an LLM to generate a tool implementation from a spec. Lives in engine/tool_builder.py. Routes to the tool_build_simple or tool_build_complex model role based on the spec’s complexity flag, augments the prompt with the relevant dataset profile and similar existing tools, and parses the LLM response with extract_json_from_response. Output is a candidate (name, implementation, test_code, schemas); it approves nothing. Reached through the registry as the write_tool_code tool, the code-writing step of the build-tool platform skill; the candidate is reviewed by review_tool_candidate and approved only by register_tool.

ToolJobQueue (retired) Retired in CUSTOM_TOOLS_AS_PLATFORM_EXTENSIONS_ADR step 3 with its approve-on-test-pass path. engine/tool_jobs.py now only reads historical tool_jobs rows (get_job_status, list_jobs) for the job-status endpoint; write_tool_code builds are recorded there too.

ToolResult The legacy return type from every tool handler. Dataclass in engine/tool_result.py with fields: content (text for the LLM), cards (list of card dicts), cost (USD), datasets (DataFrames to register in the catalog), exports (generated files to register), error (failure message). The Uniform Tool Contract replaces this at the tool boundary with an Ok | Hint | Err envelope; ToolResult remains the adapter shape the orchestrator currently consumes, via envelope_to_tool_result in the contract decorator. Both shapes coexist until the deferred-tool ratchet is empty.

ToolRuntime Outward-facing dependencies a turn passes to tool handlers (engine/turn_types.py): llm, tool_registry, catalog, knowledge_service, config, clock, ids. Replaces the previous grab-bag context: dict. State is passed separately as the third argument to handlers that need it, mutation surface is signature-visible.

ToolSpec The per-tool registration record in engine/contract.py (Uniform Contract): name, handler, is_tabular, expected_envelopes, is_cost_rollup. is_tabular flags an empty-schema Ok as a smell (validator warning) for data-producing tools and legitimizes it for render/document/metadata tools. is_cost_rollup=True exists for exactly two tools, delegate and delegate_batch, and tells the decorator to skip the usage_log write so leaf rows aren’t double-counted. Stored in the module-level _TOOL_SPECS dict populated at handler import time.

TurnConfig Resolved per-turn configuration (engine/turn_types.py). Built once per request by engine/config_resolver.resolve_turn_config(...) from settings + tenant overrides + conversation overrides + per-request overrides. Carries model id, max output tokens, temperature, loop budget (max_agentic_turns, cost_budget_usd), and dispatcher knobs (failed_approach_threshold). All knobs a turn reads come from here, not from shared.config.settings directly.

TurnError A failure that occurred during turn execution. kind is one of tool_failure | llm_failure | policy_block | budget_exceeded | internal. All errors are terminal in v1, TurnResult.__post_init__ enforces that non-empty errors implies state.end_reason == "error". Dual emission contract: whenever an executor builds a TurnError, it MUST also append a TelemetryEvent(event_type="error", ...) to result.effects. Recoverable failures (model can react and try again) surface as tool_result blocks inside messages_appended, NOT as TurnError entries.

TurnResult Everything a turn produces (engine/turn_types.py): the post-state TurnState, the new messages_appended, the effects list, any errors, the optional final_text, the cards collected during the turn, the per-tool execution log, and an optional human-readable work_log. Has a to_legacy_dict() method that builds the {message, cards, metadata} shape the public chat API and legacy callers still consume.

TurnState The single source of truth for per-conversation state carried across turns. Dataclass in engine/turn_types.py. Six rules: only home for per-conversation state (no module dicts long-term), all fields typed, mutable inside execute_turn and immutable to callers, serializes cleanly to JSON for replay, holds no infrastructure references (those live on ToolRuntime), and end_reason is the single termination source of truth. Today populate_state_from_persistent_store mirrors module-dict storage onto TurnState at turn start; the executor body still writes through the dicts. Migration is ongoing.

U

Uniform Tool Contract The contract that promotes every tool’s return value to one of three named variants, Ok | Hint | Err, routed through a single decorator (@uniform_contract) and rendered into one model-facing format at every tool boundary. The implementation is live on this branch: engine/contract.py, engine/contract_decorator.py, engine/contract_resolvers.py, engine/contract_render.py, engine/contract_schema.py, and engine/contract_telemetry.py, applied at the dispatch boundary by engine/tool_registry.py:_apply_contract.

The three result variants:

VariantCarriesMeans
Okrows, schema (measured), data, warnings, effects (cards/datasets/exports/cost)Success. Schema MUST be measured from real data, never declared.
Hinthint_kind (schema/fetch/ambiguous), message, alternatives (each with label, score)Recoverable correction the model can act on. NO data, NO effects.
Errmessage, err_kindAn actual bug or infra failure. Reserved for unhandled exceptions, connection refused, OOM, permission denied. If the model could recover by re-calling, it’s a Hint instead.

Warning (in Ok.warnings) carries advisories that don’t block success, no_match, geo_incoherence, data_quality, etc. Coherence advisories ride here because they need the data to also come back.

Effects on Ok is the orchestrator-consumed side-effect channel: cards (frontend), datasets (catalog), exports (Fabric files), cost (FinOps). NOT rendered into the model’s view. Disambiguate from the Turn Contract’s Effect catalogue, which is turn-level (PersistAssistantMessage, TelemetryEvent, StreamChunks).

@uniform_contract decorator: detects asyncio.iscoroutinefunction(handler) at decoration time, emits a sync or async wrapper, catches HintException BEFORE generic Exception, calls _record_contract_telemetry, calls _persist_effects, returns the envelope. migrate_tool(handler, name, is_tabular, is_cost_rollup=False) is the bulk path: the handler returns UNCHANGED (still emits ToolResult/dict) but a ToolSpec is registered and the registry wraps at registration via _apply_contract. Bulk migration applies the contract at the dispatch boundary, not at source, which is what makes ~100 tools safe to migrate without breaking direct callers.

envelope_to_tool_result is the registry-level adapter that converts a returned envelope back to the legacy ToolResult shape so the unchanged orchestrator path keeps working. Ok → rendered content + cards/datasets/exports/cost from effects. Hint → rendered content with error=None (recoverable; test runners count it as a correction, not an error). Err → rendered content with error=msg.

CI ratchet: tests/test_uniform_contract.py + tests/contract_deferred_baseline.json compute DEFERRED_TOOLS from registry-absence-of-marker and assert subset-of-snapshot, the set can only shrink. The 31 deliberately deferred tools include the demo-critical spatial/document/analysis surface, the streaming exceptions (call_llm, web_search), and the rollup-cost path (delegate, delegate_batch).

W

WAL (Write-Ahead Log) The durability log behind the AsyncExecutionService. Lives in infrastructure/wal.py; the service holds an optional JobWAL and writes job-state transitions through it so in-flight jobs survive process restart and crashed workers can be recovered on the next boot. Distinct from a database WAL (e.g., PostgreSQL’s), this is the async-job journal, not the SQL storage engine’s transaction log.

  • Runtime Flow, how these concepts interact during a chat request
  • Tool System, tool registration, dispatch, and the contract seam
  • Engine, orchestrator/runner/executor/dispatcher/persister breakdown
  • Fabric Module, catalog, Kits, intelligence, dream cycle
  • Shared Layer, connector, display, LLM clients, telemetry
  • Database Schema, tables behind these terms
  • Architecture, governing principles