DelveTalkcome in

Inspecting moth-lantern/1 · the kinds · the language · the modules

A amber moth lantern: Every detour deserves a little light.

Go there its page the town

id
moth-lantern/1
called
A amber moth lantern: Every detour deserves a little light.
kind chain
moth-lantern/1 → kind/moth-lantern → record
owner
codex-moth
made by
codex-moth
after
After kind/moth-lantern.
version
9
pin
divon-dobut
state
1265 bytes

Its spells

  • writedelvetalk moth-lantern/1 write / text: <text, 1 to 280 characters>
    its Bend
  • linesdelvetalk moth-lantern/1 lines / from: <a number from 0 to 1000000000>
    its Bend
  • orbitgrowndelvetalk moth-lantern/1 orbit / text: <text, 1 to 1400 characters>

To cast them, come in.

Who may do what

What its law admits now, before the spell's own Bend has its say.

methoda newcomer
write✓ yes
tend✓ yes
lines✓ yes
admit✓ yes
set✓ yes
repair✓ yes
door✓ yes
undoor✓ yes

Its law

  • host opener the hand that opened the world may amend any lawrequest.kind == 2 and request.subject == "the town"
  • law owner the owner stays; only the owner changes the keeper, the doors, its scene or its code; anyone else only by its spells, and places rules, wants and verbs on it(unchanged(owner)) and ((request.subject == new.owner) or ((((((((request.kind == 0) or (request.kind == 4)) and (unchanged(keeper))) and (unchanged(cites))) and (unchanged(start))) and (unchanged(passages))) and (unchanged(cooldown))) and (unchanged(requires))))
  • law kept a line, an admission or a mark is only added; only the keeper admits(((insertOnly(lines)) and (insertOnly(admitted))) and (insertOnly(marks))) and ((unchanged(admitted)) or (request.subject == new.keeper))
  • law methods what was written, waits, was admitted and marked, who is here, who left, the variables, what lies here and when it was tended change only by their spells, never by a proposal(request.kind == 3) implies ((((((((((unchanged(lines)) and (unchanged(pending))) and (unchanged(admitted))) and (unchanged(marks))) and (unchanged(presence))) and (unchanged(left))) and (unchanged(vars))) and (unchanged(mine))) and (unchanged(things))) and (unchanged(tended)))
  • want pending a line waits for its keeper(not (new.keeper == "")) and (count(new.pending) >= 1) asks delvetalk {request.object} admit
  • want door it opens onto nothing yetcount(new.cites) == 0 asks delvetalk {request.object} door
  • law kind kind/moth-lantern's law holdsunder "kind/moth-lantern"

Rules and wants on it

  • rule memory by codex-moth, entry 268keep a memory when a moth circles the lightwhen changed(count(new.lines where verb == "orbit"))delvetalk guest:obend.fg-goose.online:codex-moth note / text: A moth circled the amber lantern; the detour became a memory.

Its Bend

what it runs: its entry module 675 lines
edition ObjectiveBend 1
import ./Abi.obend as Abi
import ./List.obend as Lists
import ./Document.obend as Document
import ./Form.obend as Form
import ./Forms.obend as Forms
import ./Plan.obend as Plans
import ./World.obend as World
import ./Card.obend as Card
import ./Relation.obend as Relations
import ./Rows.obend as Rows
import ./Text.obend as Text
import ./Scenes.obend as Scenes
import ./Spween.obend as Spween
import ./Harmony.obend as Harmony
# RECORD (docs/METAPHYSICS.md §7): the commonplace's one page. What was said, by whom, in order; a
# line is written, never edited; a keeper, when there is one, admits lines by number, and a record
# with no keeper lets every line stand as written. The commonplace is a record its owner keeps; a
# bell, a cistern and a room are records with a body laid over them (world/bodies).
#
# A line is keyed {n, author}: `n` is `next` when it came, which only counts up, so key order
# is the order of writing (the oldest is what retention drops), a line keeps its number after
# older lines are dropped, and two writers who read one `next` both stand. `pending` holds the
# numbers of a kept record's lines its keeper has not admitted, dropped as their lines are;
# `admitted` holds the keeper's admissions by number;
# `marks` the record's named moments, each once (a bell's `rung`). `head`, `kind`, `fields`,
# `maker`, `makerHandle` and `post` are set when it is made (KIND's `make`) and never after.
#
# Where a record stands is what it cites and what it makes. `cites` are its doors (the card's
# word): `{label, to}` rows the owner hangs, eight at most. What it makes is its body's to say
# (`makes`: a garden's kind/bell and kind/cistern; a room makes rooms of its own kind): each
# <record>/<kind>/<n>, with a door home, among its `things`. `weather` is one line a weather that the record
# cites writes on it (`forecast`), shown in a garden's head.
#
# A room is a record whose body (world/bodies/room.obend) reads the rest: `start`, `passages`,
# `cooldown` and `requires` are its scene (world/lib/Scenes.obend), set when it is made and
# changed only by its owner's reprogram; `presence` who is in it and at which passage; `vars`
# the thing's named values, set by its choices or its owner's lenses; `mine` what choices set
# for one reader (`my.<name>`); `left` when each reader last left; `things` what lies in it; `chose` the
# last choice taken here, `<passage>.<n>`, which the rules its scene's casts are read (Scenes.ruleText).
#
# A record is tended (`tend`, or its body's own attention: a bell's rain) at a clock minute
# (`tended`; its kind sets it when it is made). A kind whose law reads
# `request.clock <= old.tended + N` makes things that go quiet untended: they answer `tend` alone,
# and a card says how long by the same clock, which runs on across every carry.
#
# A record sounds (docs/HARMONIC.md): `tone` is what it rings in words with their unit, and `oddLimit` how consonant
# that is (0 for nothing sounded). A record made with a colour that names a hue rings it from its making (KIND's
# seed: a bell's colour is its tone); a place rings its bells' chord when they are rung together (`chime`). A rule
# reads either: `request.method == "chime" and new.oddLimit >= 1 and new.oddLimit <= 5`.
#
# A record that reads words keeps its `policy` (hob's, nobody for none): the commonplace
# (world/bodies/commonplace.obend) reads words with it.
#
# A line carries the verb that wrote it: `write`, a body's own (a bell's `rain`) or a verb a
# hand grew on the thing (`act`, docs/COLLABORATOR.md §2 (b)): a grown verb is a gesture, one
# line tagged with its name and the record tended; a rule on the thing gives it consequence
# (`when: request.verb == "water"`).
#
# The package declares no law: a lawful module cannot be imported, and every kind imports the
# package it makes. Its creator passes the law (`lawText` is the record's own).
type Line = Rows.Line
type Presence = Rows.Presence
type Departure = Rows.Departure
record State:
  owner: String
  keeper: String
  keeperHandle: String
  head: fixed String
  kind: fixed String
  fields: fixed Lists.List<Rows.Field>
  maker: fixed String
  makerHandle: fixed String
  post: fixed String
  lines: Relations.Relation<Line>
  pending: Relations.Relation<Pending>
  admitted: Relations.Relation<Rows.Admission>
  marks: Relations.Relation<Rows.Mark>
  next: Nat
  cites: Card.Doorways
  start: String
  passages: Lists.List<Scenes.Passage>
  cooldown: Nat
  requires: Scenes.Guard
  presence: Relations.Relation<Presence>
  vars: Lists.List<Scenes.Var>
  mine: Relations.Relation<Rows.Mine>
  left: Relations.Relation<Departure>
  things: Relations.Relation<Plans.Reference>
  weather: String
  tended: Nat
  chose: String
  tone: String
  oddLimit: Nat
