|
|
|
|
@@ -0,0 +1,286 @@
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
1. `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
|
|
|
|
|
|
|
|
|
|
2. `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
|
|
|
|
|
|
|
|
|
|
3. `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
|
|
|
|
|
|
|
|
|
|
4. `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
|
|
|
|
|
- `.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.js` for ReCKoning project-chain presence and structure
|
|
|
|
|
|
|
|
|
|
### Data flow
|
|
|
|
|
|
|
|
|
|
1. Browser loads `index.html`.
|
|
|
|
|
2. `js/data.js` seeds the simulation vocabulary:
|
|
|
|
|
- configuration constants
|
|
|
|
|
- global game state `G`
|
|
|
|
|
- building definitions `BDEF`
|
|
|
|
|
- project definitions `PDEFS`
|
|
|
|
|
- phase definitions `PHASES`
|
|
|
|
|
3. Utility / subsystem files (`utils`, `combat`, `strategy`, `sound`) attach helpers and side systems.
|
|
|
|
|
4. `js/engine.js` turns static definitions into live rates and tick progression.
|
|
|
|
|
5. `js/render.js` materializes the state into visible UI and persistence behavior.
|
|
|
|
|
6. `js/tutorial.js` and `js/dismantle.js` layer onboarding and endgame sequence logic on top.
|
|
|
|
|
7. `js/main.js` starts the timers, restores or initializes state, and wires controls.
|
|
|
|
|
8. State persists in browser `localStorage` under the main save key `the-beacon-v2` plus 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 constants
|
|
|
|
|
- `PHASES` — phase names, thresholds, descriptions
|
|
|
|
|
- `BDEF` — buildings, rates, costs, unlocks, educational notes
|
|
|
|
|
- `PDEFS` — 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 interactions
|
|
|
|
|
- `tick()` 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.js` says what exists
|
|
|
|
|
- `engine.js` says what changes
|
|
|
|
|
- `render.js` says what the player sees
|
|
|
|
|
- `main.js` decides 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.js` exposes a `StrategyEngine` as `window.SSE` for rule-based play guidance
|
|
|
|
|
- `game/npc-logic.js` defines an exported `NPCStateMachine`
|
|
|
|
|
|
|
|
|
|
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.mjs`
|
|
|
|
|
- `node --test tests/dismantle.test.cjs`
|
|
|
|
|
- `python3 -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
|
|
|
|
|
1. `js/engine.js`
|
|
|
|
|
- core production math
|
|
|
|
|
- corruption-event probability / debounce behavior
|
|
|
|
|
- harmony interactions and wizard effects
|
|
|
|
|
- autosave cadence assumptions
|
|
|
|
|
|
|
|
|
|
2. `js/render.js`
|
|
|
|
|
- save/export/import flows
|
|
|
|
|
- offline popup logic
|
|
|
|
|
- stats rendering and alignment UI behavior outside dismantle
|
|
|
|
|
|
|
|
|
|
3. `js/main.js`
|
|
|
|
|
- initialization order
|
|
|
|
|
- restore-vs-new-game branch logic
|
|
|
|
|
- keyboard shortcut behavior
|
|
|
|
|
- localStorage preference restoration
|
|
|
|
|
|
|
|
|
|
4. `js/strategy.js`
|
|
|
|
|
- recommendation priority ordering
|
|
|
|
|
- stale recommendation updates
|
|
|
|
|
|
|
|
|
|
5. `js/sound.js`
|
|
|
|
|
- mute state transitions and phase-aware ambient behavior
|
|
|
|
|
|
|
|
|
|
6. `js/tutorial.js`
|
|
|
|
|
- overlay sequencing and completion persistence
|
|
|
|
|
|
|
|
|
|
7. `game/npc-logic.js` and `scripts/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:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
1. The real runtime contract is the script order in `index.html`, not the README's file list.
|
|
|
|
|
2. `G` is the true system boundary; almost everything meaningful is state-table driven.
|
|
|
|
|
3. The Unbuilding / dismantle lane is the most mature and best-tested slice of the game.
|
|
|
|
|
4. The repo already acknowledges dead-code concerns in `docs/DEAD_CODE_AUDIT_2026-04-12.md`, and manual inspection confirms that `game/npc-logic.js` is not part of the loaded runtime.
|
|
|
|
|
5. 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.
|