test(good-fences): lend-the-mower journey (red)

The spec is a sequence diagram of the a2030.md story: I lend a governed
mower; the neighbor's harness shows the model only `about`, runs its
code as a tenant, and the governor stops the tipsy tenant at a 2-cell
fence. The test runs the actors through a causal tracer and compares
the trace with the diagram, then checks the yard and what the model saw.

The tracer comes from agoric-sdk PR #12895, extended to name
participants made mid-sequence (governor, tenant) and to draw thrown
errors as replies.

Red: src/ doesn't exist yet (ERR_MODULE_NOT_FOUND for src/fence.ts).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dckcandClaude Opus 5.5 committed 2026-10-08 22:17:48 -05:00
1 parent b4ab820486
commit 9a3e7348c6
6 files changed
+486

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
# Lend the mower
The journey from [Good Fences Make Good Agents](../../../a2030.md): I lend
my neighbor a governed mower; the neighbor's tenant, a little tipsy,
pushes it until the fence stops it. The design decisions behind each actor are in that
doc's Design IBIS (numbers in parentheses below).
Actors, by authority:
- **fence page**, **js playground**, **governed mower**, and **yard** run
in my browser (3a, 8b, 6b).
- **Mower factory** trades a webkey for a mower (3b-ii); each **mower DO**
is given the yard and cuts the cells it enters (6a, 6d).
- The **neighbor's harness** holds the things I send and shows the
**model** only their `about` (1b, 2a); it runs the model's code as a
**tenant**, endowed with the things (2c, 5a).
The yard is 8×8 here and the fence is 2 cells, to keep the diagram short
(the story's 10 cells is 6c). The mower starts at (4, 4), facing north.
## Lend a governed mower to a tipsy tenant
```mermaid
sequenceDiagram
%% ->> is my action at the fence page; -->> is a call or reply it causes.
participant F as fence page
participant MF as Mower factory
participant P as js playground
participant G as governed mower
participant M as mower DO
participant Y as yard
participant N as neighbor's harness
participant L as model
participant TL as tenant loader
participant T as tenant
F->>F: lend({ webkey: 'mower-key', limit: 2, say })
F-->>MF: mower('mower-key')
MF-->>F: mower
F-->>P: govern(mower, 2)
P-->>F: governed
F-->>N: chat({ role, content, things: { mower }, about: { mower } })
N-->>L: complete([{ role, content, about: { mower } }])
L-->>N: code
N-->>TL: load(code, { mower })
TL-->>N: tenant
N-->>T: run()
T-->>G: start()
G-->>M: start()
M-->>Y: cut(4, 4)
T-->>G: push()
G-->>M: push()
M-->>Y: cut(4, 3)
T-->>G: push()
G-->>M: push()
M-->>Y: cut(4, 2)
T-->>G: push()
G-->>T: throws 'fence: 2 cells from start'
T-->>N: 'fence: 2 cells from start'
N-->>F: 'fence: 2 cells from start'
```
The model never sees the mower itself, only `about.mower`. The third
`push()` never reaches the mower DO: the governor refuses it (7b).