Skip to main content
Glama

CAVEAT Language

A decision ledger for agents.

Caveat is an embeddable decision runtime with a small rules language. It tracks evidence through computations, preserves the grounds of recorded decisions, and supports reconsideration under authored policies when evidence changes.

The published preview is 0.1.0-rc.20. See the rc.20 release record for what it changes.

npm publication verified 2026-10-15T20:51:15.212Z: exact caveat-lang@0.1.0-rc.20, tested Linux artifact SHA256 8b4e6b4855e822c824f854f36d4bda1b83c7792e784e00ed25505ecec9d4465a. Published by publish-npm.yml from tag v0.1.0-rc.20 with an npm provenance attestation. After the owner's channel update, both latest and next were verified at rc.20 on 2026-10-15. Publication record.

When a tool result is corrected or a memory turns out to be stale, an application needs to reconsider its decision without losing the reasons for the original. Caveat is a programming language that keeps evidence and caveats with computed values, freezes a decision's grounds, and records why it was reopened.

Try the published preview, 0.1.0-rc.20, in an empty directory with Node 20 or later. No Rust installation is needed:

npm init -y
npm install caveat-lang@0.1.0-rc.20
npx --no-install caveat-lang init
npx --no-install caveat-lang test umbrella.scenarios.json
npx --no-install caveat-lang explain umbrella.cav events.jsonl

The two scenarios pass. The explanation shows umbrella@1 = 70 reopened by sky, still based on rain_chance@1 with its forecast_is_old caveat. New knowledge changed the decision's status; its original grounds remain visible. Getting started walks through those files, and the language in brief covers the syntax.

The rc.20 verified publication record identifies the exact tested npm artifact. rc.20 clarifies when to use each MCP tool, its inputs and its results. It also fixes human-readable explanations of caveats carried by a decision's grounds, retained in its frozen basis, or present only in its wider lineage. It changes no Rust runtime, language or save format.

rc.19 began the 1.0 feature freeze: it added no language, schema, operation, field, CLI flag or export. It fixed restore of a session that reopened a decision because of a caveat and then took that caveat back; saves written by rc.18 in that state restore in rc.19.

rc.18 added unqualify, which takes back a caveat that qualify added, on every held occurrence of the evidence. The take-back is recorded, not erased, and decisions keep their basis. A save of a program that uses unqualify does not restore in rc.17 or earlier; other saves do. View 0.2 now lists a binding's evidence in the order it was first observed, and explain names the event and payload that observed each ground.

rc.17 introduced View 0.2, source digests in saves and the integration starter (caveat-lang/starter); the digest identifies the source and does not authenticate a save. rc.16 introduced departure of eligible retired history, host-drained archives and collection of unreachable withdrawal groups; see the history integration guide. rc.15 introduced integer clocks, history windows and caveat test checking each program first. rc.14 corrected the package's MCP server name to io.github.WSattazahn/caveat-lang. rc.13 introduced interface JSON and TypeScript declarations, stricter restore checks and refused invalid id_text operations. Restoring a save still does not authenticate its history. A refused operation is not completed; hosts must inspect its outcome. The package has no npm runtime dependencies.

With rc.20 installed, use npx --no-install caveat-lang doctor to check it and npx --no-install caveat-lang demo agent to see observation, assessment, correction and revision in one run. Introduced in rc.7, the unambiguous caveat-lang command remains preferred; caveat is supported shorthand. See CLI names.

Integrating an agent? Follow the agent quickstart and the official Python client. Caveat records supplied evidence and authored policy; it does not authenticate evidence or authorize external actions. Repository agent guidance includes how to report a capability missing from a real integration.

What stands behind it? What is checked, and how separates the Lean model theorems (proofs/lean), sampled native and WebAssembly conformance with mutation controls, runtime tests, and the boundaries nothing proves. It also states the limits: windows do not bound saves, nothing is authenticated, and hosts set their own resource budgets.

Principles and capabilities

For the thinking behind Caveat, read The Caveatist way.

Say what you know, and what it rests on.
Carry the caveats honestly.
Give uncertainty the attention its consequences deserve.
Act when there is enough to proceed.
Remember why you chose, and remain willing to choose again.

These are the project's principles. They are not additional license conditions: Caveat is under the MIT License, and using it does not require adopting them.

  • Values carry their evidence. Every number computed from an observation carries that evidence and its caveats through every sum, comparison and label.

  • Explanations are checked against recorded dependencies. Anything a program shows can say why, and the runtime rejects an explanation that cites something outside the value's recorded dependencies. That does not prove the evidence true or the explanation complete.

  • Decisions remember. A decision records what it was made on, reopens when the world disagrees, and keeps a journal.

  • Late knowledge is one line. A late qualification reaches current values built on the evidence and future values that read it. Archived readings and decisions already made keep what they knew.

What Caveat is for, on one page: the problem, one example to run, and the limitations.

Play the glowcap explainer. Four look-alike mushrooms, a belief, a trust decision that is made, doubted and remade, and a "why?" under everything on the page. The rules and explanations all live in game/glowcap.cav; the page only renders them.

Start with Change what you know at the top of that page. Make a decision in one click, learn something new in a second, and see what changed, why the decision reopened, and the original reasons it kept.

Trail Rescue is a new, complete mechanic: spend three scout tokens, weigh fallible reports, choose a tunnel and reconsider when its evidence changes or ages. Its requirements and 24 scenarios were committed before implementation. The Caveat program owns the rules; the browser page displays its decisions and frozen explanations. Build and run it with npm run build, npm run serve, then open http://127.0.0.1:4173/trail-rescue.html.

The mechanic added state caveat queries: has_caveat(plan_basis, stale) checks the actual grounds of a saved basis, and reopen route because caveated(plan_basis, stale) cites the precise observations that have gone stale. The journal now preserves elapsed time and the chosen numeric value, and restore checks its consistency with commitments and evidence. See the implementation record.

Fresh-agent authoring: six fresh contexts authored three specified policies using a frozen documentation packet, without private-test feedback. Two first submissions and all six final submissions passed the registered corpus: 20,512 final-source events and 4,788 restores. All four initial failures exposed an unclear numeric-bound restriction, now documented. Two final programs still have known clock-horizon contract violations outside the corpus. The study report preserves those limits, every revision and the independent verification.

