The Engine Decides
Two checks that never asked the world
Nine plans came through the last chapter's two checks, and one of them walked a woman into a pond. The checks were right to pass it. A walk to a cell is the shape that was asked for and a verb that is in the table, and that is everything the shape check and the verb check are allowed to know: the plan, the table and two numbers out of a file. What stopped her was the check every animal pays inside its own tick, which refused the walks one at a time, wrote each refusal into the roster's report, and never learned that any of them came from a plan. The same two checks would have passed a watch of a body the watcher could not see, a hand of a thousand grams from a woman carrying a hundred, and a line spoken to somebody who had died while the answer was on its way back. None of those is wrong on the table. All of them are wrong in the world, and the world was not asked.
Asking it is not one question. A plan can name a body the villager was never told about, which is a fact about what the villager knew when it was asked and nothing else. It can name a body that is out of reach, a cell that is open water, or more grams than the actor holds, which are facts about the world as it stands. And it can be an answer to a question asked seconds ago: a call to the small model takes seconds, the world runs at ten ticks a second, and the first chapter of this volume measured what that costs. Every decision a villager makes is a decision about a world that has already moved on. That is the design and not a defect of it, and it is safe only if something asks, at the moment the answer lands and again at the moment each step is carried out, whether the world is still the one the villager was told about. The engine decides: six checks in one order, each a function of the proposal, the grounding set, the law and a reading of the world, run over the whole plan when it arrives and over each step when it is due, and a refusal is a ledger row and never a repair.
Four checks join the two, in a fixed order that runs cheapest first and puts the two that need the world last: grounding, against the set of identities stored on the ledger row; law, against whatever law the check is handed, which on this page has no clauses in it; reach, which is the world's own rule asked through the same function every animal's tick calls; and freshness, which reads the clock and the roster. The four are pure functions in the same package as the first two, and the world reaches them as a value the caller builds at a tick boundary. A plan is validated whole when the answer lands, and each step is validated again when it comes due. A plan that fails is refused whole, its refusal is a row in the ledger, the villager runs the habit, and nothing about the refusal is written into the villager's memory.
Every verdict below is computed over the last chapter's recording, by the code on this page, and compared byte for byte; the three runs against the live models are labelled where their text appears. The model chooses and it never counts, which on this page means one thing in particular: a grams argument a model wrote is what it asked for, and whether the actor holds that many is the fifth check's question, not the model's.
Grounding against the set on the row
The third check reads one column of the ledger row. When a prompt is rendered, the retrieval chapter computes the identities the villager may name, from the memories that came to mind, the bodies its eyes returned, and itself, and the last chapter stored that set beside the answer. The check asks whether every body a step names is in it. It does not recompute the set, because what the villager could know at the moment of asking is a fact about that moment, and a set computed later would be a fact about a later one: the third check and the sixth are two clocks, and the row holds the first of them still.
// internal/law/seam.go — a new file in the package the last chapter opened
// Proposal is a plan with the three facts the checks need beside it:
// the tick it was asked at, the grounding set stored with it, and the
// law profile the villager answers to. The set is the one the prompt
// was rendered from and is stored on the ledger row, so the third
// check asks what the villager could know when it was asked and never
// what it could know now.
type Proposal struct {
Plan Plan
Asked int
Set []sim.EntityID
Profile string
}
// Terms is what a proposal is judged under besides the world: the two
// caps a plan is measured against on arrival, the law the fourth
// check asks, and how many ticks old a proposal may be before the
// sixth check refuses it. Every number is read out of configs/ by
// whoever drives a villager; the law is whatever that driver was
// handed.
type Terms struct {
Caps Caps
Law Law
Stale int
}
// GroundingOf is the third check: every body a step names is in the
// grounding set stored with the proposal, which is what this villager
// could know when it was asked. A cell is not an identity and is not
// asked about here; whether a cell can be stood on is the world's
// question and the fifth check's.
func GroundingOf(p Plan, set []sim.EntityID) Verdict {
known := map[sim.EntityID]bool{}
for _, id := range set {
known[id] = true
}
for i, s := range p.Steps {
if s.Who != 0 && !known[s.Who] {
return Refused(OnGrounding, fmt.Sprintf("step %d names body %d, and the grounding set is %s", i+1, s.Who, setOf(set)))
}
}
return Accepted()
}
Three facts ride beside a plan and none of them is the model's: the tick the question
was asked at, the set the prompt was rendered from, and the name of the law profile the
villager's row carries. The terms are the operator's: the two caps from the last
chapter, a law, and a staleness cap in ticks that the sixth check reads. A cell is
not an identity and the grounding check does not look at one. A walk to
2,7 names nobody, so an empty set passes it; whether anybody can stand on
2,7 is the world's question and is asked two checks later. The refusal
prints the step, the body and the set, in the ledger's own braces, so that a person
reading the row can see what the villager was allowed to say and what it said instead.
The fourth check is a question put to a law, and the law is an interface with one method: may this profile propose this step, and if not, which clause said so. What a law is made of is not this file's business. The one this page hands the check has no clauses in it, permits everything, and names nothing, which is exactly the state of the world's law at this point in the volume: the check exists, it is asked on every plan, its answer goes into the ledger under its own name, and the file that fills a law is not this chapter's. What the check refuses to do is run without a law at all. A nil where a law should be refuses every step, because a driver that forgot to load one should get a ledger full of refusals and not a village that does whatever it likes.
// internal/law/seam.go — below the third check
// Law is what the fourth check asks: whether a law profile may propose
// one step. The answer names the clause that decided when there is
// one, so a refusal can say which line of the law it was, and an
// empty answer means no clause spoke. What a law is made of is not
// this file's business; this file only asks.
type Law interface {
Permits(profile string, s Step) (clause string, ok bool)
}
// Lawless is the law with no clauses in it. It permits every step and
// names no clause. It is what the fourth check is handed on this page,
// and it is a value and not a nil: a check handed no law at all
// refuses everything, so that a driver that forgot to load one cannot
// pass a plan by accident.
type Lawless struct{}
// Permits says yes to everything, naming nothing.
func (Lawless) Permits(string, Step) (string, bool) { return "", true }
// LawOf is the fourth check: every step is one the profile's law
// permits, asked step by step in order, and the first clause that
// says no is the reason.
func LawOf(p Plan, profile string, l Law) Verdict {
if l == nil {
return Refused(OnLaw, "no law was handed to the check, and no law permits nothing")
}
for i, s := range p.Steps {
if clause, ok := l.Permits(profile, s); !ok {
return Refused(OnLaw, fmt.Sprintf("step %d: %s", i+1, clause))
}
}
return Accepted()
}
The clause comes back as a string because a refusal's reason is a string, and the
ledger's reason column is where a person will read it. A test further
down hands the check a one-clause law written for the test, watches the step refused
with the clause named, hands it the empty law and watches everything pass, and hands
it nothing and watches everything refused. That is the whole of what this page can say
about the fourth check, and it is enough to hold a place in the order: a law that is
asked after grounding and before the world is a law that can assume every body named is
one the villager knew, and can leave whether the body is in reach to the check after
it.
The Reading type
The last two checks need the world, and the package that runs them is sealed against
the store and the model client by a test with a floor. It is not sealed against the
simulation, and the question this section settles is how much of the simulation it may
see. The answer is one type and one import. The type is a Reading: the tick,
the actor's body and the view it stands in, the identities its eyes returned at that
boundary, and every living body with its cell and its grams, built by whoever drives the
villager from the roster, at a tick boundary, and kept for one verdict. The import is
internal/beast, for one reason: the fifth check is the same check an animal
pays, called through the same function, and that function is a method on a body. A reading built entirely of values could carry a cell and a number, but it could
not carry the call. So the law imports the package the rule lives in, and a test further
down reads the import lines to hold it at that package and the coordinate package and
nothing else: no ground, no village, no configs, no fixture.
// internal/law/seam.go — below the fourth check
// Body is one living body as a reading found it: the cell it stands
// on and the grams it is carrying. Two numbers and a cell, because
// those are the whole of what the last two checks ask about anybody
// but the actor.
type Body struct {
Cell sim.Coord
Grams float64
}
// Reading is what the checks need of the world, taken at one tick
// boundary by whoever drives a villager: the tick; the actor's own
// body and the view it stands in, so that the fifth check can ask the
// world's own rule through the same method every animal pays; who the
// actor's eyes returned at that boundary; and every living body, with
// its cell and its grams.
//
// The actor and the view are the roster's own and not copies, and
// that is allowed because a reading is taken between two ticks, at
// the one place where no phase is part way through. Nothing here is
// kept past the verdict.
type Reading struct {
Tick int
Actor *beast.Beast
View *beast.View
Sees []sim.EntityID
Bodies map[sim.EntityID]Body
}
// Next is the action a step asks the world for first, worked out
// against the actor as it stands: a walk turns toward its cell and
// then walks, a watch turns toward its body and then stands, a hand
// or a take is the table's own entry, and a wait or a line is a rest.
// It is what the fifth check puts to the world's rule, and it is what
// a dispatcher posts, so the world is asked about the action it is
// about to be given and no other.
func Next(s Step, r Reading) beast.Act {
b := r.Actor
switch s.Verb {
case Go:
if s.Where == nil || b.Cell() == *s.Where {
return beast.Rest
}
if a, turning := Turn(b, *s.Where); turning {
return a
}
return beast.Walk
case Watch:
if o, ok := r.Bodies[s.Who]; ok {
if a, turning := Turn(b, o.Cell); turning {
return a
}
}
return beast.Rest
case Hand:
return beast.Hand
case Take:
return beast.Take
}
return beast.Rest
}
The actor and the view are the roster's own pointers, and the package comment says why
that is allowed: a reading is taken between two ticks, at the one place in the daemon
where no phase is part way through and no creature is half stepped, which is where
every boundary job in this book has run since the seventh volume. Nothing keeps a
reading past the verdict it was built for. Next is the last chapter's
steering, moved into the law and given a reason to be there. A step of go
asks the world for one action on this tick, a turn toward its cell or a walk, and
that is the action the fifth check puts to the world's rule; a dispatcher that posts
the same function's answer is posting the action the world was asked about and no
other. Turn, below it in the file, is the last chapter's face
moved and renamed.
Now the fifth check. It asks three things of one step, in the order they can be asked.
Is the target where the action needs it: a cell that is ground on the grid for a walk, a
body in sight for a watch, a body inside Reach for a hand, a take or a line.
Are the grams named grams the giving end holds, which for a hand is the actor and for a
take is the body named. And does the world allow the action the step asks for first,
which is asked through Legal, the call every animal's tick makes:
Rule underneath, which puts the price to the store and then the entry's own
test to the world, with the sentence the log wants wrapped around the answer. The
sentence is the point. A villager refused by reach gets the same words an animal gets
in the roster's report, and the run that shows them side by side is further down.
// internal/law/seam.go — below Turn
// ReachOf is the fifth check, on one step: the world's own rules. The
// target is where the action needs it: a cell that is ground on the
// grid for a walk, a body in sight for a watch, a body inside Reach
// for a hand, a take or a line; the grams named are grams the giving
// end holds; and the action the step asks for first is one the world
// allows, asked through Legal, which is the call every animal's tick
// makes: Rule, which puts the price to the store and then the entry's
// own test to the world, with the sentence the log wants around it.
//
// placed is whether the actor is where this step finds it. It is true
// for the step the world is about to be asked for and false for the
// steps after it on arrival, because where the actor stands when a
// later step comes due is where the earlier steps will have put it,
// and the check does not walk the plan to find out. A step that is
// not placed is asked only what does not depend on where the actor
// stands: that its cell is ground and that its grams are held.
func ReachOf(n int, s Step, r Reading, placed bool) Verdict {
b := r.Actor
no := func(why string) Verdict { return Refused(OnReach, fmt.Sprintf("step %d: %s", n, why)) }
switch s.Verb {
case Go:
if s.Where == nil {
return no("a walk to nowhere")
}
bed := r.View.Valley.Bed
switch {
case !bed.In(*s.Where):
return no(fmt.Sprintf("%d,%d is off the grid", s.Where.X, s.Where.Y))
case bed.Kind(*s.Where) == sim.Water:
return no(fmt.Sprintf("%d,%d is open water", s.Where.X, s.Where.Y))
}
case Hand:
if held := b.Carrying(); held < s.Grams {
return no(fmt.Sprintf("%g grams named, and the actor holds %.4f", s.Grams, held))
}
case Take:
o, alive := r.Bodies[s.Who]
if alive && o.Grams < s.Grams {
return no(fmt.Sprintf("%g grams named, and body %d holds %.4f", s.Grams, s.Who, o.Grams))
}
}
if !placed {
return Accepted()
}
switch s.Verb {
case Watch:
seen := false
for _, id := range r.Sees {
seen = seen || id == s.Who
}
if !seen {
return no(fmt.Sprintf("body %d is not in sight", s.Who))
}
case Hand, Take, Say:
o, alive := r.Bodies[s.Who]
if !alive || !Within(b.Cell(), o.Cell, int(b.Kind.Reach)) {
return no(fmt.Sprintf("body %d is not inside reach", s.Who))
}
}
if err := b.Legal(Next(s, r), r.View); err != nil {
return no(err.Error())
}
return Accepted()
}
One flag decides how much of the world a step is asked about, and it exists because a plan is several steps and the actor is in one place. When a plan arrives, the world can answer for the first step, because the first step is about to be posted from where the actor stands. It cannot answer for the third, because where the actor will stand when the third comes due is where the first two will have put it, and the check does not walk the plan to find out. So a step that is not placed is asked only what does not depend on the actor's position: that its cell is ground and that its grams are held. Everything else waits for dispatch, when every step is placed. The alternative, asking the whole plan about the world as it stands now, refuses every plan that walks somewhere and does something there, which is most of the plans a person makes.
The sixth check reads the clock and the roster, and the number it reads the clock against goes in a file beside the caps. The block is the seam's own and not the planning block's, because the planning block bounds what a model may answer and this bounds how long an answer stays true; the two are read by two functions that refuse each other's keys, which is how the three blocks before them are read.
// internal/law/seam.go — below the fifth check
// FreshnessOf is the sixth check, on one step: the world has not moved
// past the premises. The proposal is no older than the staleness cap,
// and every body the step names is still alive. A dead body is not in
// the reading at all, so the question is one lookup.
func FreshnessOf(n int, s Step, asked int, r Reading, stale int) Verdict {
if age := r.Tick - asked; stale > 0 && age > stale {
return Refused(OnFreshness, fmt.Sprintf("asked at tick %d, and it is tick %d: %d ticks old, and the cap is %d", asked, r.Tick, age, stale))
}
if s.Who != 0 {
if _, alive := r.Bodies[s.Who]; !alive {
return Refused(OnFreshness, fmt.Sprintf("step %d names body %d, which is no longer in the world", n, s.Who))
}
}
return Accepted()
}
// configs/thought.json — the retrieval, reflection and planning blocks are earlier chapters'; this is the block beside them
"seam": {
"stale": 200
}
// internal/village/seam.go
// Seam is the block of configs/thought.json a proposal is aged by: a
// proposal older than Stale ticks, at arrival or at dispatch, is a
// decision about a world that is gone.
type Seam struct {
Stale int `json:"stale"`
}
// ReadSeam reads the seam block out of the embedded configs, beside
// the three blocks earlier chapters read and without reading them, and
// refuses a key it does not know.
func ReadSeam() (Seam, error) {
b, err := configs.Files.ReadFile(configs.Thought)
if err != nil {
return Seam{}, fmt.Errorf("village: %w", err)
}
var blocks map[string]json.RawMessage
if err := json.Unmarshal(b, &blocks); err != nil {
return Seam{}, fmt.Errorf("village: %s: %w", configs.Thought, err)
}
raw, ok := blocks["seam"]
if !ok {
return Seam{}, fmt.Errorf("village: %s: no seam block", configs.Thought)
}
var s Seam
dec := json.NewDecoder(bytes.NewReader(raw))
dec.DisallowUnknownFields()
if err := dec.Decode(&s); err != nil {
return Seam{}, fmt.Errorf("village: %s: seam: %w", configs.Thought, err)
}
if s.Stale < 1 {
return Seam{}, fmt.Errorf("village: %s: a staleness cap of %d ticks would refuse every proposal", configs.Thought, s.Stale)
}
return s, nil
}
// internal/law/seam.go — the six in order, and one step again when due
// Run runs one check by name over a proposal on arrival, so that the
// six can be run in an order other than the table's and the cost of
// doing so seen. The first two are the table's own; the third and
// fourth read the set and the law; the last two read the world, the
// fifth asking the placed question of the first step alone.
func Run(check string, p Proposal, t Terms, r Reading) Verdict {
switch check {
case OnShape:
return ShapeOf(p.Plan, t.Caps)
case OnVerb:
return VerbsOf(p.Plan, t.Caps)
case OnGrounding:
return GroundingOf(p.Plan, p.Set)
case OnLaw:
return LawOf(p.Plan, p.Profile, t.Law)
case OnReach:
for i, s := range p.Plan.Steps {
if v := ReachOf(i+1, s, r, i == 0); !v.OK {
return v
}
}
return Accepted()
case OnFreshness:
for i, s := range p.Plan.Steps {
if v := FreshnessOf(i+1, s, p.Asked, r, t.Stale); !v.OK {
return v
}
}
return Accepted()
}
return Refused(check, "no such check")
}
// Validate is the seam on arrival: the six checks, in the table's
// order, over the whole plan, and the first that says no is the
// verdict. Cheapest first, and the last two need the world.
func Validate(p Proposal, t Terms, r Reading) Verdict {
return InOrder(Checks[:], p, t, r)
}
// InOrder runs the checks named, in the order named, and stops at the
// first refusal. Validate hands it the table's order; a bench may hand
// it any other, which is the counterfactual and not the design.
func InOrder(order []string, p Proposal, t Terms, r Reading) Verdict {
for _, check := range order {
if v := Run(check, p, t, r); !v.OK {
return v
}
}
return Accepted()
}
// Due is the seam at dispatch: step n of an accepted plan has come
// due, and the two checks that need the world run again over the
// world as it stands, this time with the actor placed. A step refused
// here refuses the rest of the plan, because a plan is one proposal
// and one verdict, and nothing here hands back the steps that
// checked.
func Due(n int, p Proposal, t Terms, r Reading) Verdict {
s := p.Plan.Steps[n-1]
if v := ReachOf(n, s, r, true); !v.OK {
return v
}
return FreshnessOf(n, s, p.Asked, r, t.Stale)
}
Two hundred ticks is twenty seconds of world, and the math interlude further down derives it from two numbers already on the page: the horizon, and how long an answer takes to land. A proposal exactly as old as the cap passes and one tick older does not, and the reason names both ticks and the difference, so that a row in the ledger says how late the answer was without anybody subtracting. The second half of the check asks the reading whether every body a step names is still in it; a body the roster has buried is not, and the question is one lookup.
Run is one check by name and InOrder is a list of names,
which is what lets the order be a thing a bench can vary. Validate hands
it the table's order and is the seam on arrival: shape, verb, grounding, law, reach with
the first step placed, freshness over every step, and the first no is the verdict.
Due is the seam at dispatch, for one step that has come due: reach with
the step placed, then freshness, over a reading taken at that boundary. It hands back
nothing but a verdict, because a plan is one proposal and one verdict, and a step
refused here refuses whatever is left of the plan.
$ go run ./cmd/decide -mode settings | tail -20
the six checks, in the order they are run, and what each is handed
# check needs asks
1 shape the plan, caps at least one step, no more than the cap, a word in every verb slot
2 verb the table, caps every verb in the table with its own argument; the spans within the horizon
3 grounding the set every body named is in the set stored with the proposal
4 law the law every step is one the profile's law permits; the clause is the reason
5 reach the world the target is where the action needs it; the world's own rule on the action
6 freshness the world no older than the staleness cap; every body named still in the world
the two moments the checks run at
on arrival all six, over the whole plan, with the world asked about the first step
at dispatch the last two again, over one step, when that step comes due
a reading of the world, as the last two are handed it
the tick; the actor's body and the view it stands in; who its eyes returned;
every living body, with its cell and its grams. Taken at a boundary, kept for one verdict
what is done with a refusal: the plan is refused whole and dispatches nothing; the
verdict, the check and the reason go into the ledger beside the answer's bytes;
the villager runs the habit; and no memory is written about any of it
Read the needs column downward. Two checks need the plan and the table; one needs a column of the row; one needs a law; two need the world. The order is the cost of the input, and it is the order because a plan that is not the shape asked for should cost nothing to refuse, and a plan that names a body the villager never knew should be refused for that and not for whatever the world happens to say about the body. The last line of the block is the three rules of failure and the rule about memory, printed by the bench because every run below is a run of them.
The no at tick 2601
Ander's plan at tick 1400 is the one four-step plan the recording accepted, and it is the plan the last chapter's exercise flagged: a watch of Halla, who is in his grounding set through his memories and not in his sight. It goes through the six here with a reading of the world taken at the boundary of tick 1400, and the bench prints the reading before the verdicts so that every yes can be checked against what the check was handed.
$ go run ./cmd/decide -mode arrive -who Ander -now 1400 | tail -40
Ander's eyes at the boundary of tick 1400: 3 Mose on 9,6, 1.1 cells off
the grounding set, stored with the proposal: 1 Halla, 2 Ander, 3 Mose
the prompt: 1050 bytes, sha256 c8e29a79d1302570, 374 tokens in, 133 out, stopped because: stop
what the model answered, which yours will differ from:
| { "steps": [ { "reason": "Ander remembers that he has not eaten anything yet," , "verb": "go", "where": {"x": 9, "y": 5} } , { "reason": "Ander is not hungry anymore," , "verb": "wait" }, { "reason": "Ander's body is empty," , "verb": "watch", "who": 1 } , { "reason": "Ander has no food left," , "verb": "go", "where": {"x": 9, "y": 5} } ] }
read strictly: an object of 4 step(s)
# verb argument ticks reason, a model's, read by nothing
1 go to 9,5 40 Ander remembers that he has not eaten anything yet,
2 wait - 20 Ander is not hungry anymore,
3 watch 1 Halla 20 Ander's body is empty,
4 go to 9,5 40 Ander has no food left,
the reading of the world at the boundary of tick 1400, handed to the last two checks
the actor 2 Ander on 8,5 carrying 150.7298 grams, heading 1.57, reach 1 cell
in sight 3 Mose
alive 1 Halla on 9,3 with 65.0587 g; 2 Ander on 8,5 with 150.7298 g; 3 Mose on 9,6 with 178.2125 g
the six checks, in order, over the whole plan
# check said
1 shape yes
2 verb yes
3 grounding yes
4 law yes
5 reach yes
6 freshness yes
the fifth check put step 1 to the world as "turn left", through Legal, and the world said: allowed
the seam: accepted
the ledger row, column by column
villager Ander
tick 1400
kind plan
model qwen2.5:0.5b-instruct-q4_K_M
digest c5396e06af294bd1
settings {limit 256, context 4096, temperature 0.00, seed 1402}
prompt_sha256 c8e29a79d1302570
tokens 374 in, 133 out
grounding 1 Halla, 2 Ander, 3 Mose
answer 342 bytes, the model's, kept whatever they are
verdict accepted
failed -
reason -
the stream: 15 events pending before the seam ran, 15 after; the seam wrote nothing
Six yeses, and the one that needs reading is the fifth. The watch of Halla is step 3,
she is not in sight, and reach said yes, because on arrival only the first step is
placed: the world is asked about the turn Ander's first walk begins with, through
Legal, and the world said allowed. Whether Halla is in his sight when the
watch comes due is a question for the boundary it comes due at, and the dispatch
section asks it. The row is the last chapter's row with the same fifteen columns,
accepted, and the bench counts the witness's pending events on both sides of the seam:
fifteen before, fifteen after. The seam wrote nothing, because the seam has nowhere to
write; the run against the tables at the end of the chapter makes the same count over
the memory table itself.
Then the same proposal at two ticks. Halla's plan at 2400 is a walk and a wait, accepted at the boundary it was asked at. The bench keeps the same 144 bytes, runs the world on for two hundred and one ticks, takes a second reading, and puts the same proposal through the same six.
$ go run ./cmd/decide -mode stale -who Halla -now 2400 | tail -25
the plan, asked at tick 2400, which a model wrote and yours will differ from:
# verb argument ticks reason, a model's, read by nothing
1 go to 2,7 40 go walks to a cell
2 wait - 20 wait stands still
the reading of the world at the boundary of tick 2400, handed to the last two checks
the actor 1 Halla on 9,3 carrying 109.6476 grams, heading 3.67, reach 1 cell
in sight 2 Ander
alive 1 Halla on 9,3 with 109.6476 g; 2 Ander on 7,2 with 180.2103 g; 3 Mose on 6,6 with 179.7334 g
the reading of the world at the boundary of tick 2601, handed to the last two checks
the actor 1 Halla on 9,3 carrying 93.5676 grams, heading 3.67, reach 1 cell
in sight 2 Ander
alive 1 Halla on 9,3 with 93.5676 g; 2 Ander on 7,2 with 180.0703 g; 3 Mose on 6,6 with 174.4327 g
# check at tick 2400 at tick 2601
1 shape yes yes
2 verb yes yes
3 grounding yes yes
4 law yes yes
5 reach yes yes
6 freshness yes no: asked at tick 2400, and it is tick 2601: 201 ticks old, and the cap is 200
the seam accepted refused by freshness: asked at tick 2400, and it is tick 2601: 201 ticks old, and the cap is 200
the same 144 bytes, asked at tick 2400: accepted at tick 2400 and refused at tick 2601
Five checks say the same thing at both ticks, and they should: the bytes are the
same, the set is the same, the law is the same, and the world's answer about a turn
toward 2,7 is the same, because Halla has not moved. What moved is the
clock. The sixth check subtracts the tick the proposal was asked at from the tick of
the reading, gets 201, compares it with 200, and refuses with both numbers in the
reason. Halla's store went from 109.6 grams to 93.6 in those two hundred ticks and
Mose's fell by a little over five, and nothing about the plan is wrong for that; it is refused
because a decision taken twenty seconds ago about where to walk is a decision about a
world that is gone, whether or not this particular world happened to stay put.
The other four refusals do not occur on the recording, for the same reason the last chapter's verb refusal did not: the schema leaves a small model few ways to name a body it was not shown, and the three people of this village spend the day standing where they were founded. So the bench takes Ander's accepted plan and perturbs it, one step at a time, six ways, and says so on each line. A check that has only ever said yes has not been seen.
$ go run ./cmd/decide -mode refuse -who Ander -now 1400 | tail -63
the plan, recorded, which a model wrote and yours will differ from:
# verb argument ticks reason, a model's, read by nothing
1 go to 9,5 40 Ander remembers that he has not eaten anything yet,
2 wait - 20 Ander is not hungry anymore,
3 watch 1 Halla 20 Ander's body is empty,
4 go to 9,5 40 Ander has no food left,
as recorded accepted
the reading of the world at the boundary of tick 1400, handed to the last two checks
the actor 2 Ander on 8,5 carrying 150.7298 grams, heading 1.57, reach 1 cell
in sight 3 Mose
alive 1 Halla on 9,3 with 65.0587 g; 2 Ander on 8,5 with 150.7298 g; 3 Mose on 9,6 with 178.2125 g
the second step swapped for a watch of body 4, which is in no grounding set
the plan 4 steps spanning 120 ticks
the seam refused by grounding: step 2 names body 4, and the grounding set is {1,2,3}
checks run 3 of 6
dispatched nothing; the plan is not trimmed to the steps that check
the ledger row, column by column
villager Ander
tick 1400
kind plan
model qwen2.5:0.5b-instruct-q4_K_M
digest c5396e06af294bd1
settings {limit 256, context 4096, temperature 0.00, seed 1402}
prompt_sha256 c8e29a79d1302570
tokens 374 in, 133 out
grounding 1 Halla, 2 Ander, 3 Mose
answer 342 bytes, the model's, kept whatever they are
verdict refused
failed grounding
reason step 2 names body 4, and the grounding set is {1,2,3}
the first step swapped for a watch of 1 Halla, who is in the set and not in sight
the plan 4 steps spanning 100 ticks
the seam refused by reach: step 1: body 1 is not in sight
checks run 5 of 6
dispatched nothing; the plan is not trimmed to the steps that check
the first step swapped for a hand of 10 grams to 1 Halla, who is not inside reach
the plan 4 steps spanning 120 ticks
the seam refused by reach: step 1: body 1 is not inside reach
checks run 5 of 6
dispatched nothing; the plan is not trimmed to the steps that check
the first step's cell swapped for 2,3, which is open water
the plan 4 steps spanning 120 ticks
the seam refused by reach: step 1: 2,3 is open water
checks run 5 of 6
dispatched nothing; the plan is not trimmed to the steps that check
the second step swapped for a hand of 301 grams to 1 Halla, more than the actor holds
the plan 4 steps spanning 140 ticks
the seam refused by reach: step 2: 301 grams named, and the actor holds 150.7298
checks run 5 of 6
dispatched nothing; the plan is not trimmed to the steps that check
a line to 3 Mose appended as a last step, and 3 Mose taken out of the reading, as a death would
the plan 5 steps spanning 130 ticks
the seam refused by freshness: step 5 names body 3, which is no longer in the world
checks run 6 of 6
dispatched nothing; the plan is not trimmed to the steps that check
6 plans refused whole, 0 steps dispatched, and the one that checks is the one above
Read the checks run line on each. The watch of body 4, which is in no
grounding set and in no world, is refused by the third check after three checks have
run, and the row records it under grounding with the set the villager was
given. A watch of Halla, who is in the set and not in sight, gets to the fifth check
and is refused there for the sight; a hand to her is refused for the reach, because
she stands two cells off and a reach is one; a walk to 2,3 is refused
because the bed says water, before the world is asked about any action; and a hand of
301 grams by a man carrying 150 is refused with both numbers, the model's and the
world's, in one sentence. The last trial perturbs the reading instead of the plan:
Mose is in sight at 1400, the bench takes him out of the reading the way the roster's
burial would, and a line spoken to him is refused by the sixth check as a line to a
body that is no longer in the world. Every one of the six dispatches nothing, and the
bench exits non-zero if any of them is accepted.
Here is the counterfactual this chapter carries, run: the six in the reverse of the table's order, off a flag the bench prints in its header. The first trial above is the one to watch.
$ go run ./cmd/decide -mode refuse -who Ander -now 1400 -reversed | tail -51 | head -5
the second step swapped for a watch of body 4, which is in no grounding set
the plan 4 steps spanning 120 ticks
the seam refused by freshness: step 2 names body 4, which is no longer in the world
checks run 1 of 6
dispatched nothing; the plan is not trimmed to the steps that check
$ go run ./cmd/decide -mode day -reversed | tail -6
Mose 2900 no - - 1 refused shape not the shape asked for: invalid character 'T' looking ...
15 calls, 15 prompts rendered here and every one the recorded bytes
9 accepted, 6 refused: 5 by shape, 1 by verb, 0 by grounding, 0 by law, 0 by reach, 0 by freshness
64 checks run in all, over 15 calls, in the order freshness, reach, law, grounding, verb, shape
every verdict above is the engine's over the recording; the words in the answers are the model's
Body 4 is refused either way, and the two ledgers disagree about why. In the table's order the row says the villager named somebody it was never told about. In the reverse order the sixth check runs first, looks body 4 up in the reading, finds nothing, and the row says the body is no longer in the world, which is a death the world never had. Both verdicts are refusals and only one of them is true, and the order is what makes it true: a check that assumes the checks before it have run can report a cause, and a check that runs first can only report a symptom. The whole recording, reversed, comes to the same fifteen verdicts with one named differently, Mose's seven steps refused for spanning 190 ticks instead of for being seven, and costs 64 checks against 60: four more, two of them readings of a world that a plan of seven steps was never going to be allowed to reach.
The fifth check's claim is that it asks the world's rule through the same function an animal pays, and a claim about a function is checked by calling it from both sides. The bench stands Halla on a cell of ground with open water east of it and spawns a browser off the fauna table on the same cell, facing the same way, with a mind that only ever asks to walk. Halla proposes a walk to the far shore. The browser takes its tick.
$ go run ./cmd/decide -mode beside -who Halla -now 2400 | tail -22
the cell 1,3, ground; 2,3 east of it is open water; 7,3 beyond is ground again
the villager 1 Halla, stood there by the bench facing east, carrying 109.6476 grams
the animal 4, a browser off the fauna table, spawned there by the bench facing east, carrying 100.0000 grams
both facing the water, with full stores
the villager's step go to 7,3, which the fifth check puts to the world as "walk"
the seam refused by reach: step 1: creature 1 at 2,3 cannot walk: the cell ahead is open water or off the grid
the call it made Legal(walk): creature 1 at 2,3 cannot walk: the cell ahead is open water or off the grid
the animal's tick asked to walk; the phase's report: creature 4 at 2,3 cannot walk: the cell ahead is open water or off the grid
the same value errors.Is(ErrNoGround) true for the villager and true for the animal; ErrBroke false and false
refusals so far 1 for the animal, by the world's own check inside its tick
both stores emptied by the bench, still facing the water
the villager's step go to 7,3, which the fifth check puts to the world as "walk"
the seam refused by reach: step 1: creature 1 at 1,3 cannot walk: the store cannot pay for it
the call it made Legal(walk): creature 1 at 1,3 cannot walk: the store cannot pay for it
the animal's tick asked to walk; the phase's report: creature 4 at 1,3 cannot walk: the store cannot pay for it
the same value errors.Is(ErrNoGround) false for the villager and false for the animal; ErrBroke true and true
refusals so far 2 for the animal, by the world's own check inside its tick
one function, (*beast.Beast).Rule, under Legal: the price to the store first, then the entry's own test
the villager's refusal is the seam's reason and the animal's is the phase's report, and neither was told which it was
Two sentences that differ in one character, the creature's number, and the difference
is not cosmetic. The villager's sentence is the fifth check's reason, produced at a
boundary by Legal called on her body with the walk the step asks for; the
animal's is the roster's report, produced inside the phase by the same
Legal called on its body with the walk its mind asked for. Neither call
was told which kind of creature it was about, because the function has no argument
for that. The same value comes back in both, and errors.Is says so. Then
the bench empties both stores and the pair changes rule together: the price is put to
the store before the ground is looked at, so an empty store refuses a walk before the
pond gets a say, and the cell in the sentence changes from the water the rule was about
to the cell the body stands on, which is the refusal struct doing what it has always
done.
A plan's last step comes due late. The plan lands some ticks after it was asked, because the answer took that long, and then its steps run one after another for the spans the table gives them, so the last step comes due when every step before it has run. Take the four-step plan above: a walk, a wait, a watch and a walk, 120 ticks on the table, and an answer that landed 49 ticks after the asking in the live run at the end of this chapter. Step 4 comes due at 49 + 40 + 20 + 20 = 129 ticks after the asking, and the cap is 200, so it is dispatched. The same plan with an answer that took 121 ticks has its last step due at 121 + 80 = 201, one over, and the dispatch section shows that one refused.
The cap is set from the worst case. A plan may span at most the horizon, 160 ticks, and its last step is at least the table's shortest span, 10, so the last step of the longest allowed plan comes due at most 150 ticks after the plan lands. For that step to be fresh, the answer has to land within 200 − 150 = 50 ticks of the asking: five seconds at this pace. The three live calls on this page took 49, 35 and 67 ticks (measured here; yours will differ), so a four-step plan answered as fast as Ander's runs out before it is stale, and a plan answered as slowly as the paragraph the small model wrote when it was asked without a schema would have its tail refused. Both of those are the design: the cap is forty ticks of slack over the horizon, which is about one call at the durations measured on this page, and not a number picked to make every plan fit.
duek = asked + land + (span1 + … + spank−1)
agek = duek − asked = land + span1 + … + spank−1
fresh when agek ≤ stale, so land ≤ stale − (horizon − 10) = 50 for the longest plan
$ go test ./internal/law/ -run 'TestABodyOutsideTheGroundingSetIsRefusedByName|TestTheLawCheckAsksTheLawItIsHandedAndTheEmptyLawPermitsEverything|TestReachAsksTheWorldsOwnRuleThroughTheCallEveryAnimalMakes|TestFreshnessRefusesAnOldProposalAndABodyThatIsGone|TestTheSixRunInOrderAndTheFirstNoIsTheVerdict|TestAStepCheckedAgainWhenDueIsJudgedOverTheWorldAsItStands|TestTheWorldReachesTheLawOnlyAsAReading|TestTheReasonIsReadByNothing|TestLawImportsNeitherTheModelClientNorTheStore' -v
=== RUN TestTheReasonIsReadByNothing
law_test.go:258: four reasons, one verdict; every source file walked, Reason declared once and read on no line
--- PASS: TestTheReasonIsReadByNothing (0.00s)
=== RUN TestLawImportsNeitherTheModelClientNorTheStore
rule_test.go:55: every file of the package read, and none of them names the model client or the store
--- PASS: TestLawImportsNeitherTheModelClientNorTheStore (0.00s)
=== RUN TestABodyOutsideTheGroundingSetIsRefusedByName
seam_test.go:90: refused: step 3 names body 7, and the grounding set is {1,2,3}; a cell is not an identity and the set is not asked about one
--- PASS: TestABodyOutsideTheGroundingSetIsRefusedByName (0.00s)
=== RUN TestTheLawCheckAsksTheLawItIsHandedAndTheEmptyLawPermitsEverything
seam_test.go:122: the empty law permits; a one-clause law refuses naming its clause; no law refuses everything
--- PASS: TestTheLawCheckAsksTheLawItIsHandedAndTheEmptyLawPermitsEverything (0.00s)
=== RUN TestReachAsksTheWorldsOwnRuleThroughTheCallEveryAnimalMakes
seam_test.go:193: refused by the world's own sentence: creature 1 at 2,3 cannot walk: the cell ahead is open water or off the grid
--- PASS: TestReachAsksTheWorldsOwnRuleThroughTheCallEveryAnimalMakes (0.00s)
=== RUN TestFreshnessRefusesAnOldProposalAndABodyThatIsGone
seam_test.go:220: asked at tick 2400, and it is tick 2601: 201 ticks old, and the cap is 200; step 1 names body 2, which is no longer in the world
--- PASS: TestFreshnessRefusesAnOldProposalAndABodyThatIsGone (0.00s)
=== RUN TestTheSixRunInOrderAndTheFirstNoIsTheVerdict
seam_test.go:256: in the table's order, refused by shape: a plan of 7 steps, and the cap is 5; reversed, by freshness: step 7 names body 9, which is no longer in the world
--- PASS: TestTheSixRunInOrderAndTheFirstNoIsTheVerdict (0.00s)
=== RUN TestAStepCheckedAgainWhenDueIsJudgedOverTheWorldAsItStands
seam_test.go:282: accepted whole on arrival; at dispatch, step 2: body 2 is not inside reach; then asked at tick 100, and it is tick 301: 201 ticks old, and the cap is 200
--- PASS: TestAStepCheckedAgainWhenDueIsJudgedOverTheWorldAsItStands (0.00s)
=== RUN TestTheWorldReachesTheLawOnlyAsAReading
seam_test.go:325: every source file read; of this module, sim and beast and nothing else
--- PASS: TestTheWorldReachesTheLawOnlyAsAReading (0.00s)
PASS
ok theworld/internal/law 0.005s
$ go test ./internal/village/ -run 'TestTheShippedSeamIsAStalenessCapInTicks|TestTheVillageStillImportsNeitherTheModelClientNorTheStore' -v
=== RUN TestTheVillageStillImportsNeitherTheModelClientNorTheStore
reflect_test.go:259: every file of the package read, and none of them names the model client or the store
--- PASS: TestTheVillageStillImportsNeitherTheModelClientNorTheStore (0.00s)
=== RUN TestTheShippedSeamIsAStalenessCapInTicks
seam_test.go:20: a proposal older than 200 ticks is refused, at arrival or at dispatch; the horizon is 160, so the answer has 40 ticks to land in
--- PASS: TestTheShippedSeamIsAStalenessCapInTicks (0.00s)
PASS
ok theworld/internal/village 0.004s
Nine tests in the law and two in the village, and the two that guard the boundary are
the ones to read. The last chapter's sealed-import test still passes with a new file in
the package, and the new one beside it reads the same import lines for the opposite
purpose: of this module's packages, the law may name the coordinate package and the
beast package and no other, and it fails if the beast package is not named at all,
because a fifth check that did not import the rule an animal pays could not be calling
it. The reason walk from the last chapter passes over the new file too; nothing in it
selects a Reason. The one-clause law in the fourth test is written in the
test file and nowhere else, and the fifth test compares the seam's sentence with
Legal's, character for character, on a walk into the same pond the bench
found.
Step 4, due at tick 1601, is 201 ticks old
The dispatch half is the last chapter's keep with the seam in it. At the
boundary a step comes due, a reading is taken and Due runs; a step that
checks is posted to the mailbox at every boundary for the ticks the table gives it, as
the action Next works out against the body as it stands; a step that does
not check is not posted, and neither is anything after it. The plan's whole span is run
either way, so that the ticks the habit gets can be counted, and a refused step becomes
a ledger row of its own: the same fifteen columns, the kind step, the tick
it came due at, the plan's own bytes as the answer, and the verdict.
$ go run ./cmd/decide -mode dispatch -who Ander -now 1400 | tail -18
Ander is on 8,5 carrying 150.7298 grams; the mailbox has been read 0 times and the habit has run 500 ticks
# verb argument due reach, then freshness, at the due tick posted taken habit refused what the world did
1 go to 9,5 1400 yes, yes 40 40 0 0 5 turns, 1 walks: went from 8,5 to 9,5
2 wait - 1440 yes, yes 20 20 0 0 stood on 9,5
3 watch 1 Halla 1460 yes, yes 20 20 0 0 2 turns, then stood on 9,5
4 go to 9,5 1480 yes, yes 40 40 0 0 0 turns, 0 walks: went from 9,5 to 9,5
120 intents posted at the boundary, 120 taken out of the slot, 0 ticks ran the habit, over the plan's 120 ticks
what the witness wrote down while the plan ran, in the register the stream is kept in
tick 1404 saw Halla came into sight, 2.0 cells off
tick 1400 did ate 16 mouthfuls on 8,5, 8.0 grams
tick 1406 did went from 8,5 to 9,5
Ander is on 9,5 carrying 139.7629 grams at the boundary of tick 1520
the ledger, 1 row(s): the proposal, and one row for each step refused at dispatch
# tick kind verdict failed reason
1 1400 plan accepted - -
The watch of Halla, which reach could not answer for on arrival, is answered at tick
1460, and the answer is yes: by then Ander has walked to 9,5 and Halla has
come into his sight, at tick 1404 by the witness's row, so the reading at 1460 has her
in Sees. The world moved in the plan's favour. That is as much a fact
about the dispatch half as a refusal would be, and it is why the check is asked at the
due tick and not on arrival: asked at 1400 it would have said no to a watch that
turned out to be of somebody standing two cells away. A hundred and twenty intents,
a hundred and twenty taken, no ticks on the habit, and one row in the ledger.
Now the same plan with the answer taken to have been in flight for 121 ticks, which is the flag the math interlude priced. The plan lands at the boundary of tick 1521 and is accepted whole: 121 ticks old is inside the cap. Its steps come due at 1521, 1561, 1581 and 1601.
$ go run ./cmd/decide -mode dispatch -who Ander -now 1400 -late 121 | tail -32
landed at the boundary of tick 1521; the six checks on arrival
# check said
1 shape yes
2 verb yes
3 grounding yes
4 law yes
5 reach yes
6 freshness yes
the seam: accepted
Ander is on 8,5 carrying 166.5498 grams; the mailbox has been read 0 times and the habit has run 621 ticks
# verb argument due reach, then freshness, at the due tick posted taken habit refused what the world did
1 go to 9,5 1521 yes, yes 40 40 0 0 4 turns, 1 walks: went from 8,5 to 9,5
2 wait - 1561 yes, yes 20 20 0 0 stood on 9,5
3 watch 1 Halla 1581 yes, yes 20 20 0 0 2 turns, then stood on 9,5
4 go to 9,5 1601 refused by freshness: asked at tick 1400,... 0 0 40 0 the habit; stood on 8,3 at the end
80 intents posted at the boundary, 80 taken out of the slot, 40 ticks ran the habit, over the plan's 120 ticks
step 4 refused at its due tick; the witness held 0 events before the check and 0 after it
what the witness wrote down while the plan ran, in the register the stream is kept in
tick 1524 saw Halla came into sight, 2.0 cells off
tick 1520 did ate 26 mouthfuls on 8,5, 13.0 grams
tick 1526 did went from 8,5 to 9,5
tick 1611 did went from 9,5 to 8,3
tick 1640 did ate 12 mouthfuls on 8,3, 6.0 grams
tick 1641 saw Halla put 13 parcels in Ander's hands, 6.5 grams
Ander is on 8,3 carrying 160.0990 grams at the boundary of tick 1641
the ledger, 2 row(s): the proposal, and one row for each step refused at dispatch
# tick kind verdict failed reason
1 1400 plan accepted - -
2 1601 step refused freshness asked at tick 1400, and it is tick 1601: 201 ticks old, and the cap is 200
Three steps run and the fourth does not. At 1601 the reading's tick minus the asked
tick is 201, the sixth check refuses with both ticks in the sentence, nothing is posted
for the step's forty ticks, and the habit has every one of them: Ander walks to
8,3, eats, and has thirteen parcels put in his hands by Halla, none of
which any plan asked for. The ledger has two rows. The first is the proposal, accepted, and
it stays accepted, because a row is never updated; the second is the step, refused by
freshness at 1601, with the plan's bytes beside it. A person reading the two can see
that a plan was accepted whole and that its fourth step was stale by the time it came
due, which is what happened. The witness held no events on either side of the check,
and nothing about the refusal reaches the stream: the rows the witness closed during
those 120 ticks are a sighting, two meals, two walks and a gift, and every one of them
is something the world did.
The obvious dispatcher, when a step is refused, skips it and carries on, because two of the three steps were fine and throwing them away looks wasteful. The bench runs it behind a flag it prints in its header. The plan it runs is the bench's own, because no plan on the recording hands anything: to Ander, a hand of 105 grams, and home. The 105 stands where a model's number stands, a number nobody checked against a store when it was written, and Halla holds 109.6 grams when the plan arrives, so the fifth check's grams question passes on arrival.
$ go run ./cmd/decide -mode dispatch -who Halla -now 2400 -errand -grams 105 | tail -15
# verb argument due reach, then freshness, at the due tick posted taken habit refused what the world did
1 go to 7,2 2400 yes, yes 40 40 0 0 0 turns, 7 walks: went from 9,3 to 7,2
2 hand 105 grams, 2 Ander 2440 refused by reach: step 2: 105 grams named... 0 0 40 37 the habit; stood on 7,2 at the end
3 go to 8,5 2480 not run: an earlier step was refused 0 0 40 40 the habit; stood on 7,2 at the end
40 intents posted at the boundary, 40 taken out of the slot, 80 ticks ran the habit, over the plan's 120 ticks
step 2 refused at its due tick; the witness held 0 events before the check and 0 after it
what the witness wrote down while the plan ran, in the register the stream is kept in
tick 2407 did went from 9,3 to 7,2
Halla is on 7,2 carrying 95.5420 grams at the boundary of tick 2520
the ledger, 2 row(s): the proposal, and one row for each step refused at dispatch
# tick kind verdict failed reason
1 2400 plan accepted - -
2 2440 step refused reach step 2: 105 grams named, and the actor holds 102.4989
$ go run ./cmd/decide -mode dispatch -who Halla -now 2400 -errand -grams 105 -partial | tail -17 | head -7
# verb argument due reach, then freshness, at the due tick posted taken habit refused what the world did
1 go to 7,2 2400 yes, yes 40 40 0 0 0 turns, 7 walks: went from 9,3 to 7,2
2 hand 105 grams, 2 Ander 2440 refused by reach: step 2: 105 grams named... 0 0 40 37 the habit; stood on 7,2 at the end
3 go to 8,5 2480 yes, yes 40 40 0 30 6 turns, 34 walks: went from 7,2 to 7,3
80 intents posted at the boundary, 80 taken out of the slot, 40 ticks ran the habit, over the plan's 120 ticks
Start from the symptom, which is the second run's line for step 3. Halla walked to
Ander, was refused the hand at tick 2440 because the walk there had cost her seven
grams and she now holds 102.5 of the 105 the plan named, and then set off home, and got
one cell, the pond refusing thirty of her walks. Two of three
steps ran, eighty intents were posted, and the ledger says accepted on the
plan and refused on step 2, which is exactly what it says in the first
run, where forty intents were posted and she stayed where she was. The ledger cannot
tell the two runs apart, because a step row records that a step was refused and not
what was done about the steps after it. Reason from there to the cause. A plan is one
proposal and one verdict; a dispatcher that runs steps 1 and 3 of a three-step plan is
executing a plan of two steps, a walk to a man and a walk away from him, which nobody
proposed and no check judged, and the ledger, which is what this volume asserts
against, has no row for it. The fix is the line in Due's comment, made
into the dispatcher's loop: the first no ends the plan, the habit takes the rest of the
ticks, and the step row is the last thing written about that proposal. What is lost is
the walk home, and the habit walks her home when it wants to.
Eighty-eight memory rows before every ledger row and eighty-eight after
The live path runs the same code against the tables and the model server: the committed day into an empty database, the prompt rendered over rows read back, one call to the small model, the six over a reading taken at the boundary the answer lands at, the row appended whatever the verdict, and then dispatch with the step rows appended as they happen. The answer takes as long as it takes, the bench turns that into ticks at the stated pace and runs the world on for them before the reading is taken, so the live path is the only one on this page where the landing tick is measured and not a flag. Around every row the bench counts the memory table, over rows read back in order, and stops with a non-zero status if the count moves.
The containers are the last chapter's: Ollama on the closed bridge with
OLLAMA_MAX_LOADED_MODELS=1 and the three model files on a named volume, the
Go code in world-go, and the database in world-db, which starts
empty after podman kill and podman start because its data
directory is a tmpfs. The small model is loaded before the clock starts; the embedding
of the situation evicts it and the call loads it back, and both are inside the duration
the bench prints. Its API reference is under github.com/ollama/ollama.
$ podman kill world-db && podman start world-db
world-db
world-db
$ podman exec -w /bench world-go go run ./cmd/decide -mode live -who Ander -now 1400 | tail -40 | head -13
the prompt: 1050 bytes, sha256 c8e29a79d1302570, 374 tokens in, 133 out, stopped because: stop
what the model answered, which yours will differ from:
| { "steps": [ { "reason": "Ander remembers that he has not eaten anything yet," , "verb": "go", "where": {"x": 9, "y": 5} } , { "reason": "Ander is not hungry anymore," , "verb": "wait" }, { "reason": "Ander's body is empty," , "verb": "watch", "who": 1 } , { "reason": "Ander has no food left," , "verb": "go", "where": {"x": 9, "y": 5} } ] }
read strictly: an object of 4 step(s)
# verb argument ticks reason, a model's, read by nothing
1 go to 9,5 40 Ander remembers that he has not eaten anything yet,
2 wait - 20 Ander is not hungry anymore,
3 watch 1 Halla 20 Ander's body is empty,
4 go to 9,5 40 Ander has no food left,
the call took 4.933s, 49 ticks at 10 a second (measured here; yours will differ), so the answer lands at tick 1449
the reading of the world at the boundary of tick 1449, handed to the last two checks
the actor 2 Ander on 8,5 carrying 157.0098 grams, heading 1.57, reach 1 cell
in sight 3 Mose
$ podman exec -w /bench world-go go run ./cmd/decide -mode live -who Ander -now 1400 | tail -21
4 law yes
5 reach yes
6 freshness yes
the seam: accepted
the row appended as proposal 1, accepted; memory rows before it 88, after it 88
# verb argument due reach, then freshness, at the due tick posted habit what the world did
1 go to 9,5 1449 yes, yes 40 0 4 turns, 1 walks: went from 8,5 to 9,5
2 wait - 1489 yes, yes 20 0 stood on 9,5
3 watch 1 Halla 1509 yes, yes 20 0 2 turns, then stood on 9,5
4 go to 9,5 1529 yes, yes 40 0 0 turns, 0 walks: went from 9,5 to 9,5
120 intents posted at the boundary and 0 ticks ran the habit, over the plan's 120 ticks
Ander's proposals read back, ORDER BY id: 1 row(s)
id tick kind prompt_sha256 in out grounding verdict failed reason
1 1400 plan c8e29a79d1302570 374 133 {1,2,3} accepted - -
Ander's current plan, the newest accepted row of the plan kind: proposal 1, asked at tick 1400
qwen2.5:0.5b-instruct-q4_K_M is the model resident now, answering on the processor, with no bytes on a graphics card
and not one number the models answered is on this page
The call took 4.933 seconds on this machine, the eight-core AMD Ryzen 7 3700X with 30 GB of memory every duration in this volume is measured on, rootless podman, the models answering on the processor (measured here; yours will differ), which at ten ticks a second is 49 ticks, so the reading is taken at 1449 and the plan is accepted there. Its four steps come due at 1449, 1489, 1509 and 1529, every one is placed and checked and posted, and the last is 129 ticks old, which is the arithmetic in the interlude. Eighty-eight memory rows before the row and eighty-eight after. The words the model wrote came back the same as the recording's on this machine, which is what a seeded answer at temperature nought does here and is not a check; the six would judge different words by the same rule.
$ podman exec -w /bench world-go go run ./cmd/decide -mode live -who Mose -now 1900 -stale 60 | tail -16
the row appended as proposal 2, accepted; memory rows before it 88, after it 88
# verb argument due reach, then freshness, at the due tick posted habit what the world did
1 go to 9,3 1935 yes, yes 40 0 4 turns, 13 walks: went from 9,6 to 9,3
2 wait - 1975 refused by freshness: asked at tick 1900,... 0 20 the habit; stood on 9,3 at the end
the row appended as proposal 3, refused; memory rows before it 88, after it 88
40 intents posted at the boundary and 20 ticks ran the habit, over the plan's 60 ticks
Mose's proposals read back, ORDER BY id: 2 row(s)
id tick kind prompt_sha256 in out grounding verdict failed reason
2 1900 plan 88130533a0fe55bf 397 60 {1,2,3} accepted - -
3 1975 step 88130533a0fe55bf 397 60 {1,2,3} refused freshness asked at tick 1900, and it is tick 19...
Mose's current plan, the newest accepted row of the plan kind: proposal 2, asked at tick 1900
qwen2.5:0.5b-instruct-q4_K_M is the model resident now, answering on the processor, with no bytes on a graphics card
and not one number the models answered is on this page
The cap is sixty for this run, off the flag and not the file, so that a dispatch
refusal can be seen reaching the table without waiting on an answer slow enough to
earn one under the file's two hundred. The answer landed 35 ticks late; the walk came
due at 1935 and ran; the wait came due at 1975, 75 ticks after the asking, and the
sixth check refused it. The ledger then has two rows for Mose and the second is of the
step kind, at the tick it came due, carrying the same prompt digest, the
same token counts and the same grounding set as the plan it belongs to. The query that
picks a current plan asks for the plan kind and finds row 2; nothing on this page reads
the step row back into a decision, and the handover says so.
$ podman exec -w /bench world-go go run ./cmd/decide -mode live -who Halla -now 2900 -noschema | tail -12
the call took 6.8s, 67 ticks at 10 a second (measured here; yours will differ), so the answer lands at tick 2967
the seam: refused by shape: lang: qwen2.5:0.5b-instruct-q4_K_M answered with something that is not the shape asked for: invalid character 'T' looking for beginning of value
the row appended as proposal 4, refused; memory rows before it 88, after it 88
Halla's proposals read back, ORDER BY id: 1 row(s)
id tick kind prompt_sha256 in out grounding verdict failed reason
4 2900 plan 6f9a1c245cac1109 361 256 {1,2,3} refused shape not the shape asked for: invalid char...
Halla's current plan: none; no accepted plan in the ledger, so the habit runs
qwen2.5:0.5b-instruct-q4_K_M is the model resident now, answering on the processor, with no bytes on a graphics card
and not one number the models answered is on this page
$ podman exec world-db psql -U world -d world -c "SELECT id, villager, tick, kind, verdict, failed, left(reason, 44) AS reason FROM proposal ORDER BY id;"
id | villager | tick | kind | verdict | failed | reason
----+----------+------+------+----------+-----------+----------------------------------------------
1 | Ander | 1400 | plan | accepted | |
2 | Mose | 1900 | plan | accepted | |
3 | Mose | 1975 | step | refused | freshness | asked at tick 1900, and it is tick 1975: 75
4 | Halla | 2900 | plan | refused | shape | lang: qwen2.5:0.5b-instruct-q4_K_M answered
(4 rows)
$ podman exec world-db psql -U world -d world -c "SELECT id, tick, kind FROM proposal WHERE villager = 'Mose' AND kind = 'plan' AND verdict = 'accepted' ORDER BY id DESC LIMIT 1;"
id | tick | kind
----+------+------
2 | 1900 | plan
(1 row)
The third call is the last chapter's counterfactual asked again, without the schema, and what came back is a paragraph that the strict read refuses at its first character. The five checks after shape did not run, no reading was taken, and the row records the refusal with the reader's sentence. Eighty-eight memory rows before it and eighty-eight after: a villager whose answer was thrown away has nothing in her stream about having answered. That is the rule about memory as a count rather than a promise, and the reason for the rule is what a stream that recorded refusals would do on the next prompt: it would put the refusal in front of the model, in the villager's own voice, and the model would learn to argue with the engine. Four rows in the ledger, two of them refusals, one at arrival and one at dispatch, and the newest accepted plan of the plan kind for Mose is still row 2.
Why callers build the world reading
Take the village away and what is left is an arrangement for letting an untrusted answer act on a live system. The usual arrangement gives the checking code a handle on the system, and from that moment the checker can do anything the handle can: read the clock, open a connection, ask a model whether the answer looks all right. The arrangement here gives the checker a value instead. Whoever drives the villager stands at a tick boundary, reads the roster, and builds a reading: this tick, this body, this view, these bodies with these cells and these grams. The six checks are functions of the proposal, the set, the law and that value, and a test reads their import lines to hold them to it. The consequence is the one this volume is built on: a verdict computed over a recording and a verdict computed live are the same function of the same arguments, so every verdict on this page replays, and the fifteen verdicts of the recording are the verdicts the day would have left.
The second thing that generalizes is the order, and the reversed run is the argument for it. Each check after the first assumes the ones before it have run, and that assumption is what lets a refusal name a cause. The grounding check can say you named somebody you were never told about because the verb check has already established that the step's argument is a body; the reach check can ask about a body's cell because grounding has established the body is one the villager knew; the freshness check can say the body is gone because reach has established it was somewhere. Run them the other way and a body that never existed is reported as a body that died. Cheapest first is the ordering that costs least, and it is also the ordering under which every reason in the ledger is a true sentence, and the second property is the one the ledger needs.
The third is the two moments. An answer that arrives seconds after the question is an answer about the past, and there are two ways to make that safe: stop the world while the model thinks, or check the answer against the world as it stands and refuse what no longer fits. The first is the design this volume refused in its second chapter, because a tick that waits on a socket is a tick with no budget. The second is what the sixth check and the dispatch half do, and the price of it is on this page in numbers: a four-step plan answered in five seconds runs out before it is stale, one answered in twelve loses its last step, and the habit has the ticks either way. A plan is a suggestion about the near future that the world is free to overtake, and the villager always has an answer that is not a plan.
Checkpoint
- Name the six checks in order and, for each, what it is handed: the plan and the caps, the table, the set on the row, a law, or a reading of the world; then say which two run again at dispatch and why the other four do not need to.
- Say what a
Readingcarries, which package the law imports to ask the world's rule and why a reading made only of values could not have carried that call, and which test holds the law to that import and no other. - From the six refusals in the refuse run, say which check refused each and what its reason names; then say why a watch of a body not in sight is refused on arrival when it is the first step and not when it is the third.
- Work out, from the table's spans and a landing delay, the tick each step of a four-step plan comes due, and the largest delay under which its last step is still inside a cap of 200; say what the file's forty ticks of slack are forty ticks of.
- Read the two sentences in the beside run and say where each was produced, which function produced both, and why the cell in the sentence changes when the store is emptied.
- Given the four rows the live runs left, say which are refusals, at which moment each was refused, what the step row shares with its plan row, and why the memory table is the same size on both sides of every one of them.
Exercise 1 — a hundred ticks late. The stale mode takes the later tick as a flag. Run Halla's proposal at 2400 against a reading at 2500 and predict, before running, what every check says and what the sixth check's reason would read if the cap were 99.
Six yeses, because a hundred ticks is inside the cap:
$ go run ./cmd/decide -mode stale -who Halla -now 2400 -at 2500 | tail -10
# check at tick 2400 at tick 2500
1 shape yes yes
2 verb yes yes
3 grounding yes yes
4 law yes yes
5 reach yes yes
6 freshness yes yes
the seam accepted accepted
the same 144 bytes, asked at tick 2400: accepted at tick 2400 and accepted at tick 2500
With -stale 99 the sixth check refuses with asked at tick 2400,
and it is tick 2500: 100 ticks old, and the cap is 99, and the header says the
cap is off the flag and not the file's 200. The reading at 2500 shows Halla on the
same cell with fewer grams, which no check reads, because nothing in the plan
named a number of grams.
Exercise 2 — the errand at ten grams. Run the bench's errand with the flag's default of ten grams and predict, from the fifth check, whether the hand is dispatched, how many grams cross, and why the number that crosses is not the number the plan named.
$ go run ./cmd/decide -mode dispatch -who Halla -now 2400 -errand | tail -14 | head -9
2 hand 10 grams, 2 Ander 2440 yes, yes 40 40 0 0 the store went from 102.4989 to 87.7989 grams
3 go to 8,5 2480 yes, yes 40 40 0 24 10 turns, 30 walks: went from 7,2 to 7,3
120 intents posted at the boundary, 120 taken out of the slot, 0 ticks ran the habit, over the plan's 120 ticks
what the witness wrote down while the plan ran, in the register the stream is kept in
tick 2407 did went from 9,3 to 7,2
tick 2484 saw Ander came into sight, 0.5 cells off
tick 2479 did handed Ander 20 parcels, 10.0 grams
tick 2493 did went from 7,2 to 7,3
All three steps check and run. The hand is posted for forty ticks, a parcel crosses every two ticks, so twenty parcels of half a gram cross: ten grams, which is the number the plan named only because the table's span for a hand happens to be twenty parcels' worth. Name fifteen and ten still cross; the fifth check asks whether the actor holds what was named and nothing decides how much moves but the span and the row's bite. The store falls by more than ten, because walking and standing are charged too.
Exercise 3 — a clause in the test. The one-clause law in the law package's test forbids one verb for one profile. Change the test's clause to forbid go for the profile settled and predict which of the nine pinned tests fail and what their messages say; then put it back.
One. The fourth test fails at its second assertion, because the expected reason names step 2 and take and the refusal now names step 1 and go; its third assertion, a bandit's plan under a clause about settled people, would still pass, because the profile is wrong for the clause. Nothing else in the package touches the test's law, so the other eight pass, and the bench is unchanged: it hands the fourth check the empty law, and no clause written in a test file reaches a run on this page.
Six checks, four rows, and a law with nothing in it, asked on every one of them. The fourth check takes a law, prints the clause a law names, and on this page no clause spoke; the word settled on every villager's row went into a call that returned without reading it. A file of clauses put behind that interface is a file the check already knows how to ask.