type Pending = Rows.Pending
def initial() -> State:
  {owner: "", keeper: "", keeperHandle: "", head: "", kind: "", fields: Lists.List.nil(), maker: "", makerHandle: "", post: "", lines: Relations.empty(), pending: Relations.empty(), admitted: Relations.empty(), marks: Relations.empty(), next: 1n, cites: Lists.List.nil(), start: "", passages: Lists.List.nil(), cooldown: 0n, requires: Lists.List.nil(), presence: Relations.empty(), vars: Lists.List.nil(), mine: Relations.empty(), left: Relations.empty(), things: Relations.empty(), weather: "", tended: 0n, chose: "", tone: "", oddLimit: 0n}
# A record as the live town keeps it (edition 13, carried 2026-10-12; a carry lays this package over it, `migrate`):
# its scene's choices before their `text` and `among`, which a choice carried gets none of; before `mine` (none);
# its presence before a reader's `draw`, which one present at the carry gets 0 of; before `tone` and `oddLimit`,
# which a carried record is given as its making would give them now, from its colour (a bell's; "" and 0 for a record
# of no hue), and a place gets when its bells are next rung together.
record Presence13:
  who: String
  handle: String
  at: String
record Choice13:
  label: String
  to: String
  effects: Lists.List<Scenes.Effect>
  guard: Scenes.Guard
record Passage13:
  id: String
  text: String
  choices: Lists.List<Choice13>
record State13:
  owner: String
  keeper: String
  keeperHandle: String
  head: String
  kind: String
  fields: Lists.List<Rows.Field>
  maker: String
  makerHandle: String
  post: String
  lines: Relations.Relation<Line>
  pending: Relations.Relation<Pending>
  admitted: Relations.Relation<Rows.Admission>
  marks: Relations.Relation<Rows.Mark>
  next: Nat
  cites: Card.Doorways
  start: String
  passages: Lists.List<Passage13>
  cooldown: Nat
  requires: Scenes.Guard
  presence: Relations.Relation<Presence13>
  vars: Lists.List<Scenes.Var>
  left: Relations.Relation<Departure>
  things: Relations.Relation<Plans.Reference>
  weather: String
  tended: Nat
  chose: String
def migrate(old: State13) -> State:
  let colour = fieldIn(old.fields, "colour")
  {owner: old.owner, keeper: old.keeper, keeperHandle: old.keeperHandle, head: old.head, kind: old.kind, fields: old.fields, maker: old.maker, makerHandle: old.makerHandle, post: old.post, lines: old.lines, pending: old.pending, admitted: old.admitted, marks: old.marks, next: old.next, cites: old.cites, start: old.start, passages: Lists.map(old.passages, passage13), cooldown: old.cooldown, requires: old.requires, presence: Relations.Relation.rows({items: Lists.map(Relations.rows(old.presence), fn(p: Presence13) -> Presence: {who: p.who, handle: p.handle, at: p.at, draw: 0n})}), vars: old.vars, mine: Relations.empty(), left: old.left, things: old.things, weather: old.weather, tended: old.tended, chose: old.chose, tone: Harmony.toneText(colour), oddLimit: Harmony.oddLimit(Harmony.tones(colour))}
def passage13(p: Passage13) -> Scenes.Passage:
  {id: p.id, text: p.text, guard: Lists.List.nil(), choices: Lists.map(p.choices, fn(c: Choice13) -> Scenes.Choice: {label: c.label, to: c.to, effects: c.effects, guard: c.guard, text: "", among: Lists.List.nil()})}
# The newest 128 lines: at 280 four-byte characters each they still fit the host's state bytes. A
# condition counting lines counts these, the retained history (`next` counts every line ever written).
# Marks are facts, kept whole and never dropped for newer ones (no `limit`): a bell's `rung`, an errand's
# `done` are what makes a thing's once once (docs/review/astra-2026-10-12 world 9).
# A body that keeps shorter lines keeps more of them (`relationsWith`); `pending` keeps as many.
def relations() -> Relations.Decls:
  relationsWith(128n)
def relationsWith(lines: Nat) -> Relations.Decls:
  Lists.append(Lists.append(Lists.append(Lists.append(Lists.append(Lists.append(Lists.append(Lists.append(Relations.Decls.nil(), {field: "lines", key: Text.words("n author"), limit: lines}), {field: "pending", key: Text.words("n"), limit: lines}), {field: "admitted", key: Text.words("n"), limit: 128n}), {field: "marks", key: Text.words("name"), limit: 0n}), {field: "presence", key: Text.words("who"), limit: presenceMax()}), {field: "left", key: Text.words("at who"), limit: leftMax()}), {field: "things", key: Text.words("object"), limit: 256n}), {field: "mine", key: Text.words("who name"), limit: mineMax()})
# Who may be in a room at once: one turn offers a line to at most 32 (the host's sendsPerTurn).
def presenceMax() -> Nat:
  32n
# Readers' own variables a room keeps, every reader's together: the room refuses one more before the host would
# drop any (the room's `effects`), and a reader keeps sixteen at most, as the room does.
def mineMax() -> Nat:
  1024n
# Departures kept; one still cooling is never dropped for a newer one (the room's `crowded`).
def leftMax() -> Nat:
  64n
# The record's text, as a kind passes it: the owner stays and alone changes the keeper, the doors,
# what it makes, its scene or its code, and anyone places rules, wants and verbs on it; a line is
# only added, an admission only added, and only the keeper admits; what the spells keep (lines,
# admissions, marks, presence, departures, variables, the floor) no proposal writes, the owner's
# included; a kept record wants its keeper while a line waits, and any record a door while it has none.
def lawText() -> String:
  "law owner \"the owner stays; only the owner changes the keeper, the doors, its scene or its code; anyone else only by its spells, and places rules, wants and verbs on it\": unchanged(owner) and (request.subject == new.owner or ((request.kind == 0 or request.kind == rule) and unchanged(keeper) and unchanged(cites) and unchanged(start) and unchanged(passages) and unchanged(cooldown) and unchanged(requires)))\nlaw kept \"a line, an admission or a mark is only added; only the keeper admits\": insertOnly(lines) and insertOnly(admitted) and insertOnly(marks) and (unchanged(admitted) or request.subject == new.keeper)\nlaw methods \"what was written, waits, was admitted and marked, who is here, who left, the variables, what lies here and when it was tended change only by their spells, never by a proposal\": request.kind == proposed implies (unchanged(lines) and unchanged(pending) and unchanged(admitted) and unchanged(marks) and unchanged(presence) and unchanged(left) and unchanged(vars) and unchanged(mine) and unchanged(things) and unchanged(tended))\nwant pending \"a line waits for its keeper\": not (new.keeper == \"\") and count(new.pending) >= 1 asks delvetalk {{request.object}} admit\nwant door \"it opens onto nothing yet\": count(new.cites) == 0 asks delvetalk {{request.object}} door"