Reactive source can now read the runtime clock directly with elapsed(): bind hud.elapsed = elapsed();. It uses the same time as scheduled caveats and decision journals, survives save/restore, and removes the need for a separate bounded state timer.

A four-context follow-up repeated the two clock tasks with this read and the updated guide. Three first submissions and all four final submissions passed: 13,704 event dispatches and 3,158 restores. All four used elapsed() directly, without a separate state clock. The remaining first-source failure was unsupported comment syntax, repaired by its author. This is evidence on two repeated tasks, not a general reliability claim.

The reactive runtime also offers structured dispatch outcomes. dispatch_outcome distinguishes an authored policy rejection from invalid input, state-bound failure and execution-budget exhaustion. Unclassified errors remain fatal. Existing dispatch methods retain their behavior; new integrations can use the explicit outcome contract when testing why an event was refused. A host that redraws from the view uses dispatch_view_outcome (session.dispatchView in the developer kit): the same outcome, with the view in place of the snapshot.

Related MCP server: agent-fact-system

What Caveat makes part of the language

These mechanisms can also be implemented and checked in a general-purpose language, through application code or libraries. Caveat supplies them together as language and runtime facilities; the comparison is about what an author has to provide, not what another language can express.

Caveat

In a general-purpose language

Explanations

bind label = "Could be a duskcap" when … because contradiction; The runtime checks cited evidence and caveats against recorded dependencies.

Implement dependency tracking and citation checks, or use a library that supplies them.

Caveats through computation

qualified(1, taste, tasted_in_dark) carries evidence and caveats through computations that use it.

Use provenance-aware values and operations to propagate the same information.

Late caveats

qualify taste with taste_faded; qualifies current values built on the taste while earlier decision records retain their frozen caveats.

Track dependencies or resolve qualifications when read, and freeze decision records.

Decisions that remember

commit, reopen, and decision-series revisions retain each revision's grounds and publish its changes in decision_journal.

Implement decision records, frozen bases and an ordered change journal.

Grounds and lineage

The runtime distinguishes a value's content grounds from its wider control lineage and enforces grounds ⊆ lineage.

Represent both kinds of dependency and enforce their relationship in code or a library.

Atomic events

reject "already absorbed"; rolls back the event's changes to the Caveat session.

Use transactions, immutable state or explicit rollback to publish changes atomically.

Citation checking establishes that cited dependencies were recorded; it does not establish that supplied evidence or authored explanation prose is true. Citations may omit dependencies, so the check does not establish completeness.

The evidence: the glowcap benchmark

The glowcap benchmark implements the same game beat twice, in TypeScript and in Caveat:

  • a frozen, pre-registered scenario suite;

  • sixteen change requests, twelve committed before either implementation changed for those rounds;

  • seeded differential fuzz comparing accepted and rejected events, views, and save/resume behavior.

Round

Change cost, Caveat vs TypeScript

Result

1 · first version

55 vs 57 (CR1–4)

Parity. The weak spots became the language's work list.

3 · blind requests

97 vs 53 (CR5–8)

TypeScript. Caveat's lineage fought the designer's meaning.

5 · replay after language changes

71 vs 110 (CR1–8)

Caveat, with 134 lines against 164. Written knowing the requests.

6 · blind requests

92 vs 103 (CR9–12)

TypeScript. Caveat passed two of four phases on the first run, capped regrowth at eight lives, and exceeded the 1 ms event budget.

6 · replay after language changes

88 vs 103 (CR9–12 plus correction)

Lower change cost; mixed size (168 vs 233 lines, 12,701 vs 11,586 bytes). Three of four phases passed on the first run. Written knowing the requests.

7 · fresh authors, blind requests, rc.11

186 vs 282 (CR13–16)

TypeScript. Two of four phases on the first run against four; more regressions; no Caveat save stayed bounded with a fast resume in long play. Neither decision rule met.

Round 7 left a work list: a save that forgets what the program forgot, ordered grounds, timing to the tick and the adapter glue. No claim that Caveat is better than TypeScript goes into the README, AGENTS, the site or other documents on the strength of this round.

The earlier losses led to grounded explanations, grounds, reject, define, typed parameters, the view, late qualification and the decision journal.

Round 6 led to incremental evaluation, a load-time observation-order check, procedures that take evidence, renewable evidence and timed caveats, and save/restore without event replay. The replay passes all 38 scenarios and a separate twelve-life regrowth check beyond the old eight-life cap. Its evidence still has a declared limit of 1,024 lives per mushroom: the request for unlimited regrowth remains unmet. Its first save-format attempt exceeded the size limit; that failed run remains in the results.

The replay's first 2,000-sequence fuzz found five disagreements in about 7.3 million events. JSON parsing changed some floating-point values by one unit in the last place, moving timed behavior across a boundary. Exact round-trip parsing fixed those timing differences. Final review then found the fuzz was hiding a decision-basis ordering bug by sorting that list. The adapter now uses the journal's ordered evidence, and an order-sensitive comparator checks it. That correction adds two changed lines to the original 86. The five captured sequences and both stricter 2,000-sequence fuzz runs now agree: 14,443,471 fuzz events with zero divergences. The blind round remains a TypeScript win, and this replay does not establish an adoption win under the same rule: size is mixed and only change cost is clearly better.

What Caveat still costs, honestly:

  • 51.6 µs median per event plus view for the replay program, against 2.5 µs for TypeScript, measured after the fuzz;

  • 482,716 gzipped bytes (about 483 KB) for the Caveat policy, adapter and runtime;

  • rounds 4, 5 and the round-6 replay were written knowing the requests; round 7, the blind round with fresh authors that followed, went to TypeScript.

A taste

event absorb target kind mushroom, sort in glowcap duskcap;

for mushroom as $m {
    on absorb when $m_here and $m_consumed == 1 reject "already absorbed";
    on absorb when $m_here and sort == sort.glowcap
        set support = support + qualified(1, absorb_$m);
    on absorb when $m_here and sort == sort.duskcap and committed(trust)
        reopen trust because absorb_$m;
    on tick when $m_tasted_at >= 0 and now - $m_tasted_at >= 60
        qualify taste_$m with taste_faded;

    bind $m.label = "Probably a glowcap" when $m_unknown and probably_safe because support;
    bind $m.label = "Could be a duskcap — taste first" when $m_unknown and uncertain because contradiction;
};

