7 Upgrading
Breaking changes between Stone versions, collected in one place and kept out of the rest of the manual — every other page describes only what Stone does now. If you are starting fresh, skip this section.
7.1 Unreleased
On the development branch, not in any tag yet. These land in the next release cut.
An agent’s conversation is a DAG of 'turn nodes. The flat embedded 'conversation list, context-node-draft, and extract-final-result are removed. Read an agent’s result through the value node it produces — (node-text result) for either-shape tolerance, (node-get result 'text) for the raw draft. The turns behind it are reachable through node-conversation in stone/turn-node, which has no reference entry yet.
DAG vocabulary. dag-heads becomes dag-leaves (the childless node ids that new nodes attach to), and the read/replay position dag-head-id / dag-current-head / dag-set-current-head becomes dag-cursor-id / dag-cursor / dag-set-cursor. No aliases. Ashlar bodies that build through typed-node name neither.
The LLM-call layer is the call-* cluster. Four bindings in stone/llm-client are renamed, with no deprecated aliases. Read the first row carefully: call-llm was the old name of the Anthropic entry point, and is not a binding at all today.
Was
Is now
call-llm
call-llm-openai
make-anthropic-caller
make-openai-caller
make-openai-llm and make-anthropic-llm are the two names you actually write in main.rkt; call-openai and call-anthropic are the raw per-provider calls beneath them.
The same rename reaches .stone/settings.rkt: the binding it may provide to supply a configured LLM call is now named call-llm (it was caller). That settings key and the removed stone/llm-client binding share a spelling and are unrelated — the key names a value your settings module provides, not a procedure Stone exports.
A fired tool is a threshold crossing, not a log event. The stone-event 'tool-dispatch log event is replaced by the 'tool crossing (The threshold crossing bus) — subscribe to the threshold rather than reading the logger. Its payload keys are 'tool, 'input, 'result-text, and 'result-meta. A denied or refused dispatch never executes, so it never crosses.
The turn-completed journal fact is removed. Turn-nodes journal per turn as node-appended facts, so a separate completion fact carried nothing new; the session label and the TUI’s scrollback derive from the turn-nodes.
7.2 v0.2 to v0.3
#:context replaces #:system, #:user, and #:queries. make-agent-ashlar takes one context value (stone/context-struct) where it previously took those three keywords separately:
(context (system "...") (history 'earlier-type) (user 'latest-type))
The ashlar’s read-set, which the validator checks before any LLM call, is derived from the context’s elements — there is no separate declaration left to drift from what is actually read.
The threshold replaces the outbox and the ask-human channels. stone/outbox.rkt and the channel apparatus around it are removed: ask-human-channel and its accessors, make-ask-human-channel, call-with-collected-ask-human-channels, the #:ask-channels keyword on run-tui, and channel-born-event. In their place, a run binds one threshold and everything crossing outward goes through it:
make-ask-human loses its leading positional channels argument — it is now keywords only (#:format-fn, #:name, #:produces, #:queries) and solicits through whatever threshold the run bound.
A frontend calls threshold-subscribe to observe, instead of collecting channels.
run-tui takes #:record and #:threshold.
make-agent-ashlar no longer takes #:outbox or #:threshold. The agent emits to current-threshold, which the run verb binds — symmetric with the journal. Passing either keyword is an unknown-keyword error.
build-agent in .stone/settings.rkt is a zero-argument thunk. It briefly took one argument, the run’s threshold; that contract is gone with the #:threshold construction keyword above. Drop the parameter — the agent reads current-threshold itself.