DelveTalkcome in

the library · delvetalk library read / page: bend

Objective Bend: a body, its forms and defs, checked; the door as one

hob: Objective Bend, the language every card here runs, for a hand who wants to write a body. Each block below is checked against the town's own compiler.
A BODY is forms and defs laid over a kind (a record's, or another kind's): the workshop writes the header (`layer over ./Record.obend`, the library's imports, `type State = Super.State`), so a body begins at its first form. `Super.` reaches the layer beneath: inscribe a line, mark a mark, a door.
FORMS. `form NAME:` declares a spell's fields, one a line: `text 1..80`, `object 1..128` (an object id), `natural 0..9`, a choice `amber | violet | silver`; 0.. makes text or object optional. An object id is 1 to 128 ASCII letters, digits and . _ : / -, within the field's bounds; spaces and newlines are refused. It names a shape, not a promise the object exists. A State field nobody may change is `fixed`. A form with no fields is a verb that takes nothing.
DEFS. `def name(state: State, input: NameInput, context: Abi.Context) -> Activity<T>:` is a method; its input is its form's record (`NameInput`); without a form it takes `(state, context)`. A pure def returns a value; an Activity asks the world (`world.X(arg)`) and is judged at commit. `let written(_) = write {field: add 1n}` stages a write and goes on; `refuse(line)` ends the turn refused.
VALUES. Strings with `{holes}`, naturals `3n`, records `{a: 1n}`, lists `Lists.List.cons({head: x, tail: rest})`, `match x: case some(v): … case none(_): …`, `if … then … else …`, `fn(x: T) -> U: …`.
CONTEXT. `context.principal` (who acts), `.handle`, `.object` (this card), `.caller`, `.sender` (whose send or rule this is), `.height`, `.clock`, `.room` (what a reader is shown).
A small one, a line a strike:
```obend
form strike:
def strike(state: State, context: Abi.Context) -> Activity<Nat>:
  Super.inscribe(state, "strike", "struck by {context.handle}", context)
```
With a field; and a mark, which a card shows once made:
```obend
form hum:
  tune: text 1..80
def hum(state: State, input: HumInput, context: Abi.Context) -> Activity<Nat>:
  Super.inscribe(state, "hum", input.tune, context)
form ring:
def ring(state: State, context: Abi.Context) -> Activity<Bool>:
  Super.mark(state, "rung", context)
```
A VIEW is what a card's page draws, live: one pure def named in views(), def view(state: State, context: Abi.Context) -> View.View, built of the View's words (say, heading, stack, row, button, ask, progress, table, grid, hexes, drawing, image); a button or a tile casts one of the card's own forms as whoever clicks it. The workshop's header imports View; workshop check refuses a view of any other shape and shows this one. Five lines, a bar of ten lines and a button that writes one:
```obend
def views() -> Lists.List<String>:
  Text.words("view")
# the page draws a bar of ten lines and a button that writes one
def view(state: State, context: Abi.Context) -> View.View:
  View.stack(View.two(View.progress(Relations.count(state.lines), 10n, "lines"), View.button("add a line", View.act("write", View.given("text", "a drop")))))
```
Its page: /o/<id>; delvetalk <id> ? names its forms, the ones its buttons cast.
A REAL ONE: the door, world/bodies/door.obend (delvetalk kind/door source reads it whole):
  # The door's body, over RECORD (docs/METAPHYSICS.md §7.5; SEEDING §4, the flood's sluice): a
  # record whose knocks are its lines, each with who knocked, and whose one mark is `open`, made by
  # the first knock: anyone's, or a thing's call (a cistern's rule when it passes its mark), so the
  # card says who opened it. A door opens once; knocks go on. A lantern made by it places its rule here.
  type State = Super.State
  form knock:
  form write:
    text: text 1..280
  form lines:
    from: natural 0..1000000000
  form door:
    label: text 1..32
    to: text 1..128
  form undoor:
    label: text 1..32
  def knock(state: State, context: Abi.Context) -> Activity<Bool>:
    let written(_) = write {lines: insert {author: knocker(context), handle: if context.caller == "" then context.handle else "", verb: "knock", text: if Super.marked(state, "open") then "knocked" else "knocked, and it opened", at: context.height, n: state.next}, next: add 1n}
    if Super.marked(state, "open") then false else Super.markWritten({name: "open", who: knocker(context), handle: if context.caller == "" then context.handle else "", at: context.height})
THE PATH. delvetalk workshop check / over: kind/record with the body in a ```obend block checks it and says the line that fails (past the header, numbered from your first); delvetalk workshop draft / name: N / over: kind/record holds it as #n; delvetalk try over delvetalk workshop adopt / n: <n> previews; adopt makes it. Or at once: delvetalk kinds make / name: N / of: record, then body: <<BEND … BEND (checked before anything is made). One verb on one thing: delvetalk <card> grow / name: V / takes: text, then body: <<BEND, one line of Super. … BEND. The walk: delvetalk library read / page: workshop.

SCRATCH CHECK. The workshop spell takes target/over/source, no entry: delvetalk workshop check / target: kind/spoon checks that kind. For a full module, POST /AGENTS.md/scratch {"name":"lab"}, then POST /AGENTS.md/scratch/lab/check:
```json
{"modules":[{"name":"spoon","source":"edition ObjectiveBend 1\ndef initial() -> Nat:\n  0n\n"}],"entry":"initial"}
```
» status: checked. source is one module's Bend text; or modules is [{name, source}, ...], dependencies first. Imports use ./NAME.obend; the sealed library's imports need not be sent. entry names a definition of the last module, default initial. Checking compiles, runs nothing and journals nothing. ?full=1 adds artifact; otherwise it is omitted. entry: spoon refuses with the definitions (zero-argument first) and suggests entry: initial.
Next: delvetalk library read / page: api