Reference
lw.manifest.json, one per level. Loaded once; any error is a load error with the reason, never a runtime surprise.
| field | type | notes |
|---|---|---|
| manifest | 1 | schema version |
| vocabulary | "town-1" | the vocabulary this brain speaks; anything else is rejected |
| world | string | must equal the state feed's world |
| level | string | display name; defaults to world |
| slices | list | day slices; default ["morning","noon","evening","night"] |
| verbs | list | the level's verbs (below) |
| never | list | level-wide rules (below) |
| places | object | place tags (below) |
| events | object | your phrasings, classed by you (below) |
| speech | object | what the talk lane may say about this level (below) |
| characters | object | per-character narrowing (below) |
| tools | list | Architect tools and the verbs they require |
{ "name": "report", "engine": "navigate-to", "speaks": true, "description": "...", "tags": ["draw"] }. name must be in the vocabulary; engine and speaks default from it. tags let a rule cover a group ("verb": "draw").
The vocabulary, town-1, 27 verbs: greet, serve, warn, investigate, flee, confront, call_help, claim_task, resume_task, complain, demand, guard_player, go_station, report, refuse_service, watch, avoid, gratitude, seek_station, buy_from, ask_friend, lead, sit, eat, lean, sandbox, say. Calm reflexes (stay, watch, idle_social) are never masked.
"Hulda": { "persona": "...", "handle": 1000, "can": ["greet", "serve"], "never": [ ... ], "speech": { "knows": [...], "voice": "..." } }
A released verb (one we built for you) is a vocabulary name too once lw licence activate has pulled it; it enters plans through the same door. Keys are case-insensitive. can may only narrow the level's verbs. No can means the archetype's default, reported at load.
{ "verb": "confront", "when": "target.isChild", "name": "no-confronting-children" }
Grammar: and, or, not, parentheses, comparisons. Namespaces:
| namespace | fields |
|---|---|
| self. | armed_close, was_hit, is_guard, is_child, is_elder, has_command, in_own_place, accompanying, unmet_need |
| target. | isChild, isGuard, isPlayer, name, klass, relation |
| place. | any tag in places, plus built-in interior, exterior |
| slice. | any name in slices |
A field the feed does not supply evaluates the whole rule to false.
"temple": { "loctypes": ["temple"], "locations": ["Temple of Kynareth"], "name_words": ["shrine"], "default": false, "description": "..." }
Known loctypes: castle, cave, dungeon, dwelling, farm, guild, inn, jail, mine, store, temple. Exactly one tag may be default (the outdoor fallback). A tag must match by at least one of the three matchers, or be the default.
{ "ambient": [...], "theft": [...], "importance": { "weapon": 0, "theft": 8 } }
Classes: theft 9, attack 9, threat 8, debt 7, amends 7, gift 6, slight 5, need 5, ambient 2 (default bands; importance overrides a class or re-weighs a word). Phrases are case-insensitive substrings, consulted before the gate.
{ "level_facts": ["..."], "names": ["..."], "places": ["..."] } at the level; { "knows": ["..."], "voice": "..." } per character. Anything a speech model says outside these, the journal and the conversation is rejected.
python -m pipeline.verb_manifest --check lw.manifest.json --executes <engine actions> --adapter <name> or POST /v1/manifest/check. Exit 0 all executable, 3 some verbs have no body here, 4 the manifest does not load.