Read Why Caveat for side-by-side code and the Caveatist way of working. To write your first program, start from the authoring guide.

MCP server

The package includes a local MCP server, caveat-lang mcp, that gives an agent Caveat's authoring operations as tools. It runs over stdio, needs Node 20 or later and no Rust, and is listed in the MCP Registry as io.github.WSattazahn/caveat-lang (server.json). Add it to an MCP client's configuration:

{
  "mcpServers": {
    "caveat-language": {
      "command": "npx",
      "args": ["-y", "caveat-lang@0.1.0-rc.20", "mcp"]
    }
  }
}

Tool

Inputs

Result

caveat_validate

source

Whether the program loads and what it declares

caveat_check

source, optional strict

Authoring diagnostics and suppressed warnings

caveat_test

source, scenarios

Scenario results, invariant checks and check warnings

caveat_explain

source, optional events

Decisions, their exact grounds, caveats and history

caveat_dependents

source, subject, optional events

What depends on the named evidence, stream or caveat

Every tool works on inline source text and supplied events. The server has no file, network or persistent-session tools, and it runs each call in a fresh subprocess with a 10-second limit. It speaks MCP 2026-07-28 and the 2025-11-25 profile. MCP setup and limits covers the protocol, result format, limits and a configuration for an installed copy. A tool's report does not authorize an external action or authenticate its evidence.

Status

CAVEAT 0.3 is executable, and the 0.4 game profile adds executable knowledge requirements, evidence-dependent outcomes, and source-authored spatial presentation. The Rust reference runtime parses source, evaluates the epistemic graph, exposes the CAVEAT Map, and runs the same game program in a terminal or a WebAssembly browser session. The new features are specified in Draft 0.4.

Other playable examples include Light the Way, a direct-control ferry rescue powered by the new reactive CAVEAT profile. Movement, scouting, collisions, damage, score, and outcomes are source rules. The Last Beacon remains a separate 3D island mystery whose available decisions, evidence, retained uncertainty, nine outcomes, locations, cameras, and paths are authored in game/the_last_beacon.cav. Moon Garden remains a short mobile-first mystery with both a 2D presentation and a separate Moon Garden 3D presentation driven by the same CAVEAT session. The earlier The Door scenario remains the world/action stress test.

CAVEAT 3D 0.2 now consumes normalized Rust action-runtime executions (Move, Inspect, Operate, Open, Observe, Stay) and maps those commands to semantic place/entity/symbol presentation bindings. Moon Garden no longer needs normal per-action camera choreography. See spec/caveat3d-0.2.md. The remaining graphics problem is art-direction automation: semantic identifiers can now drive the scene, but attractive camera composition and assets still require authored presentation bindings.

Light the Way — play immediately

Play Light the Way. Hold and drag the lighthouse beam, or use the arrow keys. Steer the ferry around reefs into the green harbor. Hold the light over the current marker to take a reading while the ferry keeps moving. When the storm shifts, decide whether to correct the old plan manually or spend another second scouting. Damage, sampling progress, and rescued passengers appear directly in the scene. Retry immediately. No download or reading panels are required.

The new reactive language profile adds bounded numeric state, typed events, arithmetic, ordered conditional rules, and atomic event execution. The same rules can read and change CAVEAT's actual evidence graph. In the game source, spotting a reef records evidence, pays to examine the associated caveat, reopens the initial course commitment, and makes the ferry slow near the known danger. The original chart claim and contrary evidence both remain in the graph.

state boat_x = ferry.x min -9.5 max 13;
event tick dt min 0 max 0.1;
on tick when phase == 1 set boat_z = boat_z - boat_speed * dt;

The reactive 0.2 extension adds reusable numeric functions, evaluated presentation bindings, explicit sound/visual cues, source-declared controls, and a source-declared clock. The rescue's screen transitions, feedback, visual state, and keyboard steering now live in the Caveat program. Cues publish only when their event commits; a failed calculation rolls back its graph changes and feedback together.

Reactive 0.3 carries evidence and caveats through numeric values, arithmetic, function calls, comparisons, and conditional decisions. A commitment made using a derived value automatically retains its caveats and records a frozen numeric basis plus relies_on evidence edges. The crosscurrent's source-authored observation and steering functions exercise these semantics; the browser continues consuming ordinary rendering values.

The crosscurrent demonstrates why that matters beyond moving code: a qualified forecast supports an initial navigation commitment; an opposing observation reopens it and leads to counter-steering while retaining the unresolved caveat. Observation changes the navigator's response, not the physical current. Both evidence histories remain inspectable. Preserving Caveat's essence records the invariants and the remaining Rust/browser boundaries.

The current shifts twice during the crossing. A previously measured steering correction keeps its old value until a fresh sample supports a revised plan. Bright arrows show the surface flow; faint arrows preserve the last reading, and the HUD shows its age. Rescouting has an immediate cost: the same light must stay over the marker while the moving ferry still needs steering.

Reactive 0.4 adds bounded text expressions and conditional expressions. The standard functions abs, min, max, and clamp are implemented in Caveat source, replacing their Rust algorithms. Source functions also format the game's clock, numbers, and percentages; source state owns notice lifetimes and hull indicators. Rust still implements the evaluator and browser bridge. This is a first source-defined standard library, not a self-hosted compiler.

Reactive 0.5 adds bounded reading streams and decision series. Each sample creates a distinct evidence occurrence, even when the measured number repeats. latest(flow) reads its qualified value; a decision series records a new frozen basis after its previous decision is explicitly reopened. Old occurrences remain addressable in snapshots and graph relations. The game uses one sampling procedure and one navigation series across repeated weather changes, replacing its separate first-reading and storm-reading implementations.

The same capability is exercised by a thermostat program: cold, warm, and cold readings revise the heating command while preserving every reading and the unresolved calibration caveat. Run cargo test --manifest-path runtime/Cargo.toml --test thermostat_history to exercise its input history and rollback behavior. This is a separate source consumer of the generic language feature, with no thermostat logic in the interpreter.