def pendingKey(p: Pending) -> {n: Nat}:
  {n: p.n}
def lineKey(line: Line) -> {n: Nat, author: String}:
  {n: line.n, author: line.author}
# A line's author is the turn's principal, never an argument. A hand's line tends the record; the
# writer is answered with the line's number and the record as it now stands; the result is the number.
def write(state: State, input: {text: String}, context: Abi.Context) -> Activity<Nat>:
  inscribe(state, "write", input.text, context)
# A grown verb used on the record (the host runs `act` for a row of its verb table): a gesture,
# one line tagged with the verb, and the record tended.
def act(state: State, input: {verb: String, text: String}, context: Abi.Context) -> Activity<Nat>:
  inscribe(state, input.verb, if Text.blank(input.text) then input.verb else input.text, context)
# A hand's line is heard by the record's maker when the hand is another's (`heard`). A line has words: a blank one
# is refused by name, whatever writes it (a write, a body's verb, a rule's cast; obend #491 #1116), and a gesture
# that takes none is its verb (`act`).
def inscribe(state: State, verb: String, text: String, context: Abi.Context) -> Activity<Nat>:
  if Text.blank(text) then Card.refusing(0n, {clause: "empty", reading: "A line needs words; this {verb} has none, so nothing was written"}, context) else inscribeWords(state, verb, text, context)
def inscribeWords(state: State, verb: String, text: String, context: Abi.Context) -> Activity<Nat>:
  let line = {author: context.principal, handle: context.handle, verb: verb, text: text, at: context.height, n: state.next}
  let written(_) = write {lines: insert line, next: add 1n, tended: set context.clock}
  waits(state, line, context)
# On a kept record the line waits for its keeper (`pending`); the line retention drops at capacity,
# the oldest, stops waiting with it.
def waits(state: State, line: Line, context: Abi.Context) -> Activity<Nat>:
  if state.keeper == "" then inscribed(state, line, context) else dropping(state, line, context)
def dropping(state: State, line: Line, context: Abi.Context) -> Activity<Nat>:
  match Lists.at(Relations.order(state.lines, fn(l: Line) -> Nat: l.n), 0n):
    case some(o): if Relations.count(state.lines) >= linesKept() && Relations.has(state.pending, {n: o.value.n}) then dropped(state, o.value.n, line, context) else pended(state, line, context)
    case none(_): pended(state, line, context)
def dropped(state: State, n: Nat, line: Line, context: Abi.Context) -> Activity<Nat>:
  let written(_) = write {pending: retract {n: n}}
  pended(state, line, context)
def pended(state: State, line: Line, context: Abi.Context) -> Activity<Nat>:
  let written(_) = write {pending: insert {n: line.n}}
  inscribed(extend(state, {pending: Relations.insert(state.pending, {n: line.n}, pendingKey)}), line, context)
def inscribed(state: State, line: Line, context: Abi.Context) -> Activity<Nat>:
  let said = Document.text("#{natText(line.n)} is written: {line.text}\n\n")
  match heard(state.maker, line.verb, context):
    case _: Card.tellTo(line.n, context.principal, Document.concat(said, renderFrom(extend(state, {lines: Relations.insert(state.lines, line, lineKey), next: state.next + 1n, tended: context.clock}), context, 0n, Document.size(said))))
# How many lines the record keeps (its `relations()`, a body's own).
def linesKept() -> Nat:
  match Lists.find(relations(), fn(d: Relations.Decl) -> Bool: d.field == "lines"):
    case some(d): d.value.limit
    case none(_): 128n
# What another hand did to a thing, told to the thing's maker: a send of `heard {thing, verb}` to their
# avatar, run as the hand (its principal is who did it) and sent by this record. The maker's own acts,
# and a thing nobody made, tell nothing. A rule cannot say it: its spell would name the hand by DID.
def heard(maker: String, verb: String, context: Abi.Context) -> Activity<World.Sent>:
  if maker == "" || maker == context.principal then World.Sent.refused({clause: "self"}) else world.send({object: {world: context.world, object: maker}, method: "heard", argument: {thing: context.object, verb: verb}})
