Resolving Decides

The dinner mesh from the previous chapter contains one declaration the equilibrium engine will never touch on its own:

decide venue(dinner) among { verde, banh-mi-house } by 18:00

This chapter is about what happens when you run the mesh without answering that question, and about the one flag that exists for answering it.

Machines do not choose venues

Run the dinner mesh with no resolution:

$ python3 -m osmol dinner.osmol
OSMOL v0.1 - reference interpreter
parsed dinner.osmol: 2 twins, 0 sends (no such construct exists)
initial gapcount: 3   (Theorem 1 bound: equilibrium in <= 3 flows)
  human-lane  maya -> raj  (verbatim, provenance=human): "Saw a fox on the way home and thought of you."
t1  maya.eta(dinner) --exact--> raj   P=1.30 (R1.0*U1.3*T1.0*M1.0) > theta[family]=0.3   [silent]
t2  maya.status(atlas.review) --category--> raj   P=0.65 (R1.0*U1.3*T1.0*M0.5) > theta[family]=0.3   [silent]

EQUILIBRIUM after 2 flows (Theorem 1 bound 3: respected)
messages composed by humans: 0 (the grammar has no verb for it)
interruptions: 0
open gap [maya]: venue(dinner)
awaiting human judgment [raj]: venue(dinner) among ['verde', 'banh-mi-house']  (machines do not choose venues)

Everything that could settle, settled: raj's twin absorbed maya's ETA and the review status, two flows, both silent. But only two of the three gaps closed. Maya's seek venue(dinner) by 18:00 else escalate stays open, its escalation policy still armed, because the only possible supply for it is raj's decide, and the engine reached equilibrium around it. The final line is the interpreter refusing, in so many words:

awaiting human judgment [raj]: venue(dinner) among ['verde', 'banh-mi-house']  (machines do not choose venues)

This is not a stuck state. It is an equilibrium that happens to contain an open question addressed to a person.

The --resolve flag

A resolution is an injected human judgment. The syntax is twin:fact=value, and the flag is repeatable, one per pending decision:

$ python3 -m osmol dinner.osmol --resolve "raj:venue(dinner)=verde"
$ python3 -m osmol mesh.osmol --resolve "raj:venue(dinner)=verde" --resolve "maya:decision(atlas.budget)=approve"

Resolutions are applied before settling begins. The first thing settle() in osmol.py does is walk the --resolve list. For each one, it deletes the pending decide and emits the corresponding assertion: hold venue(dinner) = verde appears on raj's twin, and the trace records it as an input, not a flow:

  [human judgment] raj resolves venue(dinner) = verde

From that point the engine treats the new hold like any other supply. Maya's waiting seek venue(dinner) now has a matching holder; raj's membrane rule venue(*) -> family: exact grants it; the flow fires and lands on maya's ledger (her seek said else escalate). Run it and the mesh settles fully: three flows, then open gaps: 0 — silence is a fixpoint. The full resolved trace is walked line by line in Reading the Trace.

Notice the shape of this: the human did not compose a message announcing the venue. The human answered a question their own twin was holding open, and the mesh did the telling.

Guard rails

A resolution must name one of the declared options of the decision. The options are the contract. decide enumerates the acceptable answers at declaration time, and the interpreter enforces this:

$ python3 -m osmol dinner.osmol --resolve "raj:venue(dinner)=sushi-bar"
OSMOL v0.1 - reference interpreter
parsed dinner.osmol: 2 twins, 0 sends (no such construct exists)
osmol: resolution 'sushi-bar' not among options for venue(dinner)

A resolution naming a fact with no pending decide on that twin is simply ignored: there is no decision to resolve, so nothing happens. (Stricter behavior here is a reasonable thing for a future implementation to propose; see the RFC process.)

Why this is permanent

It would be a few lines of Python to make the engine pick the first option, or the highest-scoring one, or the one a language model likes. Those lines will never be written, in this or any implementation.

The engineering dissertation states it as a runtime-contract clause: human judgment is an input type, not a solver capability. decide blocks resolve only through an injected resolution, in every habitat (CLI, browser, edge, phone), always. The refusal of the interpreter to pick the restaurant is not a v0.1 limitation waiting for a smarter solver; it is a feature of the contract, exactly as load-bearing as the absence of send.

The reasoning runs straight back to the Seven Laws. Law IV reserves judgment, trust, and warmth for humans; the job of the mesh is to move logistics out of their way. A system that chooses on your behalf has not saved you a decision; it has taken one. So the boundary is drawn in the way this grammar prefers: not as a configuration option or a permission, but as an impossibility. The solver has no rule that touches a decide. Equilibrium is defined around open decisions, and the trace prints them as what they are: questions, waiting for the only kind of participant entitled to answer them.

For the full syntax and semantics of the construct (deadlines, option lists, and how a resolved decision becomes an assertion), see decide.