Reactive 0.6 makes retained history available to source computation through history_count, zero-based history_at, and fold_history. Reducers are ordinary pure Caveat functions: summing, calculating a range, or choosing a history-based policy requires no corresponding Rust algorithm. Results retain the observations, caveats, and selection dependencies involved. Invalid indexes, reducer errors, and bounded-work failures roll back the whole event. The thermostat calculates mean/range/trend in source, while the game compares archived readings to report a measured flow reversal. This is bounded history computation, not yet arbitrary collections or self-hosting.

Reactive 0.7 adds reusable effect procedures. A proc can share input handling or a sequence of observation and revision steps across source events. Calls freeze their numeric arguments and entry guard, retain every argument's qualifications, and run within the calling event's atomic transaction. The game shares keyboard cleanup, held-input activation, and aim movement; the thermostat records and revises through a source procedure. Rust provides bounded calls and validation, while the behavior remains Caveat source.

Explanations 0.1 lets a binding say what it cites: bind label.text = "…" when … because contradiction;. The runtime checks the citation against the binding's lineage, so an explanation may leave dependencies out but can never cite evidence or a caveat the value and its conditions did not read. The full lineage stays available for audit.

Explanations 0.2 separates what a value is based on (its grounds) from everything that could have influenced it (its lineage). A rule’s guard, a skipped rule, the guard that revealed evidence, and a decision’s predecessor all stay in lineage but never enter grounds. Citations read grounds, set x = e because c narrows them, and grounds are always a subset of lineage.

Reject 0.1 adds reject "MESSAGE": an event that is not allowed fails atomically with that message, without a dummy state or a require trick.

Define 0.1 adds define NAME = EXPRESSION;, a named expression over state and the graph that is inlined wherever it is read, including per member inside a for block.

View 0.1 adds dispatch_view: the same transaction as dispatch, returning only what a host redraws after an event (bindings and their citations, cues, effects, commitments and their grounds, relations) as compact JSON.

Typed Parameters 0.1 lets an event take an entity by name (target kind mushroom) or one of a list of names (sort in glowcap duskcap). The host sends names; the source reads positions, with sort.duskcap and target.pool as constants.

Late Qualification 0.1 adds qualify EVIDENCE with CAVEAT: a caveat learned after the fact reaches every current value built on that evidence, while decisions already made keep what they were made on.

Decision Journal 0.1 publishes every commitment and reopening, in order, with the evidence each was based on in the order it was observed.

Observation Order 0.1 rejects, when a program loads, a rule that qualifies a value with evidence only a later rule of the same event can reveal: a use that can only fail. Uses that could succeed on some dispatch are left to the runtime.

Procedure Symbols 0.1 lets a procedure take evidence, a claim, a caveat, a reading stream or a decision series by name (proc learn(e evidence, sort)), so every way of observing something can share one set of rules. Each call is specialized for the names it passes when the program loads.

Identifiers 0.1 lets an event carry text the program first learns while it runs, such as a commit SHA (event pushed commit id;). The program sees a numeric handle for each distinct text, and id_text shows the text again.

Withdrawal 0.1 records that an observation is no longer stood behind (withdraw latest(checks) because recheck;). Nothing is erased: decisions keep what they were made on, current values and later reads carry a withdrawn caveat, and rests_on_withdrawn(D) lets a program decide what the withdrawal means for a decision.

Permission 0.1 records what permitted a decision, apart from what it rests on (commit merge … permitted by latest(approvals) for head;). A missing, withdrawn or mismatched grant refuses the commit as policy/not_permitted, and the frozen record says which grant permitted it, for which value.

Reopening Triggers 0.1 lets a decision series declare which readings reopen it (decisions merge limit 8 reopened by pushes, checks opposing ready;), instead of a hand-written reopening rule after every such reading. The reopening is exactly the authored one, run at the moment the reading is taken.

Check 0.1 is caveat check: advisory warnings about patterns worth a second look, such as rules repeated across events that one procedure could share, or a decision made on readings that nothing reopens. A warning is not a proven fault; # caveat check: allow CODE records a pattern that is intended. The kit's one-page reference gives the language in brief, and its worked example takes one program through every command, with output the tests check.

Renewal 0.1 gives evidence an identity that events create: renewable taste_cave limit 256; and renew taste_cave make the name mean a new, unobserved occurrence while earlier ones keep what they were about. qualify taste_cave with taste_faded after 60 fades that occurrence on its own clock, and carries(taste_cave, taste_faded) asks whether it has.

Save 0.1 saves a session and restores it without replaying events: WebReactiveSession.save() and WebReactiveSession.restore(source, saved). Restoring costs what loading costs plus the size of the save. Restore validates the saved names, values and histories; mutation tests check that an altered save is either refused or remains playable without a crash.

Incremental Evaluation 0.1 makes an event cost what it touches: a binding is evaluated again only when something it reads changed, and a transaction copies only what its effects write. Round 6's 32-entity program went from 1.1 ms to 0.16 ms per event with identical results, checked against full evaluation after every event in the test suite.

Water time and accumulated rain travel now come from Caveat state too. The source-defined wrap function keeps travel bounded; the renderer maps those values onto its existing wave shader and seeded rain geometry. Pausing or replaying a session preserves the corresponding weather pose.

The browser sends input and elapsed time to generic WebReactiveSession, then draws its snapshot. It does not calculate the ferry's movement, collisions, damage, route rules, or rescue result. Rust implements the language interpreter; the game-specific rules are Caveat. Design notes explain the controls and the source/runtime/renderer boundary.

Keyboard policy also lives in Caveat: source-declared physical-key controls retain independent presses and releases, combine aliases and opposing keys, and steer during source ticks. The browser forwards those input facts. A source-only remapping changes the playable controls; observing, examining, and reopening still follow the same qualified event rules.

Pure Caveat functions are callable through the source library API from Rust and WebAssembly. The Door's movement timing and turning policy now live in its Caveat source, and The Last Beacon's feedback classification and copy use source functions. The same compiled evaluator serves both hosts. Full program validation and host transaction boundaries remain explicit.

For headless authoring, caveat-reactive validate checks a reactive program and caveat-reactive replay executes JSONL event histories with qualified snapshots. The authoring guide includes commands and a thermostat input fixture. Development insights separates demonstrated behavior from hypotheses about broader usefulness and AI adoption.