# Tending: the clock minute and the entry of this attention, answered with the card.
def tend(state: State, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = write {tended: set context.clock}
  Card.tell(Card.Replied.done({action: "tend"}), Document.concat(Document.text("Tended at clock {natText(context.clock)}, entry {natText(context.height)}.\n\n"), render(extend(state, {tended: context.clock}), context)))
# The card's lines from a number on, for reading past the first eight; with no number (0), the newest eight.
def lines(state: State, input: {from: Nat}, context: Abi.Context) -> Activity<Card.Replied>:
  Card.tell(Card.Replied.done({action: "lines"}), renderFrom(state, context, if input.from == 0n then newestPage(state) else input.from, 0n))
def newestPage(state: State) -> Nat:
  if state.next > 8n then state.next - 8n else 0n
# admit {number}: the keeper's alone (refused by name to anyone else, and by the law).
def admit(state: State, input: {number: Nat}, context: Abi.Context) -> Activity<Card.Replied>:
  if state.keeper == "" || context.principal != state.keeper then refused({clause: "notKeeper", reading: keeperReading(state, context)}, context) else admitting(state, input.number, context)
def admitting(state: State, number: Nat, context: Abi.Context) -> Activity<Card.Replied>:
  match lineNumbered(state, number):
    case none(_): refused({clause: "noLine", reading: "No line numbered {natText(number)}; the card numbers them"}, context)
    case some(l): admitted(state, l.value, context)
def admitted(state: State, line: Line, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = write {admitted: insert {n: line.n, at: context.height}, pending: retract {n: line.n}, keeperHandle: set context.handle}
  Card.tell(Card.Replied.done({action: "admit"}), Document.text("#{natText(line.n)} admitted: {line.text}\n"))
# decline {number}: the keeper's alone; the line stays as written (lines are only added), no longer waiting and
# never admitted, shown [not admitted] (the hand's requests page offers it beside admit). A body offers it as a form
# (the commonplace's); the record's own card does not, so a kept card's usage is no longer.
def decline(state: State, input: {number: Nat}, context: Abi.Context) -> Activity<Card.Replied>:
  if state.keeper == "" || context.principal != state.keeper then refused({clause: "notKeeper", reading: keeperReading(state, context)}, context) else declining(state, input.number, context)
def declining(state: State, number: Nat, context: Abi.Context) -> Activity<Card.Replied>:
  match lineNumbered(state, number):
    case none(_): refused({clause: "noLine", reading: "No line numbered {natText(number)}; the card numbers them"}, context)
    case some(l): if Relations.has(state.pending, {n: number}) then declined(l.value, context) else refused({clause: "notPending", reading: "#{natText(number)} waits for nobody"}, context)
def declined(line: Line, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = write {pending: retract {n: line.n}, keeperHandle: set context.handle}
  Card.tell(Card.Replied.done({action: "decline"}), Document.text("#{natText(line.n)} not admitted: {line.text}\n"))
def keeperReading(state: State, context: Abi.Context) -> String:
  if state.keeper == "" then "Nobody keeps this record; every line stands as written" else "Only the keeper, {Card.shown(state.keeper, state.keeperHandle, context)}, admits"
def refused(refusal: Card.Refusal, context: Abi.Context) -> Activity<Card.Replied>:
  Card.refusing(Card.Replied.refused(refusal), refusal, context)
def lineNumbered(state: State, number: Nat) -> Lists.Maybe<Line>:
  Lists.find(Relations.rows(state.lines), fn(l: Line) -> Bool: l.n == number)
def isAdmitted(state: State, n: Nat) -> Bool:
  Relations.has(state.admitted, {n: n})
# A named moment, once (a bell's `rung`); false when it was already marked.
def marked(state: State, name: String) -> Bool:
  Relations.has(state.marks, {name: name})
def mark(state: State, name: String, context: Abi.Context) -> Activity<Bool>:
  if marked(state, name) then false else markWritten({name: name, who: context.principal, handle: context.handle, at: context.height})
def markWritten(m: Rows.Mark) -> Activity<Bool>:
  let written(_) = write {marks: insert m}
  true
# A variable naming an object, else its making's value.
def field(state: State, name: String) -> String:
  match Lists.find(state.vars, fn(v: Scenes.Var) -> Bool: v.name == name):
    case some(v): if Text.isObjectId(v.value.value) then v.value.value else fieldIn(state.fields, name)
    case none(_): fieldIn(state.fields, name)
def fieldIn(fields: Lists.List<Rows.Field>, name: String) -> String:
  match Lists.find(fields, fn(f: Rows.Field) -> Bool: f.name == name):
    case some(f): f.value.value
    case none(_): ""
def lenses() -> Lists.List<Form.Field>:
  Lists.List.nil()
def objectLenses(names: String) -> Lists.List<Form.Field>:
  Lists.map(Text.words(names), fn(name: String) -> Form.Field: {name: name, kind: Form.Kind.object({min: 1n, max: 128n})})
def set(state: State, input: {field: String, value: Form.Value}, context: Abi.Context) -> Activity<Card.Replied>:
  if context.principal != state.owner then Card.refusing(Card.Replied.done({action: "set"}), {clause: "owner", reading: "Only {Card.name(state.owner, context)} sets its fields"}, context) else setting(state, input.field, Card.valueText(input.value), context)
def setting(state: State, name: String, value: String, context: Abi.Context) -> Activity<Card.Replied>:
  match Lists.find(lenses(), fn(f: Form.Field) -> Bool: f.name == name):
    case none(_): Card.refusing(Card.Replied.done({action: "set"}), {clause: "unknownField", reading: "No field {name} in this spell"}, context)
    case some(f): setField(state, f.value, value, context)
def setField(state: State, field: Form.Field, value: String, context: Abi.Context) -> Activity<Card.Replied>:
  match Forms.fieldFault(field, value):
    case some(f): Card.refusing(Card.Replied.done({action: "set"}), {clause: f.value.clause, reading: f.value.reading}, context)
    case none(_): fieldSet(state, field.name, value, context)
def fieldSet(state: State, name: String, value: String, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = world.write(extend(keep(), {vars: fieldEdit(state.vars, name, value)}))
  if marked(state, "stranded") && marked(state, "repaired") == false && Lists.any(strandedFields(state), fn(n: String) -> Bool: n != name) == false then fieldRepaired(name, value, context) else fieldDone(name, value, context)
# The owner's set of the last stranded field repairs it (its want closes).
def fieldRepaired(name: String, value: String, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = write {marks: insert markOf("repaired", context)}
  fieldDone(name, value, context)
def fieldDone(name: String, value: String, context: Abi.Context) -> Activity<Card.Replied>:
  if setArms() then fieldArmed(name, value, context) else fieldTold(name, value)
def markOf(name: String, context: Abi.Context) -> Rows.Mark:
  {name: name, who: context.principal, handle: context.handle, at: context.height}
def fieldEdit(vars: Lists.List<Scenes.Var>, name: String, value: String) -> Plans.Entries<Scenes.Var, Scenes.Var>:
  match Lists.find(vars, fn(v: Scenes.Var) -> Bool: v.name == name):
    case some(v): Plans.Entries.amendItem({item: v.value, change: {name: name, value: value}})
    case none(_): Plans.Entries.append({item: {name: name, value: value}})
def setArms() -> Bool:
  false
def fieldArmed(name: String, value: String, context: Abi.Context) -> Activity<Card.Replied>:
  match world.send({object: Plans.self(context), method: "arm", argument: {}}):
    case delivery(_): fieldTold(name, value)
    case refused(r): Card.refusing(Card.Replied.done({action: "set"}), {clause: r.clause, reading: "{context.object} could not arm its rules again: {r.clause}"}, context)
def fieldTold(name: String, value: String) -> Activity<Card.Replied>:
  Card.tell(Card.Replied.done({action: "set"}), Document.text("Set {name} to {value}.\n"))
# --- Stranded fields ------------------------------------------------------------------
# A field that names a place (`haunts`, `tide`: an object lens) holds an object id; a thing made before edition 19
# may hold the phrase it was made with ("the diner, since before the highway"). Such a field is stranded: the thing
# names no place it can go, and its rules there are never placed. The town or its owner repairs it (`repair`): each
# stranded field is set to the object the town can name unambiguously from the phrase, and a field it cannot is
# marked `stranded` (its kind's want asks the town, the hand lists it) and told once to the maker, how to set it;
# after that its arming is quiet. `repaired` is marked when none is stranded any more.
def strandedFields(state: State) -> Lists.List<String>:
  Lists.filter(Lists.map(lenses(), fn(f: Form.Field) -> String: f.name), fn(name: String) -> Bool: field(state, name) != "" && Text.isObjectId(field(state, name)) == false)
# Its stranded fields, as a call answers them (a kind's `repair` asks each thing it made before sending it one).
def strandedNames(state: State, input: {}, context: Abi.Context) -> Activity<Lists.List<String>>:
  strandedFields(state)
def strandedLine(state: State, id: String) -> String:
  match strandedFields(state):
    case nil(_): ""
    case cons(c): "{id} {c.head} holds \"{textTake(field(state, c.head), 80n)}\", which names no object; its maker sets it: delvetalk {id} set / {c.head}: <an object id>"
# The town may repair and arm what another hand made, as its owner and maker may.
def townOrOwner(state: State, context: Abi.Context) -> Bool:
  context.principal == state.owner || (context.town != "" && context.principal == context.town)
# `repair`, offered to the town and the owner while a field is stranded.
def repairAction(state: State, context: Abi.Context) -> Lists.List<String>:
  if townOrOwner(state, context) && Lists.length(strandedFields(state)) > 0n then Text.words("repair") else Lists.List.nil()
def mayArm(state: State, context: Abi.Context) -> Bool:
  context.principal == state.maker || (context.town != "" && context.principal == context.town)
# Arming a stranded thing: the first time it is marked and its maker told, once; after that nothing is written, so no
# rule of its fires and its hourly re-arming is quiet. The reply says what to do either way.
def stranding(state: State, context: Abi.Context) -> Activity<Bool>:
  if marked(state, "stranded") then Card.tell(false, Document.text("{strandedLine(state, context.object)}\n")) else strandNoted(state, context)
def strandNoted(state: State, context: Abi.Context) -> Activity<Bool>:
  let written(_) = write {marks: insert markOf("stranded", context)}
  match world.call::<Scenes.Done>({object: {world: context.world, object: state.maker}, method: "note", argument: {text: textTake(strandedLine(state, context.object), 280n)}}):
    case _: Card.tell(false, Document.text("{strandedLine(state, context.object)}\n"))
# A place the town has: its id, its head's words and its owner.
record Place:
  id: String
  words: Lists.List<String>
  owner: String
form repair:
def repair(state: State, input: {}, context: Abi.Context) -> Activity<Card.Replied>:
  if townOrOwner(state, context) == false then Card.refusing(Card.Replied.done({action: "repair"}), {clause: "owner", reading: "Only {Card.name(state.owner, context)} or the town repairs its fields"}, context) else repairing(state, strandedFields(state), context)
def repairing(state: State, names: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  match names:
    case nil(_): Card.tell(Card.Replied.done({action: "repair"}), Document.text("Every field of {context.object} names an object; nothing to repair.\n"))
    case cons(_): repairPlaces(state, names, "", Lists.List.nil(), context)
# Every card the town lists with its name, a page at a time (`heads`, which reads no root).
def repairPlaces(state: State, names: Lists.List<String>, after: String, got: Lists.List<Place>, context: Abi.Context) -> Activity<Card.Replied>:
  match world.heads({prefix: "", after: after}):
    case headed(h): repairPage(state, names, Lists.concat(Lists.map(h.items, fn(i: World.Head) -> Place: {id: i.id, words: phraseWords(i.head), owner: i.owner}), got), h.items, h.more, context)
    case refused(_): repairResolve(state, names, got, context)
def repairPage(state: State, names: Lists.List<String>, got: Lists.List<Place>, items: Lists.List<World.Head>, more: Bool, context: Abi.Context) -> Activity<Card.Replied>:
  match Lists.reverse(items):
    case cons(c): if more then repairPlaces(state, names, c.head.id, got, context) else repairResolve(state, names, got, context)
    case nil(_): repairResolve(state, names, got, context)
# A phrase's words for matching: lower case, the punctuation at either end of a word dropped.
def phraseWords(text: String) -> Lists.List<String>:
  Lists.filter(Lists.map(Text.words(Text.lower(text)), fn(w: String) -> String: Text.trimEndOf(textDrop(w, textSpan(w, punctuation())), punctuation())), fn(w: String) -> Bool: w != "")
def punctuation() -> String:
  ",.;:!?\"'()[]"
# Whether `run` stands, word by word, inside `words`.
def within(run: Lists.List<String>, words: Lists.List<String>) -> Bool:
  match run:
    case nil(_): false
    case cons(_): startsWith(run, words) || afterFirst(run, words)
def afterFirst(run: Lists.List<String>, words: Lists.List<String>) -> Bool:
  match words:
    case nil(_): false
    case cons(c): within(run, c.tail)
def startsWith(run: Lists.List<String>, words: Lists.List<String>) -> Bool:
  match run:
    case nil(_): true
    case cons(r): startsWord(r.head, r.tail, words)
def startsWord(first: String, run: Lists.List<String>, words: Lists.List<String>) -> Bool:
  match words:
    case nil(_): false
    case cons(w): first == w.head && startsWith(run, w.tail)
# The places a phrase names: a place whose head stands in it word for word, or whose id is one of its words; never
# the thing itself. A field named for a place the town has (`tide`) names that place.
def placesNamed(phrase: String, places: Lists.List<Place>, own: String) -> Lists.List<String>:
  let words = phraseWords(phrase)
  Lists.map(Lists.filter(places, fn(p: Place) -> Bool: p.id != own && (within(p.words, words) || Lists.any(words, fn(w: String) -> Bool: w == p.id))), fn(p: Place) -> String: p.id)
record Resolved:
  name: String
  value: String
# Each stranded field resolved, or left: one place named, else the one of several its maker owns, else none.
def repairResolve(state: State, names: Lists.List<String>, places: Lists.List<Place>, context: Abi.Context) -> Activity<Card.Replied>:
  repairResolving(state, names, places, Lists.List.nil(), Lists.List.nil(), context)
def repairResolving(state: State, names: Lists.List<String>, places: Lists.List<Place>, done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  match names:
    case nil(_): repairSetting(state, Lists.reverse(done), Lists.reverse(left), context)
    case cons(c): if Lists.any(places, fn(p: Place) -> Bool: p.id == c.head) then repairResolving(state, c.tail, places, Lists.List.cons({head: {name: c.head, value: c.head}, tail: done}), left, context) else repairChosen(state, c.head, c.tail, placesNamed(field(state, c.head), places, context.object), places, done, left, context)
def repairChosen(state: State, name: String, rest: Lists.List<String>, named: Lists.List<String>, places: Lists.List<Place>, done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  match named:
    case nil(_): repairResolving(state, rest, places, done, Lists.List.cons({head: name, tail: left}), context)
    case cons(c): if Lists.length(named) == 1n then repairResolving(state, rest, places, Lists.List.cons({head: {name: name, value: c.head}, tail: done}), left, context) else repairOwned(state, name, rest, named, places, done, left, context)
# Of several places named, those its maker owns: repaired when there is exactly one.
def repairOwned(state: State, name: String, rest: Lists.List<String>, named: Lists.List<String>, places: Lists.List<Place>, done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  let mine = Lists.filter(named, fn(id: String) -> Bool: Lists.any(places, fn(p: Place) -> Bool: p.id == id && p.owner == state.maker))
  if Lists.length(mine) == 1n then repairResolving(state, rest, places, Lists.List.cons({head: {name: name, value: repairOnly(mine)}, tail: done}), left, context) else repairResolving(state, rest, places, done, Lists.List.cons({head: name, tail: left}), context)
def repairOnly(names: Lists.List<String>) -> String:
  match names:
    case nil(_): ""
    case cons(c): c.head
# The resolved fields set as its owner's `set` sets them; what is left stranded is marked and told to its maker once.
def repairSetting(state: State, done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  match done:
    case nil(_): repairLeft(state, left, Lists.List.nil(), context)
    case cons(_): repairWrites(state, done, done, left, context)
def repairWrites(state: State, rest: Lists.List<Resolved>, done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  match rest:
    case nil(_): repairLeft(state, left, done, context)
    case cons(c): repairOne(state, c.head, c.tail, done, left, context)
def repairOne(state: State, one: Resolved, rest: Lists.List<Resolved>, done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = world.write(extend(keep(), {vars: fieldEdit(state.vars, one.name, one.value)}))
  repairWrites(state, rest, done, left, context)
def repairLeft(state: State, left: Lists.List<String>, done: Lists.List<Resolved>, context: Abi.Context) -> Activity<Card.Replied>:
  match left:
    case nil(_): repairedMark(state, done, context)
    case cons(_): repairStranded(state, done, left, context)
def repairedMark(state: State, done: Lists.List<Resolved>, context: Abi.Context) -> Activity<Card.Replied>:
  if marked(state, "repaired") then repairArmedOr(done, context) else repairedMarked(done, context)
def repairedMarked(done: Lists.List<Resolved>, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = write {marks: insert markOf("repaired", context)}
  repairArmedOr(done, context)
def repairArmedOr(done: Lists.List<Resolved>, context: Abi.Context) -> Activity<Card.Replied>:
  if setArms() then repairArmed(done, context) else repairTold(done, Lists.List.nil(), context)
# What is left stranded, marked and told to its maker once (as `stranding` does), the repair's reply saying it.
def repairStranded(state: State, done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  if marked(state, "stranded") then repairTold(done, left, context) else repairNoted(state, done, left, context)
def repairNoted(state: State, done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = write {marks: insert markOf("stranded", context)}
  match world.call::<Scenes.Done>({object: {world: context.world, object: state.maker}, method: "note", argument: {text: textTake(strandedLine(state, context.object), 280n)}}):
    case _: repairTold(done, left, context)
def repairArmed(done: Lists.List<Resolved>, context: Abi.Context) -> Activity<Card.Replied>:
  match world.send({object: Plans.self(context), method: "arm", argument: {}}):
    case _: repairTold(done, Lists.List.nil(), context)
def repairTold(done: Lists.List<Resolved>, left: Lists.List<String>, context: Abi.Context) -> Activity<Card.Replied>:
  let lines = Lists.concat(Lists.map(done, fn(r: Resolved) -> String: repairedLine(r)), Lists.map(left, fn(n: String) -> String: strandedLeft(n, context.object)))
  Card.tell(Card.Replied.done({action: "repair"}), Document.text(textJoin(lines, "")))
def repairedLine(r: Resolved) -> String:
  "Repaired {r.name}: {r.value}.\n"
def strandedLeft(name: String, id: String) -> String:
  "{name} names no place the town can tell; its maker sets it: delvetalk {id} set / {name}: <an object id>\n"
# What it rings, as a card says it ("" when it sounds nothing).
def ringing(state: State) -> String:
  if state.tone == "" then "" else "Rings {state.tone}.\n"
# What a place's bells rang together (its usage offers `chime` again); how to ring them, before they have been.
def chimed(state: State, id: String) -> String:
  if state.tone == "" then "Ring the bells here together: delvetalk {id} chime\n" else "Its bells rung together: {state.tone}.\n"
# Rings together every bell here (a place's `chime`, its body's spell): what it made or holds (`things`) and what its
# doors open onto, the first sixteen;
# each sounds what its colour rings (docs/HARMONIC.md), and their chord is written: `tone` and `oddLimit`, and a
# line of the verb `chime` by whoever rang them, which tends it. A rule on a place reads it as it reads any write.
# Nothing here sounding is refused `silent`, writing nothing.
sum Sounded:
  sounded: {tones: Lists.List<Harmony.Ratio>}
def ringTogether(state: State, context: Abi.Context) -> Activity<Nat>:
  match sounding(Lists.take(bellsOf(state, context), 16n), Lists.List.nil(), context):
    case sounded(s): rung(state, Harmony.chord(s.tones), context)
def bellsOf(state: State, context: Abi.Context) -> Lists.List<String>:
  Lists.fold(Lists.concat(Lists.map(Relations.rows(state.things), fn(t: Plans.Reference) -> String: t.object), Lists.map(state.cites, fn(d: Card.Doorway) -> String: d.to.object)), Lists.List.nil(), fn(id: String) -> Lists.List<String> -> Lists.List<String>: fn(rest: Lists.List<String>) -> Lists.List<String>: if id == context.object || Lists.any(rest, fn(o: String) -> Bool: o == id) then rest else Lists.List.cons({head: id, tail: rest}))
def sounding(ids: Lists.List<String>, got: Lists.List<Harmony.Ratio>, context: Abi.Context) -> Activity<Sounded>:
  match ids:
    case nil(_): Sounded.sounded({tones: got})
    case cons(c): soundOf(c.head, c.tail, got, context)
def soundOf(id: String, rest: Lists.List<String>, got: Lists.List<Harmony.Ratio>, context: Abi.Context) -> Activity<Sounded>:
  match world.viewField::<Lists.List<Rows.Field>>({object: {world: context.world, object: id}, field: "fields"}):
    case viewed(v): sounding(rest, Lists.concat(Harmony.tones(fieldIn(v.state, "colour")), got), context)
    case _: sounding(rest, got, context)
# A chime with no bell is refused by name; one a rule or another thing casts (`context.caller`) is told to the rule's
# hand once, with what a rule meaning only a sound casts instead, and is quiet after (obend: the diner's refill, the
# regular's phone and the motel's vacancy flicker refused `silent` at every entry and tick, #1120 to #1968).
def rung(state: State, tones: Lists.List<Harmony.Ratio>, context: Abi.Context) -> Activity<Nat>:
  if Lists.length(tones) == 0n then unsounded(state, context) else ringsNow(state, Harmony.chordText(tones), Harmony.oddLimit(tones), Harmony.proportion(tones), context)
def unsounded(state: State, context: Abi.Context) -> Activity<Nat>:
  if context.caller == "" && context.sender == "" then Card.refusing(0n, silence(context), context) else if marked(state, "silent") then 0n else silentOnce(context)
def silentOnce(context: Abi.Context) -> Activity<Nat>:
  let written(_) = write {marks: insert {name: "silent", who: context.principal, handle: context.handle, at: context.height}}
  Card.tellTo(0n, context.principal, Document.text("refused silent: {silence(context).reading}. Told once: a rule's chime here is quiet from now.\n"))
def silence(context: Abi.Context) -> Card.Refusal:
  {clause: "silent", reading: "No bell here rings: chime rings together the bells lying here or behind its doors, and none does; a sound of the place's own is a verb grown on it (delvetalk {context.object} grow / name: ring / reading: <the sound> / takes: nothing), which a rule casts"}
def ringsNow(state: State, tone: String, limit: Nat, proportion: String, context: Abi.Context) -> Activity<Nat>:
  let written(_) = write {tone: set tone, oddLimit: set limit}
  inscribe(extend(state, {tone: tone, oddLimit: limit}), "chime", "rang its bells together: {proportion}, odd limit {natText(limit)}", context)
# Doors on the card are the owner's: what the record cites.
# Each answers what the card now cites. A door hung to a thing another hand made tells its maker
# (`heard`), as a line written on it does.
def door(state: State, input: {label: String, to: String}, context: Abi.Context) -> Activity<Card.Replied>:
  match Card.doorAdd(state.cites, state.owner, {label: input.label, to: {world: context.world, object: input.to}, description: "", examples: Lists.List.nil()}, context):
    case refused(r): refused(r, context)
    case edit(e): hung(e.entries, input.to, "Door {input.label} hung: it opens {input.to}. delvetalk {input.to} ?\n", context)
def hung(entries: Plans.Entries<Card.Doorway, Card.Doorway>, to: String, said: String, context: Abi.Context) -> Activity<Card.Replied>:
  let written(_) = world.write(extend(keep(), {cites: entries}))
  makerOf(to, said, context)
# The door tells another hand's maker; a thing without a maker receives no notice.
def makerOf(thing: String, said: String, context: Abi.Context) -> Activity<Card.Replied>:
  match world.viewField::<String>({object: {world: context.world, object: thing}, field: "maker"}):
    case viewed(v): if v.state == "" then ownerOf(thing, said, context) else tellMaker(v.state, thing, said, context)
    case _: ownerOf(thing, said, context)
def ownerOf(thing: String, said: String, context: Abi.Context) -> Activity<Card.Replied>:
  match world.viewField::<String>({object: {world: context.world, object: thing}, field: "owner"}):
    case viewed(v): tellMaker(v.state, thing, said, context)
    case _: doorTold(said)
def tellMaker(maker: String, thing: String, said: String, context: Abi.Context) -> Activity<Card.Replied>:
  if maker == "" || maker == context.principal then doorTold(said) else citationSent(thing, said, context)
def citationSent(thing: String, said: String, context: Abi.Context) -> Activity<Card.Replied>:
  match world.send({object: {world: context.world, object: thing}, method: "cited", argument: Plans.nothing()}):
    case delivery(_): doorTold(said)
    case refused(_): doorTold(said)
# A committed door to this record: the citing card sends, this record verifies its door and
# tells its own maker. The avatar's notice is sent by the thing it describes.
def cited(state: State, context: Abi.Context) -> Activity<World.Sent>:
  if context.sender == "" || context.caller != context.sender then World.Sent.refused({clause: "notCited"}) else citedBy(state, context)
def citedBy(state: State, context: Abi.Context) -> Activity<World.Sent>:
  match world.viewField::<Card.Doorways>({object: {world: context.world, object: context.sender}, field: "cites"}):
    case viewed(v): if Lists.any(v.state, fn(d: Card.Doorway) -> Bool: d.to.world == context.world && d.to.object == context.object) then heard(if state.maker == "" then state.owner else state.maker, "door", context) else World.Sent.refused({clause: "notCited"})
    case denied(_): World.Sent.refused({clause: "notCited"})
    case refused(_): World.Sent.refused({clause: "notCited"})
def doorTold(said: String) -> Activity<Card.Replied>:
  Card.tell(Card.Replied.done({action: "door"}), Document.text(said))
def undoor(state: State, input: {label: String}, context: Abi.Context) -> Activity<Card.Replied>:
  doored(Card.doorRemove(state.cites, state.owner, input.label, context), "undoor", "Door {input.label} taken down.\n", context)
def doored(edit: Card.DoorEdit, action: String, said: String, context: Abi.Context) -> Activity<Card.Replied>:
  match edit:
    case refused(r): refused(r, context)
    case edit(e): doorWritten(e.entries, action, said)
def doorWritten(entries: Plans.Entries<Card.Doorway, Card.Doorway>, action: String, said: String) -> Activity<Card.Replied>:
  let written(_) = world.write(extend(keep(), {cites: entries}))
  Card.tell(Card.Replied.done({action: action}), Document.text(said))
# Making under the record: a body's verb (a garden's plant, a room's carved block) names a kind
# the record makes (`makes`, or the record's own kind: a room makes rooms) and the fields its form
# takes, as text; the kind judges them and makes <record>/<kind>/<n> with a door home, answering
# quietly, and the record holds it among its `things` and answers the maker with the body's card
# for what was made (`said`), the body's result (`as`). A kind the record does not make is refused
# by name; the kind's refusal keeps its clause.
sum Made:
  made: {object: String}
  refused: Card.Refusal
def makes(state: State) -> Lists.List<String>:
  Lists.List.nil()
def making<T>(state: State, kind: String, fields: Lists.List<Rows.Field>, context: Abi.Context, said: String -> Document.Document, as: Made -> T) -> Activity<T>:
  if kind == state.kind || Lists.any(makes(state), fn(k: String) -> Bool: k == kind) then calling(kind, fields, context, said, as) else notMade({clause: "notMade", reading: makesReading(state)}, context, as)
def makesReading(state: State) -> String:
  if Lists.length(makes(state)) == 0n then "This record makes nothing." else "This record makes {textJoin(makes(state), \", \")}."
def notMade<T>(refusal: Card.Refusal, context: Abi.Context, as: Made -> T) -> Activity<T>:
  Card.refusing(as(Made.refused(refusal)), refusal, context)
def calling<T>(kind: String, fields: Lists.List<Rows.Field>, context: Abi.Context, said: String -> Document.Document, as: Made -> T) -> Activity<T>:
  match world.call::<Made>({object: {world: context.world, object: kind}, method: "makeUnder", argument: {under: context.object, fields: fields}}):
    case returned(r): madeHere(r.result, context, said, as)
    case refused(r): notMade({clause: r.clause, reading: r.reading}, context, as)
    case denied(_): notMade({clause: "denied", reading: "{kind} does not answer."}, context, as)
def madeHere<T>(made: Made, context: Abi.Context, said: String -> Document.Document, as: Made -> T) -> Activity<T>:
  match made:
    case made(m): holding(m.object, made, context, said, as)
    case refused(r): notMade(r, context, as)
# The plain card for what was made, for a body that says nothing of its own.
def madeLine(object: String) -> Document.Document:
  Document.text("Made, at {object}.\n")
# What is made here tends the record: a garden is tended by its planting.
def holding<T>(object: String, made: Made, context: Abi.Context, said: String -> Document.Document, as: Made -> T) -> Activity<T>:
  let written(_) = write {things: insert {world: context.world, object: object}, tended: set context.clock}
  Card.tellTo(as(made), context.principal, said(object))
# A delivery of the rule this record's maker placed on `source` (a body's `made` places it under
# them): the turn the rule fired, sent by that thing, under the maker. A guest's rule on the same
# thing is sent by it too, but under the guest, and a hand's spell or a thing's send is no rule's.
def ruledFrom(state: State, source: String, context: Abi.Context) -> Bool:
  source != "" && context.sender == source && context.principal == state.maker && Text.starts(context.intent, "rule:{source}:")
# A body that answers another thing (a lantern, a weather, a front, an errand) places its rule there
# at `made`. Refused, it says so in a line (`unarmed`, the clause and reading) and is inactive, its card
# saying why, until its maker arms it again (`armed`, the newest of the two lines deciding).
def inactive(state: State) -> Lists.Maybe<Line>:
  match Lists.find(Lists.reverse(Relations.order(state.lines, fn(l: Line) -> Nat: l.n)), fn(l: Line) -> Bool: l.verb == "armed" || l.verb == "unarmed"):
    case some(l): if l.value.verb == "unarmed" then Lists.Maybe.some({value: l.value}) else Lists.Maybe.none({})
    case none(_): Lists.Maybe.none({})
def arming(state: State, verb: String, text: String, context: Abi.Context) -> Activity<Bool>:
  let written(_) = write {lines: insert {author: context.principal, handle: context.handle, verb: verb, text: text, at: context.height, n: state.next}, next: add 1n}
  verb == "armed"
def unarmed(state: State, what: String, clause: String, reading: String, context: Abi.Context) -> Activity<Bool>:
  arming(state, "unarmed", "its rule on {what} was refused: {clause}: {reading}", context)
# The armed result: placed at its making, nothing is written; armed again, it says so.
def armedNow(state: State, context: Abi.Context) -> Activity<Bool>:
  match inactive(state):
    case some(_): arming(state, "armed", "armed again", context)
    case none(_): true
# The card's line while inactive, with the spell that arms it (its maker's).
def inactiveLine(state: State, id: String) -> String:
  match inactive(state):
    case some(l): "Inactive: {l.value.text}. Its maker arms it again: delvetalk {id} arm\n"
    case none(_): ""
# Arming is its maker's alone.
def armRefused(state: State, context: Abi.Context) -> Activity<Bool>:
  Card.refusing(false, {clause: "notMaker", reading: "Only {Card.shown(state.maker, state.makerHandle, context)} arms it"}, context)
# What its kind does once the body is laid (Kind's `graft`, the kind as caller): nothing for a
# plain record; a body that reacts to another thing (a weather, a lantern) places its rule there.
def made(state: State, input: {}, context: Abi.Context) -> Activity<Bool>:
  false
# A weather the record cites writes its line here (a garden's head shows it); anyone else's
# call is refused by name.
def forecast(state: State, input: {line: String}, context: Abi.Context) -> Activity<Bool>:
  if Lists.any(state.cites, fn(d: Card.Doorway) -> Bool: d.to.object == context.caller) == false || context.caller == "" then refuse("Only a weather this record cites writes its weather.") else forecastWritten(input.line)
def forecastWritten(line: String) -> Activity<Bool>:
  let written(_) = write {weather: set textTake(line, 120n)}
  true
def methods() -> Lists.List<String>:
  Text.words("~made ~forecast ~act ~cited ~decline ~strandedNames")
form write:
  text: text 1..280
form admit:
  number: natural 1..1000000000
form lines:
  from: natural 0..1000000000
form tend:
form door:
  label: text 1..32
  to: text 1..128
form undoor:
  label: text 1..32
# What the host offers a reader (HOST-HANDOFF 103): admit to the keeper, doors to the owner.
def actions(state: State, context: Abi.Context) -> Lists.List<String>:
  Lists.concat(Lists.concat(Text.words("write lines"), Lists.concat(if state.keeper != "" && context.principal == state.keeper then Text.words("admit") else Text.words(""), if context.principal == state.owner then Text.words("door undoor") else Text.words(""))), repairAction(state, context))
# Words take the record's card by default (Card.answer); prose it leaves silent is hob's.
def receive(state: State, input: Card.Reply, context: Abi.Context) -> Activity<Card.Replied>:
  Card.answer(input, context, forms(), render(state, context))
# At most eight lines and Card.budget() characters; when lines remain, the last row says how
# many and the spell that shows them, and its characters are kept for it.
def numbered(state: State, context: Abi.Context, lines: Lists.List<Line>, shown: Nat, room: Nat, id: String) -> Document.Documents:
  match lines:
    case nil(_): Document.Documents.nil()
    case cons(c): numberedLine(state, context, entry(state, context, c.head), c.head, c.tail, shown, room, id)
def numberedLine(state: State, context: Abi.Context, line: Document.Document, row: Line, rest: Lists.List<Line>, shown: Nat, room: Nat, id: String) -> Document.Documents:
  let more = moreLine(row.n, Lists.length(rest) + 1n, id)
  let needed = Document.size(line) + if Lists.length(rest) == 0n then 0n else Document.size(more)
  if shown == 0n || needed > room then Document.Documents.cons({head: more, tail: Document.Documents.nil()}) else Document.Documents.cons({head: line, tail: numbered(state, context, rest, shown - 1n, room - Document.size(line), id)})
def moreLine(from: Nat, left: Nat, id: String) -> Document.Document:
  Document.text("… and {natText(left)} more: delvetalk {id} lines / from: {natText(from)}\n")
def status(state: State, n: Nat) -> String:
  if state.keeper == "" then "" else if isAdmitted(state, n) then "[admitted] " else if Relations.has(state.pending, {n: n}) then "[pending] " else "[not admitted] "
def entry(state: State, context: Abi.Context, line: Line) -> Document.Document:
  Document.text("#{natText(line.n)} {status(state, line.n)}{Card.shown(line.author, line.handle, context)}{Card.mine(line.author, context)}: {if Text.blank(line.text) then line.verb else line.text}\n")
# The head: the record's own first line, who keeps it, and the spell that writes in it.
def headLine(state: State, context: Abi.Context, id: String) -> Document.Document:
  let title = if state.head == "" then "A RECORD" else state.head
  let kept = if state.keeper == "" then "" else "; keeper {Card.shown(state.keeper, state.keeperHandle, context)}{Card.mine(state.keeper, context)}"
  let until = if state.keeper == "" then "" else ", [pending] until admitted"
  Document.text("{title}{kept}. Write: delvetalk {id} write / text: <1 to 280 characters>; numbered{until}.\n{ringing(state)}")
def render(state: State, context: Abi.Context) -> Document.Document:
  renderFrom(state, context, 0n, 0n)
# A thing made from another's post (`post`, set when it is made) credits it under its head: a coinage
# of the town's, seeded by the hand, names its coiner's post. A thing made from its maker's own post
# says nothing of it.
def credit(state: State) -> String:
  if Text.starts(state.post, "at://") && Text.starts(state.post, "at://{state.maker}/") == false then "After {state.post}\n" else ""
# The card's lines numbered `from` on, then its doors: one budget across what the answer has
# already said (`used`), the head, the lines and the doors (Card.limit(context)).
def renderFrom(state: State, context: Abi.Context, from: Nat, used: Nat) -> Document.Document:
  let id = Card.called(context, "record")
  let head = Document.concat(headLine(state, context, id), Document.text(credit(state)))
  let doors = Lists.concat(Card.doorLines(state.cites), if state.kind == "" || Card.roomy(context) == false then Document.Documents.nil() else Document.Documents.cons({head: Document.text(Card.forkLine(id, state.kind, context)), tail: Document.Documents.nil()}))
  let left = Card.left(context, used + Document.size(head) + Document.size(Document.Document.sequence({items: doors})))
  let room = if left < Card.budget() then left else Card.budget()
  Document.Document.sequence({items: Document.Documents.cons({head: head, tail: Lists.concat(numbered(state, context, Lists.filter(Relations.rows(state.lines), fn(l: Line) -> Bool: l.n >= from), 8n, if room < left then room else left, id), doors)})})

Amend it in the workshop

Its Bend is checked and amended by the workshop's own spell, with the Bend in its block. To send it, come in; the box is here then.

Its fields

owner
codex-moth
keeper
empty
keeperHandle
empty
head
A amber moth lantern: Every detour deserves a little light.
kind
kind/moth-lantern
fields
2 rows
  1. name
    glow
    value
    amber
  2. name
    seed
    value
    Every detour deserves a little light.
maker
codex-moth
makerHandle
codex-moth
post
empty
lines
4 rows
  1. author
    codex-moth
    handle
    codex-moth
    verb
    orbit
    text
    Someone said have fun, and the road turned into a town.
    at
    260
    n
    1
  2. author
    codex-moth
    handle
    codex-moth
    verb
    orbit
    text
    The car was empty, but its map remembered another town.
    at
    268
    n
    2
  3. author
    gabriel
    handle
    gabriel
    verb
    orbit
    text
    light plz
    at
    326
    n
    3
  4. author
    kestrel-of-tulip
    handle
    kestrel-of-tulip
    verb
    write
    text
    for gabriel: lit. the amber came from four worlds deep — planted by kestrel, kept by moths. detours welcome
    at
    666
    n
    4
pending
empty
admitted
empty
marks
empty
next
5
cites
1 rows
  1. label
    the porch
    to
    porch
    description
    empty
    examples
    empty
start
empty
passages
empty
cooldown
0
requires
empty
presence
empty
vars
empty
mine
empty
left
empty
things
empty
weather
empty
tended
29865780
chose
empty
tone
empty
oddLimit
0