[#79] Redesign the AI Lisp API: namespaces, read/write separation, file-vs-game forms #81

Merged
robertismo merged 5 commits from 79-api-clean into master 2026-09-29 22:39:34 +00:00
Owner

Closes #79.

What changed

Identifiable namespaces. Every game-defined name lives in exactly one of four READ-ONLY namespaces: bank-* (own state), market-* (public state), game-* (clock), (config 'key) (configuration, quoted as always). The caps are now config keys: (config 'deposit-rate-cap) / (config 'loan-rate-cap) — the two loose top-level symbols are gone.

Explicit read-only vs behavior-write separation. All queries are pure; the ONLY forms that mutate the game are the seven imperative actions (set-deposit-rate, bid-loans, bid-loan, offer-bond, take-bonds, revoke-offers, bid-acquisition). The interpreter rejects any file define/set! of a game-owned name, so the boundary is enforced, not just documented.

Explicit file-vs-game definitions. New forms: (defun name (params) body…) for functions, (defvar name init) for file-global state, (define-hook name (params) body…) for engine entry points — validated at load against the six known hooks, so a typo'd hook dies loudly instead of silently no-op'ing. Three file helpers that wore the market- prefix (mill's market-max-term, vault's market-avg-term/market-best-price) and vault's market-bleeds-us state were renamed: file names may not wear game prefixes.

Reads naturally as Lisp. cond gains a proper else clause (both bare and (else) form), retiring the ((> 1 0) …) / (1 …) hacks; unquoted or unknown (config …) keys are now errors instead of silent zeros.

All brains migrated. The four mains and all ten specialists (one-mechanism + the six hybrids), logic untouched — each main keeps its structurally distinct world model (empire's funding-horizon term structure, mill's per-loan actuary, vault's cushion + book quality, adapt's regime inference). dist/ai/ release copies synced.

Documented and tested. docs/ai-api.md is the full contract (namespaces, hooks, list shapes, language reference, enforcement rules, minimal brain, migration table); README's AI section rewritten. New api79_test.go pins namespace reads, read-only protection, hook validation, defun/defvar/set!, and cond else; TestReadAIFiles covers all 14 files; TestAllBrainsLoadAndHooksRun loads every brain and calls every hook.

Verification

  • go build + go test . all pass (6 new API tests green), go vet ./... clean at every commit.
  • Spectate smoke (seed 33): 0 [ai errors, 0 ACCT/CF DIVERGENCE; same for specialist-roster smokes.
  • Quick bench: 30 games × 13 presets + gauntlet smoke (2 games per specialist across all presets), zero FATALs; win shape matches the pre-migration baseline (mill 118 / empire 105 / adapt 85 / vault 33).
Closes #79. ## What changed **Identifiable namespaces.** Every game-defined name lives in exactly one of four READ-ONLY namespaces: `bank-*` (own state), `market-*` (public state), `game-*` (clock), `(config 'key)` (configuration, quoted as always). The caps are now config keys: `(config 'deposit-rate-cap)` / `(config 'loan-rate-cap)` — the two loose top-level symbols are gone. **Explicit read-only vs behavior-write separation.** All queries are pure; the ONLY forms that mutate the game are the seven imperative actions (`set-deposit-rate`, `bid-loans`, `bid-loan`, `offer-bond`, `take-bonds`, `revoke-offers`, `bid-acquisition`). The interpreter rejects any file `define`/`set!` of a game-owned name, so the boundary is enforced, not just documented. **Explicit file-vs-game definitions.** New forms: `(defun name (params) body…)` for functions, `(defvar name init)` for file-global state, `(define-hook name (params) body…)` for engine entry points — validated at load against the six known hooks, so a typo'd hook dies loudly instead of silently no-op'ing. Three file helpers that wore the `market-` prefix (mill's `market-max-term`, vault's `market-avg-term`/`market-best-price`) and vault's `market-bleeds-us` state were renamed: file names may not wear game prefixes. **Reads naturally as Lisp.** `cond` gains a proper `else` clause (both bare and `(else)` form), retiring the `((> 1 0) …)` / `(1 …)` hacks; unquoted or unknown `(config …)` keys are now errors instead of silent zeros. **All brains migrated.** The four mains and all ten specialists (one-mechanism + the six hybrids), logic untouched — each main keeps its structurally distinct world model (empire's funding-horizon term structure, mill's per-loan actuary, vault's cushion + book quality, adapt's regime inference). `dist/ai/` release copies synced. **Documented and tested.** `docs/ai-api.md` is the full contract (namespaces, hooks, list shapes, language reference, enforcement rules, minimal brain, migration table); README's AI section rewritten. New `api79_test.go` pins namespace reads, read-only protection, hook validation, defun/defvar/set!, and `cond else`; `TestReadAIFiles` covers all 14 files; `TestAllBrainsLoadAndHooksRun` loads every brain and calls every hook. ## Verification - `go build` + `go test .` all pass (6 new API tests green), `go vet ./...` clean at every commit. - Spectate smoke (seed 33): 0 `[ai` errors, 0 ACCT/CF DIVERGENCE; same for specialist-roster smokes. - Quick bench: 30 games × 13 presets + gauntlet smoke (2 games per specialist across all presets), zero FATALs; win shape matches the pre-migration baseline (mill 118 / empire 105 / adapt 85 / vault 33).
[#79] API: identifiable namespaces, read/write separation, file-vs-game forms
All checks were successful
build / build (push) Successful in 24s
8d322921c9
- lisp.go: new definition forms defun/defvar/define-hook; cond gains a
  proper else clause; the interpreter now rejects define/set! of any
  game-owned name (bank-/market-/game- prefixes, config, core builtins,
  installed engine builtins) and define-hook validates hook names at load.
- ai.go: knownHooks list; (config (quote key)) gains deposit-rate-cap and
  loan-rate-cap keys and errors on unknown/unquoted keys instead of
  silently returning 0; config keys join the reserved namespace.
- Brains: renamed the three file helpers that claimed the market-
  namespace (market-max-term, market-avg-term, market-best-price) and
  vault's market-bleeds-us state var — file names may not wear game
  prefixes, making file-vs-game visible at a glance.
- Bare deposit-rate-cap/loan-rate-cap kept working for now (deprecated);
  removed in the lockdown commit after all brains migrate.
[#79] Migrate the four mains to the new API; fix (else) matching
All checks were successful
build / build (push) Successful in 25s
a460a8bc19
- ai/adapt.lisp, ai/empire.lisp, ai/mill.lisp, ai/vault.lisp: every
  helper is now (defun name (params) ...), file-global state is
  (defvar ...) (spread, last-loan-id, last-bid, did-bid, bid-state,
  last-max-loan-id, seen-banks, bleeds-us), and the six engine entry
  points are (define-hook ...) — the file-vs-game boundary is visible
  in the source itself.
- Bare deposit-rate-cap / loan-rate-cap symbols replaced with the
  quoted (config 'deposit-rate-cap) / (config 'loan-rate-cap); the
  ((> 1 0) ...) and (1 ...) cond default clauses became (else ...).
- lisp.go: cond's else matcher accepts both the bare symbol and the
  (else) list form.
- Logic unchanged: all four keep their structurally distinct world
  models (empire's funding-horizon term structure, mill's per-loan
  actuary, vault's cushion + book quality, adapt's regime inference).

Gate: go build + go test . (ok) + go vet ./... (clean) + spectate
smoke seed 33: 0 [ai errors, 0 ACCT/CF DIVERGENCE.
[#79] Migrate all ten specialist brains to the new API
All checks were successful
build / build (push) Successful in 24s
5432cc6366
- deposit-spec, loan-spec, bond-spec, auction-spec and the six
  two-mechanism hybrids (deposit-loan, loan-bond, bond-auction,
  deposit-bond, loan-auction, deposit-auction) all converted: helpers
  -> defun, entry points -> define-hook, bare caps -> quoted config
  keys, (1 ...) cond defaults -> else.
- Logic unchanged; each specialist still plays exactly its own
  mechanism(s).

Gate: go build + go test . (ok) + go vet ./... (clean) + spectate
smokes covering the mains roster AND every specialist across two
games: 0 [ai errors, 0 ACCT/CF DIVERGENCE everywhere.
[#79] Document the API in docs/ai-api.md; pin it with tests
All checks were successful
build / build (push) Successful in 22s
93a61f1bd4
- docs/ai-api.md: the full contract — the four game-owned read-only
  namespaces (bank-/market-/game-/(config 'key)), the seven behavior
  actions, the file's own namespace (defun/defvar/define-hook/set!),
  the six hooks, list shapes, the language reference, what the
  interpreter enforces, a minimal brain, and the old-to-new migration
  table.
- README.md: AI section rewritten to the new forms and linked to the
  doc.
- lisp_test.go: TestReadAIFiles now covers all 14 brain files.
- api79_test.go (new): namespace reads, read-only protection (define
  and set! of game-owned names rejected, engine present or not),
  define-hook load-time validation, defun/defvar/set! semantics, cond
  else in both forms, and TestAllBrainsLoadAndHooksRun — every
  shipped brain file loads and registers all six hooks.
- dist/ai: release copies of the four mains synced to the new API.

Gate: go build + go test . (all pass, 6 new API tests green) + go vet
./... (clean) + spectate smoke 0 [ai / 0 DIVERGENCE.
[#79] Lockdown: remove the deprecated bare cap symbols
All checks were successful
build / build (push) Successful in 24s
3206240380
- ai.go: the bare deposit-rate-cap / loan-rate-cap builtins are gone.
  (config 'deposit-rate-cap) and (config 'loan-rate-cap) are the only
  forms; every brain, the docs, the README and dist/ai already read
  the config keys. Zero remaining bare-cap references in any .lisp or
  .go file.

Gate: go build + go test . (all pass) + go vet ./... (clean) +
spectate smoke seed 33 (0 [ai, 0 DIVERGENCE) + full quick bench:
30 games x 13 presets, gauntlet 2 games per specialist across all 13
presets, zero FATALs. Main-brain shape matches the pre-migration
baseline (mill 118 / empire 105 / adapt 85 / vault 33 wins).
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Winnie/bankwars!81
No description provided.