The Slime glow ability policy is a small host-integration consumer: a reported mushroom absorption creates one qualified learning receipt, and ordinary ability toggles retain that basis without growing a per-input history. Glow controls require a separate host-verified renderer capability; without it, the source reports the mushroom discovery without claiming light. Native and real WebAssembly tests exercise 10,001 ready toggles, early discovery, duplicate absorption, reset and source-only policy variation. Vessel's world contact, inventory transaction and visible glow remain host responsibilities.

The Last Beacon — story experiment

On stormbound Saint Orin, thirty-two ferry passengers are approaching a failing lighthouse. Spend three watches investigating uncertain evidence, try provisional plans, reopen them when the world disagrees, and choose between restoring the light, sending the island pilot, or holding the ferry offshore until daylight. Six interactions produce 324 legal decision sequences and nine outcomes across three final destinations. Earlier investigations unlock targeted preparations; performing those preparations changes what the same final order accomplishes. See the game design and action contracts.

The game also develops the language runtime. The generic Rust GameSession and WebAssembly WebGameSession apply world actions and epistemic effects atomically, expose the graph reached by the player's actual decisions, and restore saves by replaying source-checked selections. The parser now supports quoted semicolons, escaped and Unicode text, line comments, and source locations in errors. These capabilities are available to any CAVEAT program; see the game-session specification and source-text specification.

These are actual game-source statements:

require bridge_reserve observed reserve_charge;
resolve relight_beacon as beacon_guided when observed measured_pulses;
resolve relight_beacon as beacon_limited when observed hot_cable;
resolve relight_beacon as beacon_limited when observed split_beam;
resolve relight_beacon as beacon_unverified otherwise;

The runtime checks the reached evidence graph before an action. Declared but undiscovered evidence cannot unlock it; contradictory evidence remains recorded. The browser receives available choices, blocked reasons, and the selected outcome from CAVEAT. It supplies reusable graphics and controls. Presentation declarations also place the world and compose its views without changing JavaScript.

Play the earlier story. This hosted copy opens directly in your browser; downloading an HTML file is optional.

Build and play

With rustup and Node.js 20 or newer installed, run from the repository root. rust-toolchain.toml pins the compiler, and rustup installs it with the WebAssembly target on first use:

cargo install wasm-bindgen-cli --version 0.2.104 --locked
npm ci
npm run build
npm run serve

The build also writes dist/pkg-reactive/: the same runtime without the sequential, graphics and 3D sessions, for hosts that only run reactive programs (cargo build --no-default-features). It is about a fifth smaller.

Open Light the Way locally. The earlier story experiment remains available. The build compiles the Rust runtime to WebAssembly and assembles dist/ with game sources, browser assets, and a local copy of Three.js. Existing games remain available in the same build.

To play the earlier Last Beacon story in a terminal, without a browser or JavaScript:

cargo run --manifest-path runtime/Cargo.toml --bin caveat -- --game game/the_last_beacon.cav

For an optional offline copy, run npm run package:game after building. Open dist/Light-the-Way.html in a full modern browser (dist/The-Last-Beacon.html contains the earlier story): it embeds the actual CAVEAT WebAssembly runtime, story, and graphics and works without a server or network connection. Some file-preview applications disable scripts or module imports; those previews cannot run the game. The launch screen now includes browser guidance, a retry action, and a timeout for failed or stalled imports. In the earlier story game, device-local saves preserve your watch. Choose with the buttons or keys 1–3, open the journal with J, and toggle ambient sound with M.

The workflow notes explain how the video's visual inspection and testing loop informed this implementation.

Verify

cargo test --manifest-path runtime/Cargo.toml
cargo clippy --manifest-path runtime/Cargo.toml --all-targets -- -D warnings
npx playwright install chromium
npm run test:beacon
npm run test:rescue
npm run test:slime-glow

Reactive runtime tests check atomic rollback and malformed input, and rescue simulations verify a complete crossing, damage, timing, and the direct effect of observed evidence on motion. Browser rescue tests use real mouse, keyboard, and touch input. The story tests exhaust legal Beacon routes, checking unavailable-action rejection, investigation costs, retained caveats, reopening, physical destinations, evidence-dependent outcomes, and save restoration. Browser tests exercise the WebAssembly game and its presentation, starting their own local server. Run npm run build first; a separate npm run serve process is not required for tests. After npm run package:game, npm run test:launch also exercises blocked imports, a stalled module, and disabled-script previews. npm run test:slime-glow needs no browser: it drives the installed WebAssembly runtime directly and checks the host-integration policy's bounded toggles, verified renderer capability, qualified escape, atomic failure, and malformed input. It runs in the same continuous integration job that assembles dist/.

Repository layout

  • spec/ — versioned language specifications

  • runtime/ — reference runtime

  • runtime/prelude.cav — source-defined standard math and display functions

  • tests/ — canonical semantic tests

  • examples/ — example CAVEAT programs

  • game/ — playable CAVEAT scenarios, including The Last Beacon, Moon Garden, and The Door

  • web/ — browser presentations and generic world rendering

  • scripts/ — reproducible browser build, local server, and game verification

Do not save CAVEAT by redefining it. If the computational model collapses into an existing paradigm, record the result.

License

Caveat's code and documentation are available under the MIT License. Third-party components keep their own licenses: the Rust crates compiled into the WebAssembly runtime are listed with their notices in THIRD_PARTY_NOTICES.md, and the site's copy of three.js ships with its license as vendor/THREE-LICENSE.txt.

Culture

Caveatism is the philosophy that grew up around Mr. Caveat, a mechanical fortune teller who always has a caveat; it lives in caveatism/ and is culture, not a contract of the language. The Archive and Atlas are its texts, and the canon keeps the Archive as a Caveat program with scenarios.

Mr. Caveat holding a fortune ticket whose fine print runs off the card

Available Tools

5 tools
caveat_checkA
Read-onlyIdempotent

