Sharpee
Chord / Standard Library / Containers & Openables / opening and closing

opening and closing

open (opening) parses the verbs open, open up, unwrap, and uncover (synonym forms: ADR-230 D4). Only an openable opens (anything else refuses not_openable), and lock state gates opening (locked); unlocking is its own step. open X with Y is still opening (ADR-230 D3b, no separate action), and the named tool is a consulted command entity. An openable can require a tool exactly as a lockable names a key (openable with the crowbar in Chord, toolId in TypeScript), refusing no_tool / tool_not_held / wrong_tool. An openable with no requirement ignores an offered tool. A non-empty container's contents are announced by a separate, replaceable piece: the opened-revealed chain (ADR-094) reacts to opened and emits revealed. A story that wants a different reveal, or none, replaces it with a define chain opened-revealed from "./reveal.ts" hatch — an author-supplied TypeScript handler — rather than touching the action. (Declaring any hatch makes the story TypeScript-bearing, so it is no longer browser-pure — the deliberate boundary for reaching platform internals like chains.)

close (closing) parses the verbs close, shut, and cover. It refuses not_closable, already_closed, and prevents_closing; the last fires both for one-way openables (canClose: false) and for an obstacle named in closeRequirements. Lock state is not checked; closing never locks.

The author writes:

create the Galley
  a room

  A cramped ship's kitchen, all brass and old smoke.

create the anvil
  scenery
  in the Galley

  A blacksmith's anvil, out of place at sea.

create the biscuit tin
  aka tin
  a container, openable
  in the Galley

  A dented tin with a warped lid.

  on closing it
    refuse tin-warped
  end on

  phrase tin-warped:
    The lid is warped; it will not seat again.

create the sea chest
  aka chest
  a container, openable
  in the Galley

  A low sea chest, banded in iron.

create the tin whistle
  aka whistle
  in the sea chest

  A tin whistle on a loop of cord.

create the player
  starts in the Galley

override message closing-closed
  You swing it shut.
end override

The player sees:

> open the anvil
The anvil can't be opened.

> open the biscuit tin
You open the biscuit tin, which is empty.

> close the biscuit tin
The lid is warped; it will not seat again.

> open the sea chest
You open the sea chest.

Inside the sea chest you see tin whistle.

> close the sea chest
You swing it shut.

Three seams and the chain in one scene: the anvil refuses with the platform's not_openable, the tin's on closing it guard speaks its own refusal, and the story-wide override message rewrites every plain close. The sea chest's contents line is the opened-revealed chain at work.

open (opening-*)close (closing-*)
Refusalsno_target · not_openable · already_open · locked · no_tool · tool_not_held · wrong_toolnot_closable · already_closed · prevents_closing
Successopened · its_empty (a container opens onto nothing)closed
Eventsopened, then revealed via the chainclosed (rich payload: door/container flags, contents count)

The interceptor seams are on opening it and on closing it on the target (the humming hive box in chord-language.md is exactly this seam), and opening consults an explicitly named tool after the target (target, then tool, the same ordering discipline as lock-and-key).

Two gaps remain: the several-tools list toolIds is TypeScript today, and the trait's autoLock field exists but is inert (closing never locks).