RISE Framework Specification References: Spec 70 (SMDF), Spec 80 (ERDF), Spec 81 (SQDF), Spec 73 (MCP Server), Spec 74 (Web Designer), Spec 76 (RISE rispec generator), Spec 77 (Real-Time Design Bridge)
Spec ID: 82
Version: 1.0
Status: landed — protocol 0.1.9, hub 0.1.5 (the view relay), client 0.1.3 (emitView), mcp 0.3.0 (10 system tools, generate_rispec from a system), web 0.2.0 (the system map and strip, the chronicle rule), skills 0.4.0 (stateloom-system)
Implementation: TypeScript — bridge-protocol/src/system/, bridge/src/hub.ts (view relay), bridge-client/src/client.ts (emitView, on('view')), mcp/src/system.ts, web/src/components/system/
Origin: Guillaume in the Episode 121 circle, 2026-09-24: “I agree that the 3 diagrams (and potentially more) describe one system”. Decisions D1–D9 and requirement N1 of the Stateloom Systems proposal page, 2026-09-30.
What SYSDF Enables Users to Create: One system out of the drawings of one thing being built: its data, its behaviours and its scenarios, checked against each other, walked by the scenarios, and kept level by them — so a person can move between the drawings and follow one element across them, an agent can design by telling a story, and the chronicle, the medicine wheel and RISE have one address to hold.
Desired Outcomes:
.sysdf.json names its members and the actors its scenarios shareautoshowGuillaume, 2026-10-01, after the first release, watching a trading session where counting waves “doesn’t work” and he wanted to talk it through with his agent:
“I think what we built is going to be what that agent needs to have a discussion with me, giving me good representations and design and do the work that he has to do. And I’m thinking that what we created is exactly for this type of session that I’m never capable of actually fully complete and bring to completion, or at least leave a system and a set of diagrams and things for future instances, which is going to be really good information regarding why we’re creating what we’re creating here.”
Two uses follow, and they shape the format:
show.settings.notes and each drawing’s notes — the question that started it and what was decided. The next instance opens the system and its notes before it designs anything.What a design input carries, when it is good. Guillaume’s prompt to that session named, in his own words, every part the loom holds — and he said why: “the quality of my prompt is because I know that we will have the tool to actually represent that in adequate diagramming.” Read as a teaching for anyone giving a design input to a model:
| what his prompt said | what the loom holds it in |
|---|---|
| “I’m counting waves and it doesn’t work” — where he is | the current state of the existing machine (ElliottWaveCountLifecycle) |
| “give it a name of that new state machine” | a new member machine (AnalysisDiscussion) |
| “describing the event that leads us toward there” | the entering event (AskToDiscuss) |
| “what’s going to be the actual scenario, the sequence” | a .sqdf.json, each message naming its event and the state that follows |
| “prompting that correspond to what we want to resolve in that state” | the state’s prompt (set_prompt) |
| “the events that are going to be possible to transition back to existing states, or new other states” | alt fragments firing the existing machine’s own events, checked by the replay |
| “requirements for implementing it ourselves or delegating” | the system rispec, and the notes a session leaves |
An input that names these seven things can be drawn, checked and handed on; one that leaves any of them out leaves the model to guess it.
Measured on 2026-10-01 against that session’s prompt (a new “discussion” state reached from a button beside Publish): starting from an empty machine and the scenario alone, reconcileSystem in auto mode built the new machine’s five states and their transitions, added the two entities to the ERD and the agent to the actors, and the replay then named a real design question — the “trade it” outcome asks for a blueprint before the count is evaluated, which the existing lifecycle refuses.
{
"settings": { "namespace": "jgt.trading", "name": "ElliottWaveCount", "description": "...", "notes": "...", "reconcile": "propose" },
"members": [ { "path": "elliott_wave_count.erdf.json" }, { "path": "elliott_wave_count.smdf.json" }, { "path": "wave_count_to_entry.sqdf.json" } ],
"actors": [ { "name": "Guillaume", "kind": "person" }, { "name": "Agent", "kind": "agent" } ]
}
resolveMemberPath, relativeMemberPath), so a system moves as one folder..erdf.json, .smdf.json, .sqdf.json. A system is never a member of another. The list is open to later kinds (a structural tension chart, a PDE, a rispec).person, agent, service, external, with an optional wheelNode (the medicine-wheel node the actor is).docKindOfPath(path) → machine |
erd |
sequence |
system, by extension; any other .json is a machine, as it always was. docKindOfContent(doc) answers from content. |
checkSystem(system, members)| Rule | Description | Severity |
|---|---|---|
| Y001 | The system has settings.name and settings.namespace |
error |
| Y002 | Member paths are present, unique, and of a member kind | error |
| Y003 | A member can be read, and holds what its extension says | error |
| Y004 | Actor names are unique and their kinds known | error |
| Y005 | No two member machines share a settings.name (a message names a machine by it) |
error |
| E, S | Each ERD’s and each sequence’s own rules | error |
| L001–L004 | Spec 80’s links, for every machine against the entities of every ERD | error |
| L005 | A message’s event is an event of a member machine (of machine, when named) |
error |
| L006 | A participant’s actor is an actor of the system, its object a machine object, its holds entities |
error |
| L007 | A message’s carries is an entity |
error |
| L008 | Each path of each scenario is a walk the machines accept; a state names a state some machine has |
warning |
| L009 | A state that is not final has a way out (a transition on it or on a state around it) | warning |
A machine’s own V rules live with the engine; the MCP adds them to check_system. L008 is a warning because a scenario ahead of its machines is how new behaviour is designed. Only the first stop of each machine on each path is reported; the stops after it are counted, since they are usually its consequence.
replayScenario(sequence, machines)A sequence and a state machine tell the same story two ways. The replay reads the messages in order and, for each message that fires an event, follows the transition that event takes in every member machine defining it (only in message.machine when named) — a machine that does not define an event does not hear it.
It follows the runtime’s rules (ts/src/machine.ts): start in the first enterable leaf of the root; look an event up on the current leaf, then each ancestor; a transition without nextState stays; entering a composite enters its first non-history child down to a leaf; entering a final state ends the machine.
Guards cannot be evaluated outside generated code, so the walk keeps the set of states the machine may be in. A guarded transition may or may not be taken; an unguarded one always is and ends the search, as at runtime. A message is the scenario’s claim that its event is handled, so states that refuse it are dropped when others accept it, and message.state narrows the set the same way — reported as state-mismatch when the machine cannot be there.
Paths: main; main without optional messages when any message is optional; one per fragment — an alt is the main messages up to its branch point followed by its own, an opt inserts its messages, a loop inserts them twice. Parallel regions are not walked.
Each step reports moved, stayed, refused, unknown-event, ended, state-mismatch or data, with the states before and after and the guards assumed.
reconcileScenario(sequence, machines) replays and, where the scenario itself says how, proposes the machine edit as PatchOps — the vocabulary the hub already carries, so an applied proposal reaches a live canvas as an ordinary patch:
<Sender>Events, a source named after the sender, or one it feeds), created when missing.state on the message → add that transition on the state the machine is in, adding the state under the root first when missing.reconcileSystem(system, members) does this for every scenario of the system and adds what a scenario names outside the machines: entities that messages carry or participants hold (to the ERD, with a note saying which message asked), actors a participant names (to the system), a participant’s object when one machine and one held entity say which, and an object of an entity whose attribute’s stateOf names a machine that has none (Episode 550, L2).
Everything else is returned as unresolved, in words: a refusal without a state, a state that contradicts the walk, a machine that already ended, a refusal from several possible states, a stop on the path without optional messages (a claim about the scenario, not a machine gap), a state that belongs to another machine when the message does not name its machine, a machine name two members share, a state inside a parallel region, and a change that was proposed and did not let the walk through (never proposed twice). An empty machine gains its first state rather than a transition on its root. Nothing is removed or rewritten. summarizeReconcile gives the one line a tool or the strip shows.
settings.reconcileGuillaume, 2026-09-30: “you need not to bore the user with a bunch of things he needs to approve and validate … a modality.”
| Mode | When a scenario is saved |
|---|---|
propose (default) |
The changes are listed with their reasons and wait for someone to apply them |
auto |
The changes are applied at once — machines written and patched to their rooms, ERDs written and sent whole, the system written — and one line says what changed |
The mode is a design choice of the people working on the system, so it lives in the system document. reconcileModeOf(def, override) lets a session override it (STATELOOM_RECONCILE).
systemLinks(members)The same crossings, kept where both ends exist, as {from, to, rule, text, back} between element references {member, kind, name} — entity, attribute, machine, object, event, state, participant, message. The replay’s main path adds message → state for each message that moves a machine. linksOf(links, member, focus) gives the links touching one element, read from its side. A focus is <kind>:<name> (entity:WaveCount, message:f1.2).
view:showViewEnvelope { docId, member?, focus?, origin, note? }. The hub relays it to the room named by docId — the system file’s — and keeps nothing: no seq, no ring, no disk. The sender need not have joined that room; the token is checked as on join. @miadi/stateloom-client sends it with emitView and receives it with on('view'). The MCP’s show tool is how an agent points the canvas at a member and an element while it talks.
create_system, add_member, remove_member, add_actor, remove_actor, set_reconcile_mode, check_system, replay_scenario, reconcile_scenario (dry run by default, apply: true writes), show. generate_rispec from a system writes one rispec: data from the ERDs, behaviour per machine, and each scenario path as a Creative Advancement Scenario whose Resolution is the replay’s end state; L008 findings and unresolved items close it as open questions.
web/ opens a .sysdf.json as the system map: a card per member with its counts, lines between members labelled with how many names cross, the actors, the checks with the replay per path, and the reconcile mode with the proposed changes. With system= in the URL, every workspace shows a one-row system strip: the system name, a tab per member (drawn outline icons), and the links of the focused element, each opening the other member on that element. The strip listens on the system’s room and follows an agent’s show. Each workspace reads focus on load and writes it on selection.
A chronicle root (STATELOOM_CHRONICLE_ROOT) admits only <root>/<episode>/diagrams/<file>.json (D2) — no other path under the chronicle.
systemLinks already carries what such a board would draw.Desired Outcome: Episode 140’s data, lifecycle and scenario open as one system
Current Reality: Three files beside each other, grouped only by their folder; the scenario was a picture
Natural Progression: create_system names the three; check_system finds no error and two warnings — without its optional message 7 the scenario stops at message 9, and the alternative that begins after message 11 is refused from StrategicEntry
Resolution: examples/wave-count/elliott_wave_count.sysdf.json, whose findings are the two the proposal page named by reading the files by hand
Desired Outcome: The next instance continues the design from what the last one built, and knows why
Current Reality: A session ends mid-discussion; what it understood lives in a transcript nobody rereads, and the next instance starts over from the person’s memory
Natural Progression: As the discussion goes, the agent keeps a .sysdf.json beside the work: the scenario as told, the machines reconcile builds from it, notes on the system with the question that started it and what was decided; before stopping it runs check_system and leaves the warnings as they are
Resolution: The next instance opens the system, reads its notes, and sees on the map where the walk still stops — the open work, in the shape of the thing being built
Desired Outcome: A new behaviour lands in the machine without a person approving each step
Current Reality: A scenario and a machine drift apart the moment one of them changes
Natural Progression: The system’s mode is auto; the agent adds a message with a new event, the state it leads to and an entity it carries; the tool applies the new event, state, transition and entity, patches the open canvases, and answers in one line
Resolution: The person opens the lifecycle and finds the new transition already drawn