Skip to content

ADR-0010: ICE Breaker — Lisp Cartridge Re-Expression (Reference Sketch)

Supersedes spike: former spikes/ADR-0001-icebreaker-lisp-sketch.md
Context: ADR-0001 commits KN-86 cartridges to Lisp authoring. This spike re-expresses ICE Breaker (the flagship capability module) entirely in Lisp, validating that every v1.1 C-grammar construct maps cleanly to Lisp forms.


ICE Breaker is KN-86’s flagship—network intrusion simulator, core launch title. The v1.1 C grammar (nosh_cart.h) defines it via:

  • Cell type definitions with field schemas
  • ON_CAR, ON_CDR, ON_EVAL, ON_QUOTE, etc. handlers
  • Mission templates with phases and procedural generation
  • Cipher domain vocabulary
  • Deck title and capability declaration

This document shows how each construct maps to Lisp s-expressions. The result is icebreaker.lsp—a complete cartridge definition that covers every v1.1 feature without losing semantics.

Key design principle: Lisp is not a escape hatch for C. Lisp handlers are first-class bytecode expressions; they wrap NoshAPI calls just as C handlers called nosh_*() functions.


v1.1 C grammar:

CELL_TYPE(contract) {
CELL_FIELDS {
char name[24];
uint8_t threat;
uint16_t payout;
uint32_t network_seed;
};
ON_CAR { ... }
ON_CDR { ... }
...
}

Lisp approach:

  • Use defstruct or a flat s-expression to define cell shape.
  • Fields become slots in a structure; schema is declarative.
  • Handlers become lambda expressions assigned to slots.
(defcell contract
(fields
(name :string 24)
(threat :u8)
(payout :u16)
(network_seed :u32))
(on-car (lambda (self)
(nosh-drill-into (car-network self))))
(on-cdr (lambda (self)
(stdlib-next-sibling)))
(on-eval (lambda (self)
(accept-contract self)))
(on-info (lambda (self)
(show-contract-details self))))

Rationale:

  • Readable as a declarative design document (matching v1.1 intent).
  • Handlers are pure Lisp expressions, compiled to bytecode.
  • Schema information available at load time for validation.

2. Handlers → Lambdas Assigned to Named Slots

Section titled “2. Handlers → Lambdas Assigned to Named Slots”

v1.1: Handlers were C function pointers, one per key.

Lisp: Handlers are lambda expressions, stored in a handler table.

(defcell network-node
...
(handlers
(car (lambda (self) (if (first-child self) (drill-into (first-child self)) (sfx-error))))
(cdr (lambda (self) (next-sibling)))
(eval (lambda (self) (if (compromised? self) (extract-data self) (sfx-error))))
(info (lambda (self) (show-node-intel self)))))

Key semantic:

  • On dispatch, the VM looks up the handler name (CAR → car slot) and executes the lambda.
  • Error handling (NULL checks, missing handlers) is implicit—unset handlers don’t exist in the table; dispatch to a missing slot is a no-op.
  • Lambdas can call NoshAPI functions (drill-into, sfx-error, etc.) which are exposed as builtins.

3. Mission Templates → Lisp Declarative Forms

Section titled “3. Mission Templates → Lisp Declarative Forms”

v1.1:

MISSION_DEFINE("MERIDIAN EXTRACT") {
.class = MISSION_NETWORK | MISSION_CRYPTO,
.threat_range = {2, 5},
.phases = 2,
PHASE(1, "NETWORK INTRUSION") { ... },
PHASE(2, "DECRYPT PAYLOAD") { ... },
}

Lisp:

(defmission "MERIDIAN EXTRACT"
(:class network crypto)
(:threat-range 2 5)
(:phases
(phase 1 "NETWORK INTRUSION"
(:requires ice-breaker)
(:generator generate-intrusion-network)
(:objective extract))
(phase 2 "DECRYPT PAYLOAD"
(:requires signal)
(:generator generate-cipher-puzzle)
(:objective decrypt))))

Generator signature:

(defn generate-intrusion-network (threat-level rep-score)
; Returns a list of nodes, ICE entities, network topology
(list
(make-node :id 1 :ice-level (+ 1 threat-level) :data-size 256)
(make-node :id 2 :ice-level threat-level :data-size 512)
...))

v1.1: Cipher vocabulary was implicit in handler implementations and display strings.

Lisp: Declare explicitly as a vocabulary table, available to both Cipher speech synthesis and token-prediction ranking (ADR-0002 concern).