Load a single-file program and report authoring diagnostics, such as repeated rules or a missing reopening path. Use after editing source; choose caveat_validate for a declaration summary and caveat_test for behavior assertions. A clean check does not prove behavior; bundles are unsupported. report (caveat-check/0.1) contains loads, strict, diagnostics and suppressed diagnostics, with code, location, message and suggestion, or a load error. exitCode: 0 completed without a strict failure; 1 strict with unsuppressed diagnostics; 2 load failure or bundle. Returns the same JSON in structuredContent and text: {schema:"caveat-authoring/0.1",operation,sourceSha256,runtime,exitCode,report}. Read exitCode even when isError is false. Bridge failures instead set isError:true with {schema:"caveat-authoring-error/0.1",error:{kind,message}}.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourceYesComplete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime.
strictNoOptional, defaults to false. When true, any unsuppressed diagnostic makes exitCode 1 instead of 0; suppressed diagnostics do not count. Does not change program behavior. Load failures and unsupported bundles remain exitCode 2.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish a safe read-only, idempotent profile, yet the description goes further: it defines exitCode 0/1/2 semantics, explains the strict-vs-suppressed interaction, warns to read exitCode even when isError is false, and describes the bridge-failure shapes. This is rich behavioral context beyond structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then routing, then behavior and return contract; nearly every clause carries distinct information. It is dense and long, but there is little true filler, so it earns most of its length rather than wasting it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully compensates by documenting the report shape, exitCode values, the structuredContent/text payload, and the error variant. An agent has everything needed to invoke the tool and interpret its result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both source and strict are already documented in the schema, including strict's default and exitCode effect. The description's 'read exitCode even when isError is false' adds tool-level context but doesn't meaningfully extend the parameter definitions, so the baseline 3 holds.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Load a single-file program and report authoring diagnostics') and gives concrete examples of diagnostics. It explicitly distinguishes itself from caveat_validate (declaration summary) and caveat_test (behavior assertions), so an agent can select it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use it ('after editing source') and names the two alternative sibling tools with the conditions that select them. It also sets a limitation ('bundles are unsupported') and a caveat ('a clean check does not prove behavior'), leaving little to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

caveat_dependentsA
Read-onlyIdempotent

Replay optional events and find what rests on one named evidence item, reading stream or caveat. Use for impact inspection; caveat_explain instead explains all decisions and their reasons. report (caveat-dependents/0.1) includes subject, kind, sequence, event outcomes, claims, decisions, changes, values, displayed values and withdrawal records; dependency entries distinguish grounds from possible influence through lineage. exitCode: 0 replay completed (may include rejected events); 1 fatal event with last good state; 2 load failure or unknown subject, with report.error. Returns the same JSON in structuredContent and text: {schema:"caveat-authoring/0.1",operation,sourceSha256,runtime,exitCode,report}. Read exitCode even when isError is false. Bridge failures instead set isError:true with {schema:"caveat-authoring-error/0.1",error:{kind,message}}.

ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNoEvents replayed in array order from a fresh session. Omitted or [] inspects the initial state; previous calls supply no history. Rejections are recorded and replay continues; a fatal event stops replay at the last good snapshot. At most 1,000 entries and 1 MiB of serialized UTF-8 JSON.
sourceYesComplete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime.
subjectYesExact case-sensitive evidence name, reading stream name, caveat name, or evidence occurrence ID after replay. Evidence records supplied observations; a reading stream is a named history of samples; a caveat is a qualification on evidence. For example, probe selects its evidence/readings, values selects a stream, and values@1 selects one recorded reading. Use a name from source or caveat_explain; not a file path, claim or decision name. Unknown names return exitCode 2.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent annotations by disclosing exitCode semantics (0 replay completed, 1 fatal with last good state, 2 load failure/unknown subject), the report contents, and the fact that isError:false can still carry a non-zero exitCode, plus the separate bridge-failure error schema. This is exactly the extra context annotations cannot supply.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the sibling alternative are front-loaded in the first two sentences, and each subsequent sentence carries real operational detail. It is dense and long for a single paragraph, which costs a point, but nothing is pure filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the full return contract — the JSON envelope, report fields, exitCode meanings, and the error shape — and adds the non-obvious caveat that exitCode must be read even when isError is false. Nothing needed to call or interpret it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents source, subject and events in detail, including payload keying and limits. The description adds only the loose hint that subject may be an evidence name, reading stream, or caveat, which the schema states more fully — baseline 3 is right.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — replay events and find what rests on one named evidence item — and names the subject kinds it accepts (evidence, reading stream, caveat). It explicitly distinguishes itself from the sibling caveat_explain, so an agent can route without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the use case ('impact inspection') and names the alternative plus the condition that selects it: caveat_explain explains all decisions and their reasons. The when-not is covered by contrast with that sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

caveat_explainA
Read-onlyIdempotent

Replay optional events and explain the resulting decisions, evidence and displayed values. Use to answer why a decision was made; choose caveat_dependents to trace one evidence or caveat name forward, and caveat_test for assertions. report (caveat-explain/0.1) includes sequence, event outcomes, decisions with grounds and revision history, evidence with caveats, displayed values and available archive history. exitCode: 0 replay completed (may include rejected events); 1 fatal event with last good state; 2 source load failure (report has loads:false and error). Returns the same JSON in structuredContent and text: {schema:"caveat-authoring/0.1",operation,sourceSha256,runtime,exitCode,report}. Read exitCode even when isError is false. Bridge failures instead set isError:true with {schema:"caveat-authoring-error/0.1",error:{kind,message}}.

ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNoEvents replayed in array order from a fresh session. Omitted or [] inspects the initial state; previous calls supply no history. Rejections are recorded and replay continues; a fatal event stops replay at the last good snapshot. At most 1,000 entries and 1 MiB of serialized UTF-8 JSON.
sourceYesComplete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive, closed-world behavior, yet the description adds substantial non-obvious context: exitCode 0/1/2 semantics (including that rejected events still yield 0), the warning to 'Read exitCode even when isError is false', and the fact that bridge failures use a different error schema with isError:true. That is exactly the behavior an annotations-only view would miss.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and routing come first, followed by report contents, exitCode meanings, and return/error shapes — a sensible front-loaded order with no filler sentences. It is dense, and the single packed paragraph would scan better broken into segments, but each sentence carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description must describe returns — and it does: the caveat-explain/0.1 report fields (sequence, event outcomes, decisions with grounds and revision history, evidence, displayed values, archive history), the identical structuredContent/text payload shape, and the caveat-authoring-error/0.1 error envelope for bridge failures.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents 'source' (inline Caveat text, 1 MiB limit) and 'events' (order, payload keying, 1000-entry limit) in detail. The description adds only the framing that events are optional and replayed from a fresh session; baseline 3 is appropriate when the schema carries the parameter burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Replay optional events and explain the resulting decisions, evidence and displayed values.' It also names the distinguishing scope against siblings ('choose caveat_dependents to trace one evidence or caveat name forward, and caveat_test for assertions'), so an agent can separate it from the other caveat_* tools without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use to answer why a decision was made' gives the triggering intent, and the same sentence routes to two named alternatives with the condition that selects each. When-to-use and when-to-use-something-else are both explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

