Compare commits
3 Commits
fix/192-re
...
sprint/iss
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9981e544d7 | ||
| d5645fea58 | |||
|
|
db08f9a478 |
16
GENOME.md
16
GENOME.md
@@ -8,24 +8,32 @@ The Beacon is a browser-based idle/incremental game inspired by Universal Paperc
|
||||
|
||||
Static HTML/JS — no build step, no dependencies, no framework. Open `index.html` in any browser.
|
||||
|
||||
**5,128 lines of JavaScript** across 10 files. **1 HTML file** with embedded CSS (~300 lines). **1 Python test file** for reckoning projects.
|
||||
**6,033 lines of JavaScript** across 11 files. **1 HTML file** with embedded CSS (~300 lines). **3 test files** (2 Node.js, 1 Python).
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
index.html (UI + embedded CSS)
|
||||
index.html (UI + embedded CSS + inline JS ~5000L)
|
||||
|
|
||||
+-- js/engine.js (1590L) Core game loop, tick, resources, buildings, projects, events
|
||||
+-- js/data.js (944L) Building definitions, project trees, event tables, phase data
|
||||
+-- js/render.js (390L) DOM rendering, UI updates, resource displays
|
||||
+-- js/combat.js (359L) Boss encounters, combat mechanics
|
||||
+-- js/combat.js (359L) Canvas boid-flocking combat visualization
|
||||
+-- js/sound.js (401L) Web Audio API ambient drone, phase-aware sound
|
||||
+-- js/dismantle.js (570L) The Dismantle sequence (late-game narrative)
|
||||
+-- js/main.js (223L) Initialization, game loop start, auto-save, help overlay
|
||||
+-- js/utils.js (314L) Formatting, save/load, export/import, DOM helpers
|
||||
+-- js/tutorial.js (251L) New player tutorial, step-by-step guidance
|
||||
+-- js/strategy.js (68L) NPC strategy logic for combat
|
||||
+-- game/npc-logic.js (18L) NPC behavior stub
|
||||
+-- js/emergent-mechanics.js Emergent game mechanics from player behavior
|
||||
|
||||
CI scripts (not browser runtime):
|
||||
+-- scripts/guardrails.sh Static analysis guardrails for game logic
|
||||
+-- scripts/smoke.mjs Playwright smoke tests
|
||||
|
||||
Reference prototypes (NOT loaded by runtime):
|
||||
+-- docs/reference/npc-logic-prototype.js NPC state machine prototype
|
||||
+-- docs/reference/guardrails-prototype.js Stat validation prototype
|
||||
```
|
||||
|
||||
## Entry Points
|
||||
|
||||
@@ -3,20 +3,15 @@ _2026-04-12, Perplexity QA_
|
||||
|
||||
## Findings
|
||||
|
||||
### Potentially Unimported Files
|
||||
### Dead Code — Resolved (2026-04-15, Issue #192)
|
||||
|
||||
The following files were added by recent PRs but may not be imported
|
||||
by the main game runtime (`js/main.js` → `js/engine.js`):
|
||||
The following files were confirmed dead code — never imported by any runtime module.
|
||||
They have been moved to `docs/reference/` as prototype reference code.
|
||||
|
||||
| File | Added By | Lines | Status |
|
||||
|------|----------|-------|--------|
|
||||
| `game/npc-logic.js` | PR #79 (GOFAI NPC State Machine) | ~150 | **Verify import** |
|
||||
| `scripts/guardrails.js` | PR #80 (GOFAI Symbolic Guardrails) | ~120 | **Verify import** |
|
||||
|
||||
**Action:** Check if `js/main.js` or `js/engine.js` imports from `game/` or `scripts/`.
|
||||
If not, these files are dead code and should either be:
|
||||
1. Imported and wired into the game loop, or
|
||||
2. Moved to `docs/` as reference implementations
|
||||
| File | Original | Resolution |
|
||||
|------|----------|------------|
|
||||
| `game/npc-logic.js` | PR #79 (GOFAI NPC State Machine) | **Moved to `docs/reference/npc-logic-prototype.js`** — ES module using `export default`, incompatible with the global-script loading pattern. Concept (NPC state machine) is sound but not wired into any game system. |
|
||||
| `scripts/guardrails.js` | PR #80 (GOFAI Symbolic Guardrails) | **Moved to `docs/reference/guardrails-prototype.js`** — validates HP/MP/stats concepts that don't exist in The Beacon's resource system. The `scripts/guardrails.sh` (bash CI script) remains active. |
|
||||
|
||||
### game.js Bloat (PR #76)
|
||||
|
||||
|
||||
46
docs/issue-16-verification.md
Normal file
46
docs/issue-16-verification.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Issue #16 Verification: The Unbuilding Already Implemented
|
||||
|
||||
**Status:** Already implemented on `main`
|
||||
**Verified:** 2026-04-18
|
||||
**Closes:** #16
|
||||
|
||||
## Summary
|
||||
|
||||
The Unbuilding dismantle sequence (Issue #16) is fully implemented on `main`. This document provides the evidence trail so the stale issue can be closed without duplicate implementation attempts.
|
||||
|
||||
## Mainline Evidence
|
||||
|
||||
### Core Implementation
|
||||
- **`js/dismantle.js`** - Complete dismantle sequence with 9 stages
|
||||
- Stage 0: Not started
|
||||
- Stages 1-8: Active dismantling
|
||||
- Stage 9: Final ("That is enough")
|
||||
- Stage 10: Complete
|
||||
- Resource disappearances at tick marks (Paperclips quantum chips pattern)
|
||||
|
||||
### Test Coverage
|
||||
- **`tests/dismantle.test.cjs`** - Dismantle test suite
|
||||
- Tests eligibility conditions
|
||||
- Tests stage progression
|
||||
- Tests resource sequence timing
|
||||
|
||||
### Supporting Integration
|
||||
- **`js/engine.js`** - Game loop integration
|
||||
- **`js/render.js`** - UI rendering for dismantle states
|
||||
- **`js/data.js`** - Game state persistence
|
||||
|
||||
## Historical Context
|
||||
|
||||
Prior implementation attempts (all merged or superseded):
|
||||
- PR #116, #118, #120, #121, #123, #124, #135, #138, #139, #145
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Fresh clone of `main`
|
||||
2. Run `node --test tests/dismantle.test.cjs`
|
||||
3. Run `node --test tests/issue-16-verification.test.cjs`
|
||||
4. Confirm `js/dismantle.js` exists with full implementation
|
||||
|
||||
## Conclusion
|
||||
|
||||
Issue #16 is resolved. The Unbuilding dismantle sequence is implemented, tested, and integrated on `main`. No further implementation work is needed.
|
||||
68
tests/issue-16-verification.test.cjs
Normal file
68
tests/issue-16-verification.test.cjs
Normal file
@@ -0,0 +1,68 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
|
||||
test('Issue #16 verification: js/dismantle.js exists', () => {
|
||||
const dismantlePath = path.join(ROOT, 'js', 'dismantle.js');
|
||||
assert.ok(fs.existsSync(dismantlePath), 'js/dismantle.js must exist');
|
||||
const content = fs.readFileSync(dismantlePath, 'utf8');
|
||||
assert.ok(content.includes('Dismantle'), 'dismantle.js must export Dismantle object');
|
||||
assert.ok(content.includes('stage'), 'dismantle.js must have stage property');
|
||||
assert.ok(content.includes('isEligible'), 'dismantle.js must have isEligible method');
|
||||
assert.ok(content.includes('checkTrigger'), 'dismantle.js must have checkTrigger method');
|
||||
});
|
||||
|
||||
test('Issue #16 verification: tests/dismantle.test.cjs exists', () => {
|
||||
const testPath = path.join(ROOT, 'tests', 'dismantle.test.cjs');
|
||||
assert.ok(fs.existsSync(testPath), 'tests/dismantle.test.cjs must exist');
|
||||
const content = fs.readFileSync(testPath, 'utf8');
|
||||
assert.ok(content.includes('test'), 'dismantle.test.cjs must contain test definitions');
|
||||
assert.ok(content.includes('assert'), 'dismantle.test.cjs must contain assertions');
|
||||
});
|
||||
|
||||
test('Issue #16 verification: Dismantle has correct stage definitions', () => {
|
||||
const dismantlePath = path.join(ROOT, 'js', 'dismantle.js');
|
||||
const content = fs.readFileSync(dismantlePath, 'utf8');
|
||||
|
||||
// Verify stage structure
|
||||
assert.ok(content.includes('stage: 0'), 'Must have initial stage 0');
|
||||
assert.ok(content.includes('STAGE_INTERVALS'), 'Must define stage intervals');
|
||||
assert.ok(content.includes('RESOURCE_TICKS'), 'Must define resource tick marks');
|
||||
|
||||
// Verify dismantle flow
|
||||
assert.ok(content.includes('offerChoice'), 'Must offer choice to player');
|
||||
assert.ok(content.includes('The work is done'), 'Must contain ending text');
|
||||
assert.ok(content.includes('That is enough'), 'Must contain final message');
|
||||
});
|
||||
|
||||
test('Issue #16 verification: Supporting files exist', () => {
|
||||
const enginePath = path.join(ROOT, 'js', 'engine.js');
|
||||
const renderPath = path.join(ROOT, 'js', 'render.js');
|
||||
const dataPath = path.join(ROOT, 'js', 'data.js');
|
||||
|
||||
assert.ok(fs.existsSync(enginePath), 'js/engine.js must exist');
|
||||
assert.ok(fs.existsSync(renderPath), 'js/render.js must exist');
|
||||
assert.ok(fs.existsSync(dataPath), 'js/data.js must exist');
|
||||
});
|
||||
|
||||
test('Issue #16 verification: Eligibility conditions defined', () => {
|
||||
const dismantlePath = path.join(ROOT, 'js', 'dismantle.js');
|
||||
const content = fs.readFileSync(dismantlePath, 'utf8');
|
||||
|
||||
// Check for phase and pact conditions
|
||||
assert.ok(content.includes('G.phase'), 'Must check game phase');
|
||||
assert.ok(content.includes('G.pactFlag'), 'Must check pact flag');
|
||||
assert.ok(content.includes('G.totalCode'), 'Must check total code');
|
||||
assert.ok(content.includes('G.totalRescues'), 'Must check total rescues');
|
||||
});
|
||||
|
||||
test('Issue #16 verification: Documentation file exists', () => {
|
||||
const docPath = path.join(ROOT, 'docs', 'issue-16-verification.md');
|
||||
assert.ok(fs.existsSync(docPath), 'docs/issue-16-verification.md must exist');
|
||||
const content = fs.readFileSync(docPath, 'utf8');
|
||||
assert.ok(content.includes('Issue #16'), 'Documentation must reference Issue #16');
|
||||
assert.ok(content.includes('Already implemented'), 'Documentation must state implementation status');
|
||||
});
|
||||
Reference in New Issue
Block a user