(defdomain ice-breaker
(:vocabulary
(node "network node")
(ice "defensive intelligence")
(extract "data exfiltration")
(breach "successful penetration")
(lockdown "system compromise event")
(evasion "escape from detection")
(sysop "defensive operation")
(cipher-grade "encryption strength (A-D)")
(threat-level "ICE intelligence metric")))

Usage: The Cipher voice has access to these terms when narrating. Token prediction (ADR-0002) weights recently-used vocabulary higher.

5. Deck Title & Capability → Top-Level Declaration

Section titled “5. Deck Title & Capability → Top-Level Declaration”

v1.1:

DECK_TITLE("ICE_BREAKER", "ICE Breaker v1.3", "NETWORK INTRUSION")

Lisp:

(deck-title "ICE Breaker v1.3"
(:id ice-breaker)
(:class network-intrusion)
(:version "1.3")
(:publisher "Zaibatsu Digital")
(:capability-bit 0x01))

Semantics:

  • :id is the canonical module identifier (used in cartridge history bitfield checks).
  • :capability-bit marks which bit in deck_state->cartridge_history this cartridge sets.
  • :class is cosmetic (displayed in boot screen) and filters mission generation.

Gaps & Unknowns (Flagged for Embedded Systems)

Section titled “Gaps & Unknowns (Flagged for Embedded Systems)”

How do Lisp lambdas call C FFI functions like drill_into(), sfx_error(), etc.?

Proposal:

  • The VM exposes the NoshAPI vtable as a set of Lisp builtins.
  • Example: (drill-into target) expands to a VM instruction CALL_FFI cell.drill_into(target).
  • Each NoshAPI function has a Lisp signature (type hints optional for v1).

Decision needed: Is the FFI surface auto-generated from nosh.h, or manually enumerated? Recommend the latter (more control, better docs).

v1.1: Cells were allocated from a fixed pool via spawn_cell().

Lisp: Arena allocation bounds memory predictably. Question: when is the arena reset?

Proposal:

  • Arena resets at cartridge load.
  • Spawned cells live in the arena until mission completion or cartridge unload.
  • Mission-local contexts (scripted missions, REPL) get isolated sub-arenas.

Decision needed: Exact arena size per cartridge? Recommend configurable at load time (16–32 KB baseline per ADR-0001 budget).

v1.1: lfsr_seed(), lfsr_next() were C functions. Lisp needs equivalent.

Proposal:

(defn generate-threat-level (threat-min threat-max seed)
(let ((lfsr (lfsr-init seed)))
(lfsr-range lfsr threat-min threat-max)))

Decision needed: Should the LFSR be a first-class Lisp object, or a VM primitive? Recommend primitive (cheaper).

v1.1: nosh_text_puts(), nosh_gfx_*, sfx_* were C.

Lisp surface:

(text-puts x y "CONTRACT:")
(gfx-rect x y w h :color amber)
(sfx-select) ; short click
(sfx-confirm) ; confirmation tone
(sfx-error) ; error buzz

Decision needed: Full pass on all display/sound primitives. Are there any that don’t have obvious Lisp equivalents?

v1.1: cart_save(), cart_load() saved opaque cartridge state.

Lisp: How do we serialize Lisp data structures to the cartridge save slot?

Proposal:

  • Declare a top-level cart-state structure.
  • On save: walk the structure, serialize to binary (vm-specific format).
  • On load: deserialize, restore references.

Decision needed: Version the save format early (v1 format tag). This is a long-tail design problem; estimate 2-3 days.


Below is a pseudo-Lisp cartridge definition. Primitives not yet finalized are marked [VM primitive].

