12 KiB
GENOME.md — the-beacon
Generated: 2026-04-15 Subject repo: Timmy_Foundation/the-beacon Issue: timmy-home #674
Project Overview
the-beacon is a browser-based idle/incremental game about building sovereign AI without losing purpose. It is explicitly static and local-first: open index.html in a browser, load an ordered stack of plain JavaScript files, persist state in localStorage, and drive the whole simulation through a single shared global state object.
The core design divergence from Universal Paperclips is moral rather than mechanical. The game turns trust, harmony, drift, the Pact, rescues, and sovereign infrastructure into hard gameplay constraints. That gives the codebase two simultaneous jobs:
- run as a lightweight idle game with no build step
- act as a symbolic simulation of the Timmy Foundation's actual systems and decisions
Grounded repo facts from the current main branch:
- static entrypoint:
index.html - runtime scripts loaded in order:
js/data.js,js/utils.js,js/combat.js,js/strategy.js,js/sound.js,js/engine.js,js/render.js,js/tutorial.js,js/dismantle.js,js/main.js - smoke verification:
scripts/smoke.mjs - CI workflows:
.gitea/workflows/smoke.yml,.gitea/workflows/a11y.yml - existing focused tests:
tests/dismantle.test.cjs,tests/test_reckoning_projects.py - known documentation drift already tracked in the target repo:
the-beacon#169(README still references non-existent game.js after runtime split)
Architecture Diagram
flowchart TD
A[index.html] --> B[js/data.js]
B --> C[js/utils.js]
C --> D[js/combat.js]
D --> E[js/strategy.js]
E --> F[js/sound.js]
F --> G[js/engine.js]
G --> H[js/render.js]
H --> I[js/tutorial.js]
I --> J[js/dismantle.js]
J --> K[js/main.js]
B --> B1[CONFIG]
B --> B2[G global state]
B --> B3[BDEF building definitions]
B --> B4[PDEFS project definitions]
B --> B5[PHASES]
G --> C1[tick loop]
G --> C2[updateRates]
G --> C3[event and ending logic]
H --> D1[resource/building/project rendering]
H --> D2[save-load and import-export UI]
H --> D3[alignment and toast UI]
J --> E1[The Unbuilding endgame controller]
K --> F1[boot sequence]
K --> F2[keyboard shortcuts]
K --> F3[autosave intervals]
K --> LS[(localStorage)]
LS --> H
SMOKE[scripts/smoke.mjs] --> A
A11Y[.gitea/workflows/a11y.yml] --> A
TEST1[tests/dismantle.test.cjs] --> J
TEST2[tests/test_reckoning_projects.py] --> B4
Entry Points and Data Flow
Runtime entry points
-
index.html- the single document shell
- declares all UI regions, inline controls, and the exact script load order
- acts as the runtime contract for the whole game
-
js/main.js- bootstraps a new game or restores an existing save
- wires timers (
setInterval(tick, 100), autosave, education refresh) - binds keyboard shortcuts, mute/contrast toggles, save-on-pause, tooltip behavior
-
js/engine.js- the simulation core
- recalculates production with
updateRates() - advances the game in
tick() - triggers milestones, projects, corruption events, endgame checks, and rendering cadence
-
js/render.js- pushes global state into the DOM
- renders resources, buildings, projects, alignment UI, strategy guidance, save/export/import flow, and offline popup behavior
Verification / operator entry points
scripts/smoke.mjs- parses all JS files with
node --check - verifies HTML script references exist
- checks policy guardrail: no Anthropic/Claude references
- parses all JS files with
.gitea/workflows/smoke.yml- CI floor for syntax / policy / node tests
.gitea/workflows/a11y.yml- ARIA presence and JS syntax validation
tests/dismantle.test.cjs- Node test harness using a vm-based DOM shim to verify Unbuilding behavior
tests/test_reckoning_projects.py- Python assertions over
js/data.jsfor ReCKoning project-chain presence and structure
- Python assertions over
Data flow
- Browser loads
index.html. js/data.jsseeds the simulation vocabulary:- configuration constants
- global game state
G - building definitions
BDEF - project definitions
PDEFS - phase definitions
PHASES
- Utility / subsystem files (
utils,combat,strategy,sound) attach helpers and side systems. js/engine.jsturns static definitions into live rates and tick progression.js/render.jsmaterializes the state into visible UI and persistence behavior.js/tutorial.jsandjs/dismantle.jslayer onboarding and endgame sequence logic on top.js/main.jsstarts the timers, restores or initializes state, and wires controls.- State persists in browser
localStorageunder the main save keythe-beacon-v2plus preference keys for mute/contrast/tutorial behavior.
Key Abstractions
1. G — the state nucleus
Defined in js/data.js, G is the canonical runtime store. Nearly every subsystem reads or mutates it.
It contains:
- primary resources (
code,compute,knowledge,users,impact,rescues,ops,trust,creativity,harmony) - totals and rates
- building counts
- progression flags
- drift / event state
- sprint state
- dismantle / ending state
This is the real heart of the codebase. The rest of the app is mostly interpretation of G.
2. Definition tables as declarative content
The game is driven by large declarative registries in js/data.js:
CONFIG— balancing constantsPHASES— phase names, thresholds, descriptionsBDEF— buildings, rates, costs, unlocks, educational notesPDEFS— research projects and their triggers/effects
This makes the repo content-heavy rather than class-heavy. The dominant abstraction is “data table + engine function,” not object graph.
3. The tick engine
js/engine.js contains the real simulation semantics:
updateRates()recomputes all production and harmony interactionstick()applies those rates, checks milestones/events, advances sprint/combat/unbuilding, and schedules render work
The engine is where the game's moral mechanics become math.
4. Render split
js/render.js is responsible for DOM output, not state truth. That division is fairly clean:
data.jssays what existsengine.jssays what changesrender.jssays what the player seesmain.jsdecides when the loop starts
5. Endgame controller (js/dismantle.js)
The Unbuilding sequence is effectively its own subsystem with staged state, restore logic, progression pacing, and DOM transformations. It is the most deeply tested system in the repo and is a distinct abstraction, not just a couple of flags.
6. GOFAI sidecars
Two symbolic subsystems sit next to the main loop:
js/strategy.jsexposes aStrategyEngineaswindow.SSEfor rule-based play guidancegame/npc-logic.jsdefines an exportedNPCStateMachine
Important finding: game/npc-logic.js is not loaded by index.html, so it is currently a dormant or reference-only component rather than part of the active runtime.
Likewise, scripts/guardrails.js is a standalone symbolic checker script and not part of the browser runtime. The repo already carries a dead-code audit (docs/DEAD_CODE_AUDIT_2026-04-12.md) pointing at these unwired paths.
API Surface
This repo has no network API or package API in the conventional sense. Its public surface is a browser-global command surface plus local verification scripts.
Browser / gameplay surface
Player-triggered globals and handlers exposed through onclick or keyboard hooks include:
writeCode()doOps(...)activateSprint()saveGame()exportSave()importSave()toggleHelp()toggleMute()toggleContrast()- combat controls via
Combat.startBattle()
Persistence surface
- main save key:
the-beacon-v2 - mute preference:
the-beacon-muted - high-contrast preference:
the-beacon-contrast - tutorial completion flag in
js/tutorial.js
Verification surface
node scripts/smoke.mjsnode --test tests/dismantle.test.cjspython3 -m pytest tests/test_reckoning_projects.py -q- CI workflows in
.gitea/workflows/
Test Coverage Gaps
The repo is not untested, but coverage is sharply concentrated in a few late-game systems.
What is covered now
- Unbuilding / dismantle state machine and persistence (
tests/dismantle.test.cjs) - ReCKoning project-chain presence and basic structure (
tests/test_reckoning_projects.py) - smoke / accessibility policy checks via Gitea workflows
Major gaps
-
js/engine.js- core production math
- corruption-event probability / debounce behavior
- harmony interactions and wizard effects
- autosave cadence assumptions
-
js/render.js- save/export/import flows
- offline popup logic
- stats rendering and alignment UI behavior outside dismantle
-
js/main.js- initialization order
- restore-vs-new-game branch logic
- keyboard shortcut behavior
- localStorage preference restoration
-
js/strategy.js- recommendation priority ordering
- stale recommendation updates
-
js/sound.js- mute state transitions and phase-aware ambient behavior
-
js/tutorial.js- overlay sequencing and completion persistence
-
game/npc-logic.jsandscripts/guardrails.js- effectively unverified and, more importantly, apparently unwired into active runtime
Coverage quality warning
The pipeline's auto-estimates are misleading here. It undercounts JS coverage badly because this is a browser-first repo, not a Python package. Manual inspection is required to understand the real test surface.
Security Considerations
1. Save import trust boundary
importSave() accepts arbitrary JSON files and writes them into localStorage if they pass only a lightweight shape check. This is fine for a local-only game, but it means malformed or adversarial saves can still mutate game state in unexpected ways.
2. Large global mutable surface
Most game systems share the same mutable global G. That keeps the implementation simple but increases regression risk: any new subsystem can silently break another by mutating shared flags.
3. Inline browser-global commands
The runtime still uses inline onclick handlers and window-exposed functions. That is acceptable for a static offline-first game, but it widens the accidental API surface and makes dependency tracking less explicit.
4. Documentation drift risk
The README still references a non-existent game.js, while the real runtime has already been split across many js/*.js files. That mismatch is already tracked in the-beacon#169 and is the clearest contributor-facing risk discovered during this genome pass.
5. Dead / unwired code paths
The repo contains symbolic or prototype files (game/npc-logic.js, scripts/guardrails.js) that are not in the active browser load path. Unwired code is not just clutter — it can mislead contributors about what the game actually executes.
Verification Run
Grounded checks performed against the target repo:
python3 ~/.hermes/pipelines/codebase-genome.py --path /tmp/the-beacon-674 --output /tmp/the-beacon-base-GENOME.md
cd /tmp/the-beacon-674 && node scripts/smoke.mjs
cd /tmp/the-beacon-674 && node --test tests/dismantle.test.cjs
cd /tmp/the-beacon-674 && python3 -m pytest tests/test_reckoning_projects.py -q
Observed results:
- smoke script passed
- Node dismantle suite passed: 10 tests
- Python ReCKoning suite passed: 6 tests
- pipeline generated a tiny inventory helper but was not sufficient as the final artifact
Concrete Findings
- The real runtime contract is the script order in
index.html, not the README's file list. Gis the true system boundary; almost everything meaningful is state-table driven.- The Unbuilding / dismantle lane is the most mature and best-tested slice of the game.
- The repo already acknowledges dead-code concerns in
docs/DEAD_CODE_AUDIT_2026-04-12.md, and manual inspection confirms thatgame/npc-logic.jsis not part of the loaded runtime. - Documentation drift is a real contributor hazard and already tracked in
the-beacon#169.
Bottom Line
the-beacon is a static sovereign-web game whose architecture is cleaner than it first appears: data tables define the world, the engine advances it, render paints it, and main boots it. The codebase's strength is that it stays build-free and inspectable. Its main weaknesses are documentation drift, broad global mutable state, and shallow coverage over core loop behavior outside the dismantle / ReCKoning systems.