Language policy
All code is authored in KEC Lisp. A C file is justified only when it is the FFI layer itself. This is a standing project rule, stated by the product owner on multiple occasions and codified here on 2026-08-02. It binds every contributor and every agent brief.
The rule
Section titled “The rule”C exists in this tree to give Lisp its primitives. Everything above the primitive layer is KEC Lisp: gameplay, screens, programs, carts, mission and economy logic, generation, scheduling policy, and test cases.
A new .c file, or new logic inside an existing one, is acceptable only when the deliverable
is the FFI layer:
- binding seams (
*_bindfunctions, bridge primitives innosh_lisp_bridge.c); - glue that crosses the boundary into Lisp (event-bus or scheduler callbacks whose body is an invocation of a Lisp entry point);
- device drivers and realtime kernels that primitives expose (the framebuffer blitter, the PSG synthesis inside the audio callback, SPI/UART/OLED transport);
- the interpreter embedding and arena plumbing;
- thin test runners (lifecycle only; cases live in
.lspsuites, per the testing rule indocumentation-standard.mdand the repository conventions).
Logic never goes in C again. When a change touches an existing C core that holds logic, the change migrates that logic to Lisp behind a thin seam rather than extending the C.
Standing debt
Section titled “Standing debt”C files carrying logic that predates this codification, tracked for migration under GWP-777:
| File | Logic to migrate |
|---|---|
runtime/src/board_screen.c | Countdown, verb policy, row/detail formatting |
Migrated under GWP-777: the mission-board generator
(runtime/system-image/lib/mission/board-gen.lsp: template pool, eligibility gate, tier and
instance-count tables, threat clamp, payout formula). mission_board.c holds mechanisms only
(board memory, event subscriptions, the 32-bit LFSR behind the gen-draw seam, the accept
sink, marshalling). The tier and broke-bonus math the old board_screen.c row named reached
the screen through mission_board.c and moved with it; the remaining row is the screen-side
policy board_screen.c itself holds.
Migrated already on the ICE Breaker sprint stack (PRs #202 to #204): the mission-end pricing
(runtime/system-image/lib/mission/pricing.lsp), the contract reader API
(mission/contract.lsp over one raw primitive), and the sweep arming policy
(sweep/sweep.lsp); the corresponding C files hold mechanisms only. Migrated since: the
objective-graph policy (mission/objectives.lsp, GWP-750, PR #208).
Migrated on the map’s wave 1 (GWP-808): the baseline selection-weight policy
(mission/baseline.lsp), the first-boot tutorial policy (sys/tutorial.lsp), the
headless demo-deck seed (deck/demo-seed.lsp), the NoshAPI draw helpers
(cart/stdlib.lsp), the bare-deck display state (deck/deck.lsp), and the aux
bounty and dialog logic (deck/aux.lsp); the corresponding C files
(nosh_baseline.c, tutorial.c, tutorial_wiring.c, deck.c, nosh_stdlib.c,
deck_screen.c, deck_aux.c) hold mechanisms only.
The full source-by-source plan (dispositions, waves, the retained-C inventory) is
docs/software/runtime/c-to-lisp-migration-map.md
(GWP-781); wave 1 is DONE there.
The seams themselves (board_screen_bind, the accept sink, the event publishes) stay in C:
they are the FFI layer.
Enforcement
Section titled “Enforcement”- Every engineering brief carries this rule.
- Review rejects a PR that adds C logic outside the FFI layer.
- The capability boundary argument (“the engine owns mission truth”) governs which CONTEXT may mutate state; it does not license writing the algorithm in C. The binding set enforces ownership; the implementation language is free to be Lisp.