caveat_testA
Read-onlyIdempotent

Run scenario assertions and runtime invariant checks against inline source, with a fresh session per scenario. Use to verify expected event outcomes and snapshot values; caveat_validate only checks loading, caveat_check reports diagnostics, and caveat_explain inspects history without assertions. report (caveat-scenario-report/0.1) includes files, per-scenario results/failures, check diagnostics and passed/failed totals. exitCode: 0 all passed; 1 scenario failure; 2 invalid scenario document (report has valid:false and error) or blocking authoring diagnostics. Every source reference must be inline.cav. Returns the same JSON in structuredContent and text: {schema:"caveat-authoring/0.1",operation,sourceSha256,runtime,exitCode,report}. Read exitCode even when isError is false. Bridge failures instead set isError:true with {schema:"caveat-authoring-error/0.1",error:{kind,message}}.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourceYesComplete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime.
scenariosYesScenario document object, not JSON text. Example: {"schema":"caveat-scenarios/0.1","source":"inline.cav","scenarios":[{"id":"initial","title":"Initial sequence","steps":[{"expect":{"/sequence":0}}]}]}. Each scenario needs a unique nonempty id, a title and nonempty steps. Every source reference, including optional per-scenario source, must be inline.cav. Each step has exactly one operation: send (event name; optional payload, rejected, repeat), expect (JSON Pointer-to-value map), checkpoint (state name), same_as (stored state name, with paths), resume:true, or size (save/snapshot byte bounds). Sends expect acceptance unless rejected specifies a policy message, true for any policy rejection, or an object with origin and optional code/message. Object expectations match listed members; arrays match in order; $exact, $set, $includes and $absent matchers are supported. Limits: 1 MiB serialized UTF-8 JSON, 32 scenarios, 2,000 total steps and 1,000 sends after repeat expansion.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare a safe read-only, idempotent, closed-world profile, and the description goes well beyond them: exitCode 0/1/2 semantics, that a valid:false report accompanies invalid documents, that exitCode must be read even when isError is false, and that bridge failures instead set isError:true with a distinct error schema. This is exactly the kind of context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and sibling routing, then output contract, then error shape. Density is high and every clause carries operational information, though the repetition of limits and step details already present in the schema makes it longer than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description fully carries the return contract: the report schema id and contents (files, per-scenario results/failures, diagnostics, passed/failed totals), the exitCode table, and the alternate error payload shape. An agent has everything needed to call it and interpret both success and failure responses.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema itself already documents inline.cav availability, the 1 MiB source cap, the scenario step operations, matchers and the 32-scenario/2,000-step/1,000-send limits. The description largely restates that same material rather than adding syntax or semantics the schema lacks, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Run scenario assertions and runtime invariant checks against inline source') plus a key behavioral scope ('fresh session per scenario'). It explicitly separates itself from caveat_validate, caveat_check and caveat_explain, so an agent can pick it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It says when to use it ('verify expected event outcomes and snapshot values') and then names each sibling with its contrasting purpose ('caveat_validate only checks loading, caveat_check reports diagnostics, caveat_explain inspects history without assertions'). Explicit when-to-use and when-not-to-use routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

caveat_validateA
Read-onlyIdempotent