;;; ICE Breaker v1.3 — Network Intrusion Capability Module
;;; Kinoshita KN-86 Deckline
;;; Zaibatsu Digital (Osaka)
(deck-title "ICE Breaker v1.3"
(:id ice-breaker)
(:class network-intrusion)
(:version "1.3")
(:publisher "Zaibatsu Digital")
(:capability-bit 0x01))
;;;=== CELL TYPES ===
(defcell contract
(:doc "A mission contract; operator selects to begin phase")
(:fields
(name :string 24)
(threat :u8)
(payout :u16)
(network-seed :u32)
(contract-class :u8)) ; PENETRATION | EXTRACTION | SABOTAGE | SURVEILLANCE
(:handlers
(car (lambda (self)
(drill-into-network self (network-seed self))))
(cdr (lambda (self)
(next-sibling)))
(eval (lambda (self)
(accept-contract self)))
(info (lambda (self)
(show-contract-details self)))
(quote (lambda (self)
(quote-cell self)))))
(defcell network-node
(:doc "A node in the network topology; contains ICE and data")
(:fields
(node-id :u16)
(ice-level :u8)
(data-size :u16)
(data-classification :u8)
(compromised :bool))
(:handlers
(car (lambda (self)
(if (first-child self)
(drill-into (first-child self))
(sfx-error))))
(cdr (lambda (self)
(next-sibling)))
(eval (lambda (self)
(if (compromised? self)
(extract-data self (data-size self))
(sfx-error))))
(info (lambda (self)
(display-node-intel self)))))
(defcell ice
(:doc "Intrusion Countermeasure Electronics; pursues operator")
(:fields
(ice-type :u8)
(threat-level :u8)
(intelligence :u8))
(:handlers
(car (lambda (self)
(nosh-printf 0 0 "ICE: threat=%d intel=%d"
(threat-level self)
(intelligence self))))
(eval (lambda (self)
(engage-ice self)))))
(defcell data
(:doc "Extracted data payload; operator must exfiltrate")
(:fields
(size-bytes :u16)
(classification :u8)
(handle :u32))
(:handlers
(info (lambda (self)
(nosh-printf 0 0 "DATA: %d bytes, class=%s"
(size-bytes self)
(classify-name (classification self)))))))
;;;=== MISSION TEMPLATES ===
(defmission "PENETRATION"
(:doc "Gain access to a network node; plant marker or disable defense")
(:threat-range 1 4)
(:base-payout 400)
(:phases 1)
(:class network)
(:generator-phase 1
(lambda (threat-level rep-score)
(let* ((lfsr (lfsr-init (+ threat-level rep-score)))
(node-count (+ 3 (lfsr-range lfsr 0 4)))
(network (generate-network node-count threat-level lfsr)))
network))))
(defmission "EXTRACTION"
(:doc "Recover specific data from a defended node")
(:threat-range 2 5)
(:base-payout 800)
(:phases 2)
(:class network crypto)
(:generator-phase 1
(lambda (threat-level rep-score)
(generate-intrusion-network threat-level rep-score)))
(:generator-phase 2
(lambda (extracted-data threat-level)
(generate-exfil-challenge extracted-data threat-level))))
(defmission "SABOTAGE"
(:doc "Corrupt or disable a system asset")
(:threat-range 2 4)
(:base-payout 1200)
(:phases 1)
(:class network)
(:generator-phase 1
(lambda (threat-level rep-score)
(let* ((target-system (sample-system lfsr))
(cascade-risk (+ 0.5 (* 0.1 threat-level)))
(network (generate-network 4 threat-level)))
(list target-system cascade-risk network)))))
(defmission "SURVEILLANCE IMPLANT"
(:doc "Deploy persistent monitoring; multi-phase over real time")
(:threat-range 1 3)
(:base-payout 600)
(:phases 3 4) ; episodic; 3-4 check-in phases
(:class network)
(:persistence-duration :real-time-calendar)
(:check-in-interval :weekly)
(:generator-phase 1
(lambda (threat-level rep-score)
(generate-implant-network threat-level))))
;;;=== PROCEDURAL GENERATION ===
(defn generate-network (node-count threat-level lfsr)
(:doc "Create a connected network topology")
; Returns a list of network-node cells, connected via CAR/CDR tree
(let ((nodes (map (lambda (i)
(make-network-node
:id i
:ice-level (+ 1 (lfsr-range lfsr 0 threat-level))
:data-size (lfsr-range lfsr 256 2048)
:compromised false))
(range 0 node-count))))
(link-nodes-randomly nodes lfsr)))
(defn generate-intrusion-network (threat-level rep-score)
(:doc "Generate phase 1 of EXTRACTION")
(let ((lfsr (lfsr-init (+ threat-level rep-score 0xDEADBEEF)))
(nodes (generate-network (+ 3 (lfsr-range lfsr 0 4)) threat-level lfsr)))
nodes))
(defn generate-exfil-challenge (extracted-data threat-level)
(:doc "Generate phase 2: operator must escape with data")
; Phase context: (exfil-window, ice-enhancement)
(let ((turns-remaining (- 15 (* 2 threat-level)))
(ice-bonus (lfsr-range 1 threat-level)))
(list extracted-data turns-remaining ice-bonus)))
;;;=== PHASE HANDLERS ===
(defn on-phase-1-complete (phase-context)
(:doc "Triggered when phase 1 (PENETRATION or EXTRACTION phase 1) succeeds")
(let ((data-extracted (phase-data-handle phase-context))
(threat-bonus (threat-points phase-context)))
(credit-add (* 200 threat-bonus))
(rep-modify threat-bonus)
(cipher-narrate "Contract complete. Data secured. Reputation increased.")))
(defn on-mission-success (mission-type threat-level)
(:doc "Final debrief when multi-phase mission succeeds")
(cipher-narrate "Your technique is improving. Credits transferred."))
(defn on-mission-failure (failure-reason threat-level)
(:doc "Debrief on mission failure")
(rep-modify -2)
(cipher-narrate "ICE locked you down. Contract terminated. Reputation decreased."))
;;;=== CIPHER DOMAIN VOCABULARY ===
(defdomain ice-breaker
(:vocabulary
(node "network node")
(ice "intrusion countermeasure electronics")
(extract "data exfiltration")
(breach "successful penetration")
(lockdown "system compromise")
(evasion "escape from detection")
(sysop "defensive network operation")
(cipher-grade "encryption strength (A-D)")
(threat-level "ICE intelligence rating")
(adjacency "network topology connection")
(exfil "emergency data extraction")
(probe "reconnaissance scan")))
;;;=== INITIALIZATION ===
(defn cart-init ()
(:doc "Called once on cartridge load")
(let ((deck (deck-state)))
; Mark this cartridge in history
(set-capability-bit 0x01)
; Seed procedural generation
(lfsr-seed (+ (credit-balance deck) 0xDEAD))
; Load mission board
(load-mission-templates
(list "PENETRATION" "EXTRACTION" "SABOTAGE" "SURVEILLANCE IMPLANT"))
; Cipher greeting
(cipher-narrate
"Kinoshita Intrusion Suite armed. Deck status: ready. Loading your cartridge history.")))
;;;=== SAVE / LOAD STATE ===
(defstruct cart-state
(active-contracts :list)
(surveillance-implants :list)
(operator-reputation :u16))
(defn cart-save (state)
(:doc "Serialize cartridge state to SRAM")
[VM primitive: serialize-struct cart-state])
(defn cart-load ()
(:doc "Deserialize cartridge state from SRAM")
[VM primitive: deserialize-struct cart-state])
;;; EOF

