Caveat Lang

io.github.WSattazahnv0.1.0-rc.14更新于 Oct 5, 2026

Authoring bridge for Caveat: validate, check and test programs; explain decisions; find dependents.

已验证STDIO仅桌面AI & MLDeveloper Tools

概览

AI 生成的概览

让助手校验、测试并解释 Caveat 语言程序,并追踪哪些决策依赖哪些证据。

功能
这是 Caveat 语言的编写辅助工具。Caveat 运行时会把证据与保留条件随计算值一起保存,并记录决策的依据以及重新开启的原因。通过本地命令行,它可以校验和检查程序、运行场景测试、解释某个决策的依据,并查找某个值的依赖方。它还能以 JSON 输出程序接口,并据此生成 TypeScript 声明。
适用场景
当助手正在编写或审查 Caveat 程序,需要检查程序、运行其场景测试,或解释某个决策为何被作出或重新开启时,适合使用。它也适合追踪哪些值和决策依赖某条证据。
运行要求
以 npm 包 caveat-lang 的形式通过 stdio 在本地运行,用 npx 启动。需要 Node.js 20 或更高版本;使用已发布的预览版无需安装 Rust。未声明任何认证、环境变量或请求头。
安装前请注意
项目说明指出:Caveat 记录所提供的证据和编写的策略,但不验证证据,也不授权外部操作;恢复存档不会验证其历史。引用检查只能说明被引用的依赖已被记录,不能说明证据或解释为真或完整。被拒绝的操作不会完成,宿主必须检查其结果。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Caveat Lang,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

CAVEAT Language

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

npm publication verified 2026-10-05T02:17:29.240Z: exact [email protected], tested Linux artifact SHA256 9aab7b811666e5b43b6f7c96ad5116235241b08fbed395698476cc035bfd57bf. latest and next name rc.14. Published by publish-npm.yml from tag v0.1.0-rc.14 with an npm provenance attestation. Publication record.

Development for 0.1.0-rc.15 is open and unpublished. See the rc.15 development scope for acceptance criteria and verification status.

Programs that remember why.

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.14, in an empty directory with Node 20 or later. No Rust installation is needed:

sh
npm init -ynpm install [email protected]npx --no-install caveat-lang initnpx --no-install caveat-lang test umbrella.scenarios.jsonnpx --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.14 verified publication record identifies the published npm candidate. The rc.14 GitHub prerelease retains the exact tested Linux tarball and its checksum. rc.14 changes only the package's MCP server name, so the MCP Registry lists it as io.github.WSattazahn/caveat-lang; the language is rc.13's. rc.13 reports a program's interface as JSON and writes TypeScript declarations from it (caveat-lang types), makes restore refuse a caveat the source cannot attach and a membership without its record, and turns id_text of a non-handle into a refused event instead of a fatal failure. Restoring a save still does not authenticate its history. A refused operation is not completed; hosts must inspect its outcome. It adds no npm runtime dependency.

With rc.14 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.

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.

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.

CaveatIn a general-purpose language
Explanationsbind 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 computationqualified(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 caveatsqualify 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 remembercommit, 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 lineageThe 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 eventsreject "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.
RoundChange cost, Caveat vs TypeScriptResult
1 · first version55 vs 57 (CR1–4)Parity. The weak spots became the language's work list.
3 · blind requests97 vs 53 (CR5–8)TypeScript. Caveat's lineage fought the designer's meaning.
5 · replay after language changes71 vs 110 (CR1–8)Caveat, with 134 lines against 164. Written knowing the requests.
6 · blind requests92 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 changes88 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.11186 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

caveat
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.

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.

caveat
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:

caveat
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:

sh
cargo install wasm-bindgen-cli --version 0.2.104 --lockednpm cinpm run buildnpm 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:

sh
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

sh
cargo test --manifest-path runtime/Cargo.tomlcargo clippy --manifest-path runtime/Cargo.toml --all-targets -- -D warningsnpx playwright install chromiumnpm run test:beaconnpm run test:rescuenpm 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]

来源:README.md,提交 e539223

工具

0
工具元数据尚未被收录。

版本历史

1
  1. v0.1.0-rc.14最新Oct 5, 2026