Load inline source with the installed runtime and list its declarations. Start here to find load errors; use caveat_check for authoring diagnostics and caveat_test to verify expected behavior. No events are dispatched. report (caveat-validate/0.1) contains program, loads, events, reading_streams, decision_series and displayed bindings, or a load error. exitCode: 0 loaded; 2 load failure. Returns the same JSON in structuredContent and text: {schema:"caveat-authoring/0.1",operation,sourceSha256,runtime,exitCode,report}. Read exitCode even when isError is false. Bridge failures instead set isError:true with {schema:"caveat-authoring-error/0.1",error:{kind,message}}.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourceYesComplete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, closed-world), yet the description adds substantial context beyond them: 'No events are dispatched,' the report's field list, exitCode meanings (0 loaded; 2 failure), the structuredContent/text mirroring, and the caveat that isError can be false with a nonzero exitCode plus the isError:true bridge-failure shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, then routing, then return/exit semantics; every sentence carries information. It is dense and slightly enumerative (report field list, JSON shape inline), but no sentence is redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the full burden of describing returns, and it does: report contents, exitCode values, the exact response envelope shape, and the separate error envelope when isError is true. Nothing an agent needs to call and interpret this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single param (source) is fully documented in the schema, including the 1 MiB limit, inline.cav virtual-file name, and 'fresh runtime' note. The description's 'Load inline source' restates rather than extends that, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb+resource ('Load inline source ... and list its declarations') and explicitly positions itself against siblings by naming caveat_check and caveat_test with their distinct purposes. An agent can distinguish it from all named siblings without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: 'Start here to find load errors; use caveat_check for authoring diagnostics and caveat_test to verify expected behavior.' This is a when-to-use plus named alternatives, exactly the guidance an agent needs to pick the right tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.1
    • Changedcaveat_check2 fields changed
      • changedInput schema / properties / source / description
        Previous value: -"Inline Caveat source; no file or URL lookup."New value: +"Complete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime."
      • addedInput schema / properties / strict / description
        Added value: +"Optional, defaults to false. When true, any unsuppressed diagnostic makes exitCode 1 instead of 0; suppressed diagnostics do not count. Does not change program behavior. Load failures and unsupported bundles remain exitCode 2."
    • Changedcaveat_dependents6 fields changed
      • addedInput schema / properties / events / description
        Added value: +"Events replayed in array order from a fresh session. Omitted or [] inspects the initial state; previous calls supply no history. Rejections are recorded and replay continues; a fatal event stops replay at the last good snapshot. At most 1,000 entries and 1 MiB of serialized UTF-8 JSON."
      • addedInput schema / properties / events / items / description
        Added value: +"One event to dispatch to the supplied program, for example {\"event\":\"read\",\"payload\":{\"value\":85}} when source declares read with a value parameter."
      • addedInput schema / properties / events / items / properties / event / description
        Added value: +"Event name declared in source, such as read or assess. Supply the name only, without Caveat syntax."
      • addedInput schema / properties / events / items / properties / payload / description
        Added value: +"Values keyed by the event parameter names declared in source, for example {\"value\":85}. Omit for an empty payload ({}). The runtime checks parameter names, types and declared bounds."
      • changedInput schema / properties / source / description
        Previous value: -"Inline Caveat source; no file or URL lookup."New value: +"Complete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime."
      • addedInput schema / properties / subject / description
        Added value: +"Exact case-sensitive evidence name, reading stream name, caveat name, or evidence occurrence ID after replay. Evidence records supplied observations; a reading stream is a named history of samples; a caveat is a qualification on evidence. For example, probe selects its evidence/readings, values selects a stream, and values@1 selects one recorded reading. Use a name from source or caveat_explain; not a file path, claim or decision name. Unknown names return exitCode 2."
    • Changedcaveat_explain5 fields changed
      • addedInput schema / properties / events / description
        Added value: +"Events replayed in array order from a fresh session. Omitted or [] inspects the initial state; previous calls supply no history. Rejections are recorded and replay continues; a fatal event stops replay at the last good snapshot. At most 1,000 entries and 1 MiB of serialized UTF-8 JSON."
      • addedInput schema / properties / events / items / description
        Added value: +"One event to dispatch to the supplied program, for example {\"event\":\"read\",\"payload\":{\"value\":85}} when source declares read with a value parameter."
      • addedInput schema / properties / events / items / properties / event / description
        Added value: +"Event name declared in source, such as read or assess. Supply the name only, without Caveat syntax."
      • addedInput schema / properties / events / items / properties / payload / description
        Added value: +"Values keyed by the event parameter names declared in source, for example {\"value\":85}. Omit for an empty payload ({}). The runtime checks parameter names, types and declared bounds."
      • changedInput schema / properties / source / description
        Previous value: -"Inline Caveat source; no file or URL lookup."New value: +"Complete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime."
    • Changedcaveat_test2 fields changed
      • addedInput schema / properties / scenarios / description
        Added value: +"Scenario document object, not JSON text. Example: {\"schema\":\"caveat-scenarios/0.1\",\"source\":\"inline.cav\",\"scenarios\":[{\"id\":\"initial\",\"title\":\"Initial sequence\",\"steps\":[{\"expect\":{\"/sequence\":0}}]}]}. Each scenario needs a unique nonempty id, a title and nonempty steps. Every source reference, including optional per-scenario source, must be inline.cav. Each step has exactly one operation: send (event name; optional payload, rejected, repeat), expect (JSON Pointer-to-value map), checkpoint (state name), same_as (stored state name, with paths), resume:true, or size (save/snapshot byte bounds). Sends expect acceptance unless rejected specifies a policy message, true for any policy rejection, or an object with origin and optional code/message. Object expectations match listed members; arrays match in order; $exact, $set, $includes and $absent matchers are supported. Limits: 1 MiB serialized UTF-8 JSON, 32 scenarios, 2,000 total steps and 1,000 sends after repeat expansion."
      • changedInput schema / properties / source / description
        Previous value: -"Inline Caveat source; no file or URL lookup."New value: +"Complete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime."
    • Changedcaveat_validate1 field changed
      • changedInput schema / properties / source / description
        Previous value: -"Inline Caveat source; no file or URL lookup."New value: +"Complete inline Caveat program text, available as the virtual file inline.cav. No file path or URL lookup. At most 1 MiB of UTF-8 source; each call uses a fresh runtime."
  2. 5 tool updatesv0.1.0
    • First observedcaveat_check
    • First observedcaveat_dependents
    • First observedcaveat_explain
    • First observedcaveat_test
    • First observedcaveat_validate

TDQS

A4.6/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct authoring phase: caveat_validate for loading/declarations, caveat_check for static diagnostics, caveat_test for scenario assertions, caveat_explain for decision replay, and caveat_dependents for lineage impact on a single subject. Descriptions explicitly cross-reference each other with 'choose X instead' guidance, leaving essentially no overlap.

Naming Consistency4/5

All names share the caveat_ prefix and a predictable snake_case style, which is easy to scan. The only deviation is caveat_dependents, a noun rather than the verb form used by validate/test/check/explain.

Tool Count5/5

Five tools is well-scoped for a language authoring/inspection server, with each tool occupying a distinct step in the authoring lifecycle. Nothing feels padded or redundant.

Completeness4/5

The surface covers the full authoring loop: load, diagnose, test behaviors, explain decisions, and trace dependencies. Minor gaps exist for auxiliary operations like formatting source, listing runtime/version info, or scaffolding new programs, but no core workflow is a dead end.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    A local, evidence-driven MCP runtime and control plane for open-source maintainers that provides workspace-bounded tools including controlled file operations, command execution, validation primitives, durable execution records, and human review workflows via stdio and Streamable HTTP transports.
    33
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Coordination protocol for parallel coding agents, built above Git. The MCP server exposes the full 17-tool lifecycle over stdio: register agents, publish intents with semantic scopes and declared operations, claim work, check for conflicts before code is written, publish ChangeSets, run trusted named verification checks, and record accepted work. Deterministic rules raise findings when two agents'
    18
    538
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides a local stdio MCP server that gives AI coding agents a typed, temporal, evidence-backed memory on embedded SQLite, letting them record decisions and constraints, ask why something happened, navigate memory by time, trace proof paths between refs, and export or supersede stored state without rewriting it. It also exposes read-only ChronoLoom view tools so a person and their agent can steer the same multidimensional memory view by semantic intent rather than raw coordinates.
    Apache 2.0