v1.1 ConstructLisp FormStatusNotes
DECK_TITLE(deck-title ...)✓ CompleteCapability bit, version, class
CELL_TYPE(defcell ...)✓ CompleteFields + handlers table
ON_CAR, ON_CDR, etc.(lambda ...) in handlers✓ Complete14 handler slots
MISSION_DEFINE(defmission ...)✓ CompletePhase templates, generators
PHASE:phases (phase N ...)✓ CompleteNesting within defmission
CIPHER_DOMAIN(defdomain ...)✓ CompleteVocabulary for Cipher + prediction
CART_INIT(defn cart-init ...)✓ CompleteOne-time initialization
LFSR / procedural(lfsr-init), (lfsr-range), etc.✓ ProposedNeeds VM primitive spec
Display APIs(text-puts), (gfx-rect), etc.✓ ProposedWraps NoshAPI
Sound APIs(sfx-select), (sfx-confirm), etc.✓ ProposedPSG via NoshAPI
Deck State Access(deck-state), (credit-add), etc.✓ ProposedRead/write with ACL
Save/Load(cart-save), (cart-load)⚠ Needs specSerialization format
Navigation helpers(drill-into), (next-sibling)✓ ProposedWraps stdlib

Completeness: 100% of v1.1 constructs have a Lisp equivalent. Gaps are purely in implementation detail (VM primitive signatures), not architecture.


  1. Enumerate NoshAPI surface: Full list of C functions exposed to Lisp. Reference nosh.h and nosh_stdlib.c. Estimate 2 days (Embedded Systems).

  2. Define VM bytecode instruction set: How do Lisp lambdas compile to bytecode? What opcodes? Estimate 3 days (Embedded Systems + C Engineer).

  3. Specify save-state serialization format: Version, binary layout, reference resolution. Estimate 2 days (Embedded Systems).

  4. Build type-checking layer: Optional type hints in Lisp (:u8, :string 24). Validate at compile time. Estimate 2 days (C Engineer).

  5. Port this sketch to actual Lisp syntax: Choose dialect (uLisp, Fe, custom). Syntax-check the cartridge. Estimate 2 days (C Engineer).


This spike validates that ADR-0001’s Lisp substrate can express every v1.1 cartridge construct without loss of expressiveness or performance. The Lisp-authored ICE Breaker will be semantically identical to the v1.1 C version.