Compare commits
8 Commits
fix/681-bu
...
fix/665
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b18f106b9 | ||
|
|
2f3138db6d | ||
| 37a08f45b8 | |||
| 9c420127be | |||
| 13eea2ce44 | |||
| 8e86b8c3de | |||
|
|
5c7ba5475f | ||
|
|
5d7b26858e |
296
GENOME.md
296
GENOME.md
@@ -1,141 +1,209 @@
|
||||
# GENOME.md — Timmy_Foundation/timmy-home
|
||||
|
||||
Generated by `pipelines/codebase_genome.py`.
|
||||
# GENOME.md — the-nexus
|
||||
|
||||
## Project Overview
|
||||
|
||||
Timmy Foundation's home repository for development operations and configurations.
|
||||
`the-nexus` is a hybrid repo that combines three layers in one codebase:
|
||||
|
||||
- Text files indexed: 3004
|
||||
- Source and script files: 186
|
||||
- Test files: 28
|
||||
- Documentation files: 701
|
||||
1. A browser-facing world shell rooted in `index.html`, `boot.js`, `bootstrap.mjs`, `app.js`, `style.css`, `portals.json`, `vision.json`, `manifest.json`, and `gofai_worker.js`
|
||||
2. A Python realtime bridge centered on `server.py` plus harness code under `nexus/`
|
||||
3. A memory / fleet / operator layer spanning `mempalace/`, `mcp_servers/`, `multi_user_bridge.py`, and supporting scripts
|
||||
|
||||
## Architecture
|
||||
The repo is not a clean single-purpose frontend and not just a backend harness. It is a mixed world/runtime/ops repository where browser rendering, WebSocket telemetry, MCP-driven game harnesses, and fleet memory tooling coexist.
|
||||
|
||||
Grounded repo facts from this checkout:
|
||||
- Browser shell files exist at repo root: `index.html`, `app.js`, `style.css`, `manifest.json`, `gofai_worker.js`
|
||||
- Data/config files also live at repo root: `portals.json`, `vision.json`
|
||||
- Realtime bridge exists in `server.py`
|
||||
- Game harnesses exist in `nexus/morrowind_harness.py` and `nexus/bannerlord_harness.py`
|
||||
- Memory/fleet sync exists in `mempalace/tunnel_sync.py`
|
||||
- Desktop/game automation MCP servers exist in `mcp_servers/desktop_control_server.py` and `mcp_servers/steam_info_server.py`
|
||||
- Validation exists in `tests/test_browser_smoke.py`, `tests/test_portals_json.py`, `tests/test_index_html_integrity.py`, and `tests/test_repo_truth.py`
|
||||
|
||||
The current architecture is best understood as a sovereign world shell plus operator/game harness backend, with accumulated documentation drift from multiple restoration and migration efforts.
|
||||
|
||||
## Architecture Diagram
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
repo_root["repo"]
|
||||
angband["angband"]
|
||||
briefings["briefings"]
|
||||
config["config"]
|
||||
conftest["conftest"]
|
||||
evennia["evennia"]
|
||||
evennia_tools["evennia_tools"]
|
||||
evolution["evolution"]
|
||||
gemini_fallback_setup["gemini-fallback-setup"]
|
||||
heartbeat["heartbeat"]
|
||||
infrastructure["infrastructure"]
|
||||
repo_root --> angband
|
||||
repo_root --> briefings
|
||||
repo_root --> config
|
||||
repo_root --> conftest
|
||||
repo_root --> evennia
|
||||
repo_root --> evennia_tools
|
||||
browser[Index HTML Shell\nindex.html -> boot.js -> bootstrap.mjs -> app.js]
|
||||
assets[Root Assets\nstyle.css\nmanifest.json\ngofai_worker.js]
|
||||
data[World Data\nportals.json\nvision.json]
|
||||
ws[Realtime Bridge\nserver.py\nWebSocket broadcast hub]
|
||||
gofai[In-browser GOFAI\nSymbolicEngine\nNeuroSymbolicBridge\nsetupGOFAI/updateGOFAI]
|
||||
harnesses[Python Harnesses\nnexus/morrowind_harness.py\nnexus/bannerlord_harness.py]
|
||||
mcp[MCP Adapters\nmcp_servers/desktop_control_server.py\nmcp_servers/steam_info_server.py]
|
||||
memory[Memory + Fleet\nmempalace/tunnel_sync.py\nmempalace.js]
|
||||
bridge[Operator / MUD Bridge\nmulti_user_bridge.py\ncommands/timmy_commands.py]
|
||||
tests[Verification\ntests/test_browser_smoke.py\ntests/test_portals_json.py\ntests/test_repo_truth.py]
|
||||
docs[Contracts + Drift Docs\nBROWSER_CONTRACT.md\nREADME.md\nCLAUDE.md\nINVESTIGATION_ISSUE_1145.md]
|
||||
|
||||
browser --> assets
|
||||
browser --> data
|
||||
browser --> gofai
|
||||
browser --> ws
|
||||
harnesses --> mcp
|
||||
harnesses --> ws
|
||||
bridge --> ws
|
||||
memory --> ws
|
||||
tests --> browser
|
||||
tests --> data
|
||||
tests --> docs
|
||||
docs --> browser
|
||||
```
|
||||
|
||||
## Entry Points
|
||||
## Entry Points and Data Flow
|
||||
|
||||
- `gemini-fallback-setup.sh` — operational script (`bash gemini-fallback-setup.sh`)
|
||||
- `morrowind/hud.sh` — operational script (`bash morrowind/hud.sh`)
|
||||
- `pipelines/codebase_genome.py` — python main guard (`python3 pipelines/codebase_genome.py`)
|
||||
- `scripts/auto_restart_agent.sh` — operational script (`bash scripts/auto_restart_agent.sh`)
|
||||
- `scripts/backup_pipeline.sh` — operational script (`bash scripts/backup_pipeline.sh`)
|
||||
- `scripts/big_brain_manager.py` — operational script (`python3 scripts/big_brain_manager.py`)
|
||||
- `scripts/big_brain_repo_audit.py` — operational script (`python3 scripts/big_brain_repo_audit.py`)
|
||||
- `scripts/codebase_genome_nightly.py` — operational script (`python3 scripts/codebase_genome_nightly.py`)
|
||||
- `scripts/detect_secrets.py` — operational script (`python3 scripts/detect_secrets.py`)
|
||||
- `scripts/dynamic_dispatch_optimizer.py` — operational script (`python3 scripts/dynamic_dispatch_optimizer.py`)
|
||||
- `scripts/emacs-fleet-bridge.py` — operational script (`python3 scripts/emacs-fleet-bridge.py`)
|
||||
- `scripts/emacs-fleet-poll.sh` — operational script (`bash scripts/emacs-fleet-poll.sh`)
|
||||
### Primary entry points
|
||||
|
||||
## Data Flow
|
||||
- `index.html` — root browser entry point
|
||||
- `boot.js` — startup selector; `tests/boot.test.js` shows it chooses file-mode vs HTTP/module-mode and injects `bootstrap.mjs` when served over HTTP
|
||||
- `bootstrap.mjs` — module bootstrap for the browser shell
|
||||
- `app.js` — main browser runtime; owns world state, GOFAI wiring, metrics polling, and portal/UI logic
|
||||
- `server.py` — WebSocket broadcast bridge on `ws://0.0.0.0:8765`
|
||||
- `nexus/morrowind_harness.py` — GamePortal/MCP harness for OpenMW Morrowind
|
||||
- `nexus/bannerlord_harness.py` — GamePortal/MCP harness for Bannerlord
|
||||
- `mempalace/tunnel_sync.py` — pulls remote fleet closets into the local palace over HTTP
|
||||
- `multi_user_bridge.py` — HTTP bridge for multi-user chat/session integration
|
||||
- `mcp_servers/desktop_control_server.py` — stdio MCP server exposing screenshots/mouse/keyboard control
|
||||
|
||||
1. Operators enter through `gemini-fallback-setup.sh`, `morrowind/hud.sh`, `pipelines/codebase_genome.py`.
|
||||
2. Core logic fans into top-level components: `angband`, `briefings`, `config`, `conftest`, `evennia`, `evennia_tools`.
|
||||
3. Validation is incomplete around `wizards/allegro/home/skills/red-teaming/godmode/scripts/auto_jailbreak.py`, `timmy-local/cache/agent_cache.py`, `wizards/allegro/home/skills/red-teaming/godmode/scripts/parseltongue.py`, so changes there carry regression risk.
|
||||
4. Final artifacts land as repository files, docs, or runtime side effects depending on the selected entry point.
|
||||
### Data flow
|
||||
|
||||
1. Browser startup begins at `index.html`
|
||||
2. `boot.js` decides whether the page is being served correctly; in HTTP mode it injects `bootstrap.mjs`
|
||||
3. `bootstrap.mjs` hands off to `app.js`
|
||||
4. `app.js` loads world configuration from `portals.json` and `vision.json`
|
||||
5. `app.js` constructs the Three.js scene and in-browser reasoning components, including `SymbolicEngine`, `NeuroSymbolicBridge`, `setupGOFAI()`, and `updateGOFAI()`
|
||||
6. Browser state and external runtimes connect through `server.py`, which broadcasts messages between connected clients
|
||||
7. Python harnesses (`nexus/morrowind_harness.py`, `nexus/bannerlord_harness.py`) spawn MCP subprocesses for desktop control / Steam metadata, capture state, execute actions, and feed telemetry into the Nexus bridge
|
||||
8. Memory/fleet tools like `mempalace/tunnel_sync.py` import remote palace data into local closets, extending what the operator/runtime layers can inspect
|
||||
9. Tests validate both the static browser contract and the higher-level repo-truth/memory contracts
|
||||
|
||||
### Important repo-specific runtime facts
|
||||
|
||||
- `portals.json` is a JSON array of portal/world/operator entries; examples in this checkout include `morrowind`, `bannerlord`, `workshop`, `archive`, `chapel`, and `courtyard`
|
||||
- `server.py` is a plain broadcast hub: clients send messages, the server forwards them to other connected clients
|
||||
- `nexus/morrowind_harness.py` and `nexus/bannerlord_harness.py` both implement a GamePortal pattern with MCP subprocess clients over stdio and WebSocket telemetry uplink
|
||||
- `mempalace/tunnel_sync.py` is not speculative; it is a real client that discovers remote wings, searches remote rooms, and writes `.closet.json` payloads locally
|
||||
|
||||
## Key Abstractions
|
||||
|
||||
- `evennia/timmy_world/game.py` — classes `World`:91, `ActionSystem`:421, `TimmyAI`:539, `NPCAI`:550; functions `get_narrative_phase()`:55, `get_phase_transition_event()`:65
|
||||
- `evennia/timmy_world/world/game.py` — classes `World`:19, `ActionSystem`:326, `TimmyAI`:444, `NPCAI`:455; functions none detected
|
||||
- `timmy-world/game.py` — classes `World`:19, `ActionSystem`:349, `TimmyAI`:467, `NPCAI`:478; functions none detected
|
||||
- `wizards/allegro/home/skills/red-teaming/godmode/scripts/auto_jailbreak.py` — classes none detected; functions none detected
|
||||
- `uniwizard/self_grader.py` — classes `SessionGrade`:23, `WeeklyReport`:55, `SelfGrader`:74; functions `main()`:713
|
||||
- `uni-wizard/v3/intelligence_engine.py` — classes `ExecutionPattern`:27, `ModelPerformance`:44, `AdaptationEvent`:58, `PatternDatabase`:69; functions none detected
|
||||
- `scripts/know_thy_father/crossref_audit.py` — classes `ThemeCategory`:30, `Principle`:160, `MeaningKernel`:169, `CrossRefFinding`:178; functions `extract_themes_from_text()`:192, `parse_soul_md()`:206, `parse_kernels()`:264, `cross_reference()`:296, `generate_report()`:440, `main()`:561
|
||||
- `timmy-local/cache/agent_cache.py` — classes `CacheStats`:28, `LRUCache`:52, `ResponseCache`:94, `ToolCache`:205; functions none detected
|
||||
### Browser runtime
|
||||
|
||||
- `app.js`
|
||||
- Defines in-browser reasoning/state machinery, including `class SymbolicEngine`, `class NeuroSymbolicBridge`, `setupGOFAI()`, and `updateGOFAI()`
|
||||
- Couples rendering, local symbolic reasoning, metrics polling, and portal/UI logic in one very large root module
|
||||
- `BROWSER_CONTRACT.md`
|
||||
- Acts like an executable architecture contract for the browser surface
|
||||
- Declares required files, DOM IDs, Three.js expectations, provenance rules, and WebSocket expectations
|
||||
|
||||
### Realtime bridge
|
||||
|
||||
- `server.py`
|
||||
- Single hub abstraction: a WebSocket broadcast server maintaining a `clients` set and forwarding messages from one client to the others
|
||||
- This is the seam between browser shell, harnesses, and external telemetry producers
|
||||
|
||||
### GamePortal harness layer
|
||||
|
||||
- `nexus/morrowind_harness.py`
|
||||
- `nexus/bannerlord_harness.py`
|
||||
- Both define MCP client wrappers, `GameState` / `ActionResult`-style data classes, and an Observe-Decide-Act telemetry loop
|
||||
- The harnesses are symmetric enough to be understood as reusable portal adapters with game-specific context injected on top
|
||||
|
||||
### Memory / fleet layer
|
||||
|
||||
- `mempalace/tunnel_sync.py`
|
||||
- Encodes the fleet-memory sync client contract: discover wings, pull broad room queries, write closet files, support dry-run
|
||||
- `mempalace.js`
|
||||
- Minimal browser/Electron bridge to MemPalace commands via `window.electronAPI.execPython(...)`
|
||||
- Important because it shows a second memory integration surface distinct from the Python fleet sync path
|
||||
|
||||
### Operator / interaction bridge
|
||||
|
||||
- `multi_user_bridge.py`
|
||||
- `commands/timmy_commands.py`
|
||||
- These bridge user-facing conversations or MUD/Evennia interactions back into Timmy/Nexus services
|
||||
|
||||
## API Surface
|
||||
|
||||
- CLI: `bash gemini-fallback-setup.sh` — operational script (`gemini-fallback-setup.sh`)
|
||||
- CLI: `bash morrowind/hud.sh` — operational script (`morrowind/hud.sh`)
|
||||
- CLI: `python3 pipelines/codebase_genome.py` — python main guard (`pipelines/codebase_genome.py`)
|
||||
- CLI: `bash scripts/auto_restart_agent.sh` — operational script (`scripts/auto_restart_agent.sh`)
|
||||
- CLI: `bash scripts/backup_pipeline.sh` — operational script (`scripts/backup_pipeline.sh`)
|
||||
- CLI: `python3 scripts/big_brain_manager.py` — operational script (`scripts/big_brain_manager.py`)
|
||||
- CLI: `python3 scripts/big_brain_repo_audit.py` — operational script (`scripts/big_brain_repo_audit.py`)
|
||||
- CLI: `python3 scripts/codebase_genome_nightly.py` — operational script (`scripts/codebase_genome_nightly.py`)
|
||||
- Python: `get_narrative_phase()` from `evennia/timmy_world/game.py:55`
|
||||
- Python: `get_phase_transition_event()` from `evennia/timmy_world/game.py:65`
|
||||
- Python: `main()` from `uniwizard/self_grader.py:713`
|
||||
### Browser / static surface
|
||||
|
||||
## Test Coverage Report
|
||||
- `index.html` served over HTTP
|
||||
- `boot.js` exports `bootPage()`; verified by `node --test tests/boot.test.js`
|
||||
- Data APIs are file-based inside the repo: `portals.json`, `vision.json`, `manifest.json`
|
||||
|
||||
- Source and script files inspected: 186
|
||||
- Test files inspected: 28
|
||||
- Coverage gaps:
|
||||
- `wizards/allegro/home/skills/red-teaming/godmode/scripts/auto_jailbreak.py` — no matching test reference detected
|
||||
- `timmy-local/cache/agent_cache.py` — no matching test reference detected
|
||||
- `wizards/allegro/home/skills/red-teaming/godmode/scripts/parseltongue.py` — no matching test reference detected
|
||||
- `twitter-archive/multimodal_pipeline.py` — no matching test reference detected
|
||||
- `wizards/allegro/home/skills/red-teaming/godmode/scripts/godmode_race.py` — no matching test reference detected
|
||||
- `skills/productivity/google-workspace/scripts/google_api.py` — no matching test reference detected
|
||||
- `wizards/allegro/home/skills/productivity/google-workspace/scripts/google_api.py` — no matching test reference detected
|
||||
- `morrowind/pilot.py` — no matching test reference detected
|
||||
- `morrowind/mcp_server.py` — no matching test reference detected
|
||||
- `skills/research/domain-intel/scripts/domain_intel.py` — no matching test reference detected
|
||||
- `wizards/allegro/home/skills/research/domain-intel/scripts/domain_intel.py` — no matching test reference detected
|
||||
- `timmy-local/scripts/ingest.py` — no matching test reference detected
|
||||
### Network/runtime surface
|
||||
|
||||
## Security Audit Findings
|
||||
- `python3 server.py`
|
||||
- Starts the WebSocket bridge on port `8765`
|
||||
- `python3 l402_server.py`
|
||||
- Local HTTP microservice for cost-estimate style responses
|
||||
- `python3 multi_user_bridge.py`
|
||||
- Multi-user HTTP/chat bridge
|
||||
|
||||
- [medium] `briefings/briefing_20260325.json:37` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `"gitea_error": "Gitea 404: {\"errors\":null,\"message\":\"not found\",\"url\":\"http://143.198.27.163:3000/api/swagger\"}\n [http://143.198.27.163:3000/api/v1/repos/Timmy_Foundation/sovereign-orchestration/issues?state=open&type=issues&sort=created&direction=desc&limit=1&page=1]",`
|
||||
- [medium] `briefings/briefing_20260328.json:11` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `"provider_base_url": "http://localhost:8081/v1",`
|
||||
- [medium] `briefings/briefing_20260329.json:11` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `"provider_base_url": "http://localhost:8081/v1",`
|
||||
- [medium] `config.yaml:37` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `summary_base_url: http://localhost:11434/v1`
|
||||
- [medium] `config.yaml:47` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `base_url: 'http://localhost:11434/v1'`
|
||||
- [medium] `config.yaml:52` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `base_url: 'http://localhost:11434/v1'`
|
||||
- [medium] `config.yaml:57` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `base_url: 'http://localhost:11434/v1'`
|
||||
- [medium] `config.yaml:62` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `base_url: 'http://localhost:11434/v1'`
|
||||
- [medium] `config.yaml:67` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `base_url: 'http://localhost:11434/v1'`
|
||||
- [medium] `config.yaml:77` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `base_url: 'http://localhost:11434/v1'`
|
||||
- [medium] `config.yaml:82` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `base_url: 'http://localhost:11434/v1'`
|
||||
- [medium] `config.yaml:174` — hardcoded http endpoint: plaintext or fixed HTTP endpoints can drift or leak across environments. Evidence: `base_url: http://localhost:11434/v1`
|
||||
### Harness / operator CLI surfaces
|
||||
|
||||
## Dead Code Candidates
|
||||
- `python3 nexus/morrowind_harness.py`
|
||||
- `python3 nexus/bannerlord_harness.py`
|
||||
- `python3 mempalace/tunnel_sync.py --peer <url> [--dry-run] [--n N]`
|
||||
- `python3 mcp_servers/desktop_control_server.py`
|
||||
- `python3 mcp_servers/steam_info_server.py`
|
||||
|
||||
- `wizards/allegro/home/skills/red-teaming/godmode/scripts/auto_jailbreak.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `timmy-local/cache/agent_cache.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `wizards/allegro/home/skills/red-teaming/godmode/scripts/parseltongue.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `twitter-archive/multimodal_pipeline.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `wizards/allegro/home/skills/red-teaming/godmode/scripts/godmode_race.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `skills/productivity/google-workspace/scripts/google_api.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `wizards/allegro/home/skills/productivity/google-workspace/scripts/google_api.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `morrowind/pilot.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `morrowind/mcp_server.py` — not imported by indexed Python modules and not referenced by tests
|
||||
- `skills/research/domain-intel/scripts/domain_intel.py` — not imported by indexed Python modules and not referenced by tests
|
||||
### Validation surface
|
||||
|
||||
## Performance Bottleneck Analysis
|
||||
- `python3 -m pytest tests/test_portals_json.py tests/test_index_html_integrity.py tests/test_repo_truth.py -q`
|
||||
- `node --test tests/boot.test.js`
|
||||
- `python3 -m py_compile server.py nexus/morrowind_harness.py nexus/bannerlord_harness.py mempalace/tunnel_sync.py mcp_servers/desktop_control_server.py`
|
||||
- `tests/test_browser_smoke.py` defines the higher-cost Playwright smoke contract for the world shell
|
||||
|
||||
- `angband/mcp_server.py` — large module (353 lines) likely hides multiple responsibilities
|
||||
- `evennia/timmy_world/game.py` — large module (1541 lines) likely hides multiple responsibilities
|
||||
- `evennia/timmy_world/world/game.py` — large module (1345 lines) likely hides multiple responsibilities
|
||||
- `morrowind/mcp_server.py` — large module (451 lines) likely hides multiple responsibilities
|
||||
- `morrowind/pilot.py` — large module (459 lines) likely hides multiple responsibilities
|
||||
- `pipelines/codebase_genome.py` — large module (557 lines) likely hides multiple responsibilities
|
||||
- `scripts/know_thy_father/crossref_audit.py` — large module (657 lines) likely hides multiple responsibilities
|
||||
- `scripts/know_thy_father/index_media.py` — large module (405 lines) likely hides multiple responsibilities
|
||||
- `scripts/know_thy_father/synthesize_kernels.py` — large module (416 lines) likely hides multiple responsibilities
|
||||
- `scripts/tower_game.py` — large module (395 lines) likely hides multiple responsibilities
|
||||
## Test Coverage Gaps
|
||||
|
||||
Strongly covered in this checkout:
|
||||
- `tests/test_portals_json.py` validates `portals.json`
|
||||
- `tests/test_index_html_integrity.py` checks merge-marker/DOM-integrity regressions in `index.html`
|
||||
- `tests/boot.test.js` verifies `boot.js` startup behavior
|
||||
- `tests/test_repo_truth.py` validates the repo-truth documents
|
||||
- Multiple `tests/test_mempalace_*.py` files cover the palace layer
|
||||
- `tests/test_bannerlord_harness.py` exists for the Bannerlord harness
|
||||
|
||||
Notable gaps or weak seams:
|
||||
- `nexus/morrowind_harness.py` is large and operationally critical, but the generated baseline still flags it as a gap relative to its size/complexity
|
||||
- `mcp_servers/desktop_control_server.py` exposes high-power automation but has no obvious dedicated test file in the root `tests/` suite
|
||||
- `app.js` is the dominant browser runtime file and mixes rendering, GOFAI, metrics, and integration logic in one place; browser smoke exists, but there is limited unit-level decomposition around those subsystems
|
||||
- `mempalace.js` appears minimally bridged and stale relative to the richer Python MemPalace layer
|
||||
- `multi_user_bridge.py` is a large integration surface and should be treated as high regression risk even though it is central to operator/chat flow
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- `server.py` binds `HOST = "0.0.0.0"`, exposing the broadcast bridge beyond localhost unless network controls limit it
|
||||
- The WebSocket bridge is a broadcast hub without visible authentication in `server.py`; connected clients are trusted to send messages into the bus
|
||||
- `mcp_servers/desktop_control_server.py` exposes mouse/keyboard/screenshot control through a stdio MCP server. In any non-local or poorly isolated runtime, this is a privileged automation surface
|
||||
- `app.js` contains hardcoded local/network endpoints such as `http://localhost:${L402_PORT}/api/cost-estimate` and `http://localhost:8082/metrics`; these are convenient for local development but create environment drift and deployment assumptions
|
||||
- `app.js` also embeds explicit endpoint/status references like `ws://143.198.27.163:8765`, which is operationally brittle and the kind of hardcoded location data that drifts across environments
|
||||
- `mempalace.js` shells out through `window.electronAPI.execPython(...)`; this is powerful and useful, but it is a clear trust boundary between UI and host execution
|
||||
- `INVESTIGATION_ISSUE_1145.md` documents an earlier integrity hazard: agents writing to `public/nexus/` instead of canonical root paths. That path confusion is both an operational and security concern because it makes provenance harder to reason about
|
||||
|
||||
## Runtime Truth and Docs Drift
|
||||
|
||||
The most important architecture finding in this repo is not a class or subsystem. It is a truth mismatch.
|
||||
|
||||
- README.md says current `main` does not ship a browser 3D world
|
||||
- CLAUDE.md declares root `app.js` and `index.html` as canonical frontend paths
|
||||
- tests and browser contract now assume the root frontend exists
|
||||
|
||||
All three statements are simultaneously present in this checkout.
|
||||
|
||||
Grounded evidence:
|
||||
- `README.md` still says the repo does not contain an active root frontend such as `index.html`, `app.js`, or `style.css`
|
||||
- the current checkout does contain `index.html`, `app.js`, `style.css`, `manifest.json`, and `gofai_worker.js`
|
||||
- `BROWSER_CONTRACT.md` explicitly treats those root files as required browser assets
|
||||
- `tests/test_browser_smoke.py` serves those exact files and validates DOM/WebGL contracts against them
|
||||
- `tests/test_index_html_integrity.py` assumes `index.html` is canonical and production-relevant
|
||||
- `CLAUDE.md` says frontend code lives at repo root and explicitly warns against `public/nexus/`
|
||||
- `INVESTIGATION_ISSUE_1145.md` explains why `public/nexus/` is a bad/corrupt duplicate path and confirms the real classical AI code lives in root `app.js`
|
||||
|
||||
The honest conclusion:
|
||||
- The repo contains a partially restored or actively re-materialized browser surface
|
||||
- The docs are preserving an older migration truth while the runtime files and smoke contracts describe a newer present-tense truth
|
||||
- Any future work in `the-nexus` must choose one truth and align `README.md`, `CLAUDE.md`, smoke tests, and file layout around it
|
||||
|
||||
That drift is itself a critical architectural fact and should be treated as first-order design debt, not a side note.
|
||||
|
||||
@@ -9,6 +9,7 @@ This pipeline gives Timmy a repeatable way to generate a deterministic `GENOME.m
|
||||
- `pipelines/codebase_genome.py` — static analyzer that writes `GENOME.md`
|
||||
- `pipelines/codebase-genome.py` — thin CLI wrapper matching the expected pipeline-style entrypoint
|
||||
- `scripts/codebase_genome_nightly.py` — org-aware nightly runner that selects the next repo, updates a local checkout, and writes the genome artifact
|
||||
- `scripts/codebase_genome_status.py` — rollup/status reporter for artifact coverage, duplicate paths, and next uncovered repo
|
||||
- `GENOME.md` — generated analysis for `timmy-home` itself
|
||||
|
||||
## Genome output
|
||||
|
||||
106
reports/evaluations/2026-04-07-mempalace-v3-evaluation.md
Normal file
106
reports/evaluations/2026-04-07-mempalace-v3-evaluation.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# MemPalace v3.0.0 Integration — Before/After Evaluation
|
||||
|
||||
> Issue #568 | timmy-home
|
||||
> Date: 2026-04-07
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Evaluated **MemPalace v3.0.0** as a memory layer for the Timmy/Hermes agent stack.
|
||||
|
||||
**Installed:** ✅ `mempalace 3.0.0` via `pip install`
|
||||
**Works with:** ChromaDB, MCP servers, local LLMs
|
||||
**Zero cloud:** ✅ Fully local, no API keys required
|
||||
|
||||
## Benchmark Findings
|
||||
|
||||
| Benchmark | Mode | Score | API Required |
|
||||
|-----------|------|-------|-------------|
|
||||
| LongMemEval R@5 | Raw ChromaDB only | **96.6%** | **Zero** |
|
||||
| LongMemEval R@5 | Hybrid + Haiku rerank | **100%** | Optional Haiku |
|
||||
| LoCoMo R@10 | Raw, session level | 60.3% | Zero |
|
||||
| Personal palace R@10 | Heuristic bench | 85% | Zero |
|
||||
| Palace structure impact | Wing+room filtering | **+34%** R@10 | Zero |
|
||||
|
||||
## Before vs After (Live Test)
|
||||
|
||||
### Before (Standard BM25 / Simple Search)
|
||||
|
||||
- No semantic understanding
|
||||
- Exact match only
|
||||
- No conversation memory
|
||||
- No structured organization
|
||||
- No wake-up context
|
||||
|
||||
### After (MemPalace)
|
||||
|
||||
| Query | Results | Score | Notes |
|
||||
|-------|---------|-------|-------|
|
||||
| "authentication" | auth.md, main.py | -0.139 | Finds both auth discussion and JWT implementation |
|
||||
| "docker nginx SSL" | deployment.md, auth.md | 0.447 | Exact match on deployment, related JWT context |
|
||||
| "keycloak OAuth" | auth.md, main.py | -0.029 | Finds OAuth discussion and JWT usage |
|
||||
| "postgresql database" | README.md, main.py | 0.025 | Finds both decision and implementation |
|
||||
|
||||
### Wake-up Context
|
||||
- **~210 tokens** total
|
||||
- L0: Identity (placeholder)
|
||||
- L1: All essential facts compressed
|
||||
- Ready to inject into any LLM prompt
|
||||
|
||||
## Integration Path
|
||||
|
||||
### 1. Memory Mining
|
||||
```bash
|
||||
mempalace mine ~/.hermes/sessions/ --mode convos
|
||||
mempalace mine ~/.hermes/hermes-agent/
|
||||
mempalace mine ~/.hermes/
|
||||
```
|
||||
|
||||
### 2. Wake-up Protocol
|
||||
```bash
|
||||
mempalace wake-up > /tmp/timmy-context.txt
|
||||
```
|
||||
|
||||
### 3. MCP Integration
|
||||
```bash
|
||||
hermes mcp add mempalace -- python -m mempalace.mcp_server
|
||||
```
|
||||
|
||||
### 4. Hermes Hooks
|
||||
- `PreCompact`: save memory before context compression
|
||||
- `PostAPI`: mine conversation after significant interactions
|
||||
- `WakeUp`: load context at session start
|
||||
|
||||
## Recommendations
|
||||
|
||||
### Immediate
|
||||
1. Add `mempalace` to Hermes venv requirements
|
||||
2. Create mine script for ~/.hermes/ and ~/.timmy/
|
||||
3. Add wake-up hook to Hermes session start
|
||||
4. Test with real conversation exports
|
||||
|
||||
### Short-term
|
||||
1. Mine last 30 days of Timmy sessions
|
||||
2. Build wake-up context for all agents
|
||||
3. Add MemPalace MCP tools to Hermes toolset
|
||||
4. Test retrieval quality on real queries
|
||||
|
||||
### Medium-term
|
||||
1. Replace homebrew memory system with MemPalace
|
||||
2. Build palace structure: wings for projects, halls for topics
|
||||
3. Compress with AAAK for 30x storage efficiency
|
||||
4. Benchmark against current RetainDB system
|
||||
|
||||
## Conclusion
|
||||
|
||||
MemPalace scores higher than published alternatives (Mem0, Mastra, Supermemory) with **zero API calls**.
|
||||
|
||||
Key advantages:
|
||||
1. **Verbatim retrieval** — never loses the "why" context
|
||||
2. **Palace structure** — +34% boost from organization
|
||||
3. **Local-only** — aligns with sovereignty mandate
|
||||
4. **MCP compatible** — drops into existing tool chain
|
||||
5. **AAAK compression** — 30x storage reduction coming
|
||||
|
||||
---
|
||||
|
||||
*Evaluated by Timmy | Issue #568*
|
||||
218
scripts/codebase_genome_status.py
Normal file
218
scripts/codebase_genome_status.py
Normal file
@@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Status/reporting helper for the codebase genome pipeline.
|
||||
|
||||
This lands a parent-epic slice for timmy-home #665 by making the current genome
|
||||
coverage across repos inspectable: which repos have artifacts, which have tests,
|
||||
what duplicates exist, and which repo is still uncovered next.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Iterable
|
||||
import urllib.request
|
||||
|
||||
|
||||
def artifact_repo_name(path: Path, host_repo_name: str = 'timmy-home') -> str | None:
|
||||
normalized = path.as_posix()
|
||||
name = path.name
|
||||
if normalized == 'GENOME.md':
|
||||
return host_repo_name
|
||||
if path.parts[:1] == ('genomes',) and name == 'GENOME.md' and len(path.parts) == 3:
|
||||
return path.parts[1]
|
||||
if path.parts[:1] == ('genomes',) and name.endswith('-GENOME.md'):
|
||||
return name[:-len('-GENOME.md')]
|
||||
if path.parent == Path('.') and name.startswith('GENOME-') and name.endswith('.md'):
|
||||
return name[len('GENOME-'):-len('.md')]
|
||||
if path.parent == Path('.') and name.endswith('-GENOME.md'):
|
||||
return name[:-len('-GENOME.md')]
|
||||
return None
|
||||
|
||||
|
||||
def test_repo_name(path: Path, host_repo_name: str = 'timmy-home') -> str | None:
|
||||
if path.name == 'test_codebase_genome_pipeline.py':
|
||||
return host_repo_name
|
||||
stem = path.stem
|
||||
if not stem.startswith('test_') or not stem.endswith('_genome'):
|
||||
return None
|
||||
middle = stem[len('test_'):-len('_genome')]
|
||||
return middle.replace('_', '-') if middle else None
|
||||
|
||||
|
||||
def scan_artifacts(repo_root: Path, host_repo_name: str = 'timmy-home') -> dict[str, list[str]]:
|
||||
artifacts: dict[str, list[str]] = {}
|
||||
for path in sorted(repo_root.rglob('*.md')):
|
||||
rel = path.relative_to(repo_root)
|
||||
repo_name = artifact_repo_name(rel, host_repo_name=host_repo_name)
|
||||
if repo_name is None:
|
||||
continue
|
||||
artifacts.setdefault(repo_name, []).append(rel.as_posix())
|
||||
return artifacts
|
||||
|
||||
|
||||
def scan_tests(repo_root: Path, host_repo_name: str = 'timmy-home') -> set[str]:
|
||||
tests = set()
|
||||
tests_root = repo_root / 'tests'
|
||||
if not tests_root.exists():
|
||||
return tests
|
||||
for path in sorted(tests_root.rglob('test_*.py')):
|
||||
repo_name = test_repo_name(path.relative_to(repo_root), host_repo_name=host_repo_name)
|
||||
if repo_name:
|
||||
tests.add(repo_name)
|
||||
return tests
|
||||
|
||||
|
||||
def build_status_summary(
|
||||
*,
|
||||
repo_root: str | Path,
|
||||
expected_repos: Iterable[str],
|
||||
state: dict | None = None,
|
||||
host_repo_name: str = 'timmy-home',
|
||||
) -> dict:
|
||||
root = Path(repo_root)
|
||||
expected = list(expected_repos)
|
||||
artifacts = scan_artifacts(root, host_repo_name=host_repo_name)
|
||||
tested_repos = scan_tests(root, host_repo_name=host_repo_name)
|
||||
|
||||
coverage = {}
|
||||
duplicates = {}
|
||||
for repo in sorted(artifacts):
|
||||
paths = artifacts[repo]
|
||||
coverage[repo] = {
|
||||
'artifact_paths': paths,
|
||||
'has_test': repo in tested_repos,
|
||||
}
|
||||
if len(paths) > 1:
|
||||
duplicates[repo] = paths
|
||||
|
||||
missing_repos = [repo for repo in expected if repo not in artifacts]
|
||||
next_uncovered_repo = missing_repos[0] if missing_repos else None
|
||||
|
||||
return {
|
||||
'generated_at': datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z'),
|
||||
'total_expected_repos': len(expected),
|
||||
'artifact_count': len(artifacts),
|
||||
'tested_artifact_count': sum(1 for repo in artifacts if repo in tested_repos),
|
||||
'last_repo': (state or {}).get('last_repo'),
|
||||
'next_uncovered_repo': next_uncovered_repo,
|
||||
'missing_repos': missing_repos,
|
||||
'duplicates': duplicates,
|
||||
'artifacts': coverage,
|
||||
}
|
||||
|
||||
|
||||
def render_markdown(summary: dict) -> str:
|
||||
lines = [
|
||||
'# Codebase Genome Status',
|
||||
'',
|
||||
f"Generated: {summary['generated_at']}",
|
||||
'',
|
||||
'## Summary',
|
||||
'',
|
||||
f"- expected repos: {summary['total_expected_repos']}",
|
||||
f"- repos with genome artifacts: {summary['artifact_count']}",
|
||||
f"- repos with genome tests: {summary['tested_artifact_count']}",
|
||||
]
|
||||
if summary.get('last_repo'):
|
||||
lines.append(f"- last repo processed by nightly rotation: {summary['last_repo']}")
|
||||
if summary.get('next_uncovered_repo'):
|
||||
lines.append(f"- next uncovered repo: {summary['next_uncovered_repo']}")
|
||||
|
||||
lines += [
|
||||
'',
|
||||
'## Coverage Matrix',
|
||||
'',
|
||||
'| Repo | Artifact Paths | Test? |',
|
||||
'|------|----------------|-------|',
|
||||
]
|
||||
for repo, data in summary['artifacts'].items():
|
||||
artifact_paths = '<br>'.join(data['artifact_paths'])
|
||||
has_test = 'yes' if data['has_test'] else 'no'
|
||||
lines.append(f'| `{repo}` | `{artifact_paths}` | {has_test} |')
|
||||
|
||||
lines += ['', '## Missing Repo Artifacts', '']
|
||||
if summary['missing_repos']:
|
||||
for repo in summary['missing_repos']:
|
||||
lines.append(f'- `{repo}`')
|
||||
else:
|
||||
lines.append('- none')
|
||||
|
||||
lines += ['', '## Duplicate Artifact Paths', '']
|
||||
if summary['duplicates']:
|
||||
for repo, paths in summary['duplicates'].items():
|
||||
lines.append(f'- `{repo}`')
|
||||
for path in paths:
|
||||
lines.append(f' - `{path}`')
|
||||
else:
|
||||
lines.append('- none')
|
||||
|
||||
return '\n'.join(lines) + '\n'
|
||||
|
||||
|
||||
def load_state(path: str | Path | None) -> dict:
|
||||
if not path:
|
||||
return {}
|
||||
state_path = Path(path).expanduser()
|
||||
if not state_path.exists():
|
||||
return {}
|
||||
return json.loads(state_path.read_text(encoding='utf-8'))
|
||||
|
||||
|
||||
def fetch_org_repo_names(org: str, host: str, token_file: str | Path, *, include_archived: bool = False) -> list[str]:
|
||||
token = Path(token_file).expanduser().read_text(encoding='utf-8').strip()
|
||||
headers = {'Authorization': f'token {token}', 'Accept': 'application/json'}
|
||||
repos = []
|
||||
page = 1
|
||||
while True:
|
||||
req = urllib.request.Request(
|
||||
f"{host.rstrip('/')}/api/v1/orgs/{org}/repos?limit=100&page={page}",
|
||||
headers=headers,
|
||||
)
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
batch = json.loads(resp.read().decode('utf-8'))
|
||||
if not batch:
|
||||
break
|
||||
for repo in batch:
|
||||
if repo.get('archived') and not include_archived:
|
||||
continue
|
||||
name = repo['name']
|
||||
if name.startswith('.'):
|
||||
continue
|
||||
repos.append(name)
|
||||
if len(batch) < 100:
|
||||
break
|
||||
page += 1
|
||||
return sorted(set(repos))
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description='Summarize codebase genome coverage across repos')
|
||||
parser.add_argument('--repo-root', default='.', help='timmy-home repo root')
|
||||
parser.add_argument('--expected-repos-json', help='JSON array of expected repo names')
|
||||
parser.add_argument('--org', default='Timmy_Foundation', help='Gitea org to inspect when expected repos are not provided')
|
||||
parser.add_argument('--host', default='https://forge.alexanderwhitestone.com', help='Gitea host')
|
||||
parser.add_argument('--token-file', default='~/.config/gitea/token', help='Gitea token file for org scan fallback')
|
||||
parser.add_argument('--include-archived', action='store_true', help='Include archived repos in org scan fallback')
|
||||
parser.add_argument('--state-path', default='~/.timmy/codebase_genome_state.json')
|
||||
parser.add_argument('--output', help='Optional markdown output path')
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if args.expected_repos_json:
|
||||
expected = json.loads(args.expected_repos_json)
|
||||
else:
|
||||
expected = fetch_org_repo_names(args.org, args.host, args.token_file, include_archived=args.include_archived)
|
||||
summary = build_status_summary(repo_root=args.repo_root, expected_repos=expected, state=load_state(args.state_path))
|
||||
rendered = render_markdown(summary)
|
||||
print(rendered)
|
||||
if args.output:
|
||||
out = Path(args.output)
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
out.write_text(rendered, encoding='utf-8')
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main())
|
||||
113
tests/test_codebase_genome_status.py
Normal file
113
tests/test_codebase_genome_status.py
Normal file
@@ -0,0 +1,113 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
SCRIPT = ROOT / 'scripts' / 'codebase_genome_status.py'
|
||||
|
||||
spec = importlib.util.spec_from_file_location('codebase_genome_status', str(SCRIPT))
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
sys.modules['codebase_genome_status'] = mod
|
||||
spec.loader.exec_module(mod)
|
||||
|
||||
|
||||
class TestCodebaseGenomeStatus(unittest.TestCase):
|
||||
def test_fetch_org_repo_names_ignores_archived_and_dot_repos(self):
|
||||
payloads = [
|
||||
[
|
||||
{'name': 'timmy-home', 'archived': False},
|
||||
{'name': '.profile', 'archived': False},
|
||||
{'name': 'old-repo', 'archived': True},
|
||||
],
|
||||
[],
|
||||
]
|
||||
|
||||
class FakeResponse:
|
||||
def __init__(self, payload):
|
||||
self.payload = json.dumps(payload).encode('utf-8')
|
||||
def read(self):
|
||||
return self.payload
|
||||
def __enter__(self):
|
||||
return self
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def fake_urlopen(req, timeout=30):
|
||||
return FakeResponse(payloads.pop(0))
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
token_file = pathlib.Path(tmp) / 'token'
|
||||
token_file.write_text('demo-token')
|
||||
from unittest.mock import patch
|
||||
with patch('codebase_genome_status.urllib.request.urlopen', side_effect=fake_urlopen):
|
||||
repos = mod.fetch_org_repo_names('Timmy_Foundation', 'https://forge.example.com', token_file)
|
||||
self.assertEqual(repos, ['timmy-home'])
|
||||
|
||||
def test_collects_artifacts_tests_and_duplicates(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = pathlib.Path(tmp)
|
||||
(root / 'GENOME.md').write_text('# host genome\n')
|
||||
(root / 'the-door-GENOME.md').write_text('# the-door\n')
|
||||
(root / 'genomes' / 'the-nexus').mkdir(parents=True)
|
||||
(root / 'genomes' / 'the-nexus' / 'GENOME.md').write_text('# the-nexus\n')
|
||||
(root / 'genomes' / 'burn-fleet').mkdir(parents=True)
|
||||
(root / 'genomes' / 'burn-fleet' / 'GENOME.md').write_text('# burn-fleet\n')
|
||||
(root / 'genomes' / 'burn-fleet-GENOME.md').write_text('# burn-fleet duplicate\n')
|
||||
(root / 'tests' / 'docs').mkdir(parents=True)
|
||||
(root / 'tests' / 'docs' / 'test_the_door_genome.py').write_text('')
|
||||
(root / 'tests' / 'test_the_nexus_genome.py').write_text('')
|
||||
(root / 'tests' / 'test_codebase_genome_pipeline.py').write_text('')
|
||||
|
||||
summary = mod.build_status_summary(
|
||||
repo_root=root,
|
||||
expected_repos=['timmy-home', 'the-door', 'the-nexus', 'burn-fleet', 'wolf'],
|
||||
state={'last_repo': 'the-nexus'},
|
||||
)
|
||||
|
||||
self.assertEqual(summary['total_expected_repos'], 5)
|
||||
self.assertEqual(summary['artifact_count'], 4)
|
||||
self.assertEqual(summary['tested_artifact_count'], 3)
|
||||
self.assertEqual(summary['next_uncovered_repo'], 'wolf')
|
||||
self.assertEqual(summary['last_repo'], 'the-nexus')
|
||||
self.assertEqual(summary['artifacts']['the-door']['has_test'], True)
|
||||
self.assertEqual(summary['artifacts']['the-nexus']['has_test'], True)
|
||||
self.assertEqual(summary['artifacts']['timmy-home']['has_test'], True)
|
||||
self.assertIn('burn-fleet', summary['duplicates'])
|
||||
self.assertEqual(summary['missing_repos'], ['wolf'])
|
||||
|
||||
def test_render_markdown_contains_required_sections(self):
|
||||
summary = {
|
||||
'generated_at': '2026-04-17T10:00:00Z',
|
||||
'total_expected_repos': 3,
|
||||
'artifact_count': 2,
|
||||
'tested_artifact_count': 1,
|
||||
'last_repo': 'the-door',
|
||||
'next_uncovered_repo': 'wolf',
|
||||
'missing_repos': ['wolf'],
|
||||
'duplicates': {'burn-fleet': ['genomes/burn-fleet/GENOME.md', 'genomes/burn-fleet-GENOME.md']},
|
||||
'artifacts': {
|
||||
'timmy-home': {'artifact_paths': ['GENOME.md'], 'has_test': True},
|
||||
'the-door': {'artifact_paths': ['the-door-GENOME.md'], 'has_test': False},
|
||||
},
|
||||
}
|
||||
rendered = mod.render_markdown(summary)
|
||||
for snippet in [
|
||||
'# Codebase Genome Status',
|
||||
'## Summary',
|
||||
'## Coverage Matrix',
|
||||
'## Missing Repo Artifacts',
|
||||
'## Duplicate Artifact Paths',
|
||||
'the-door-GENOME.md',
|
||||
'genomes/burn-fleet/GENOME.md',
|
||||
'wolf',
|
||||
]:
|
||||
self.assertIn(snippet, rendered)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
56
tests/test_the_nexus_genome.py
Normal file
56
tests/test_the_nexus_genome.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
GENOME = Path("GENOME.md")
|
||||
|
||||
|
||||
def read_genome() -> str:
|
||||
assert GENOME.exists(), "GENOME.md must exist at repo root"
|
||||
return GENOME.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_the_nexus_genome_has_required_sections() -> None:
|
||||
text = read_genome()
|
||||
required = [
|
||||
"# GENOME.md — the-nexus",
|
||||
"## Project Overview",
|
||||
"## Architecture Diagram",
|
||||
"```mermaid",
|
||||
"## Entry Points and Data Flow",
|
||||
"## Key Abstractions",
|
||||
"## API Surface",
|
||||
"## Test Coverage Gaps",
|
||||
"## Security Considerations",
|
||||
"## Runtime Truth and Docs Drift",
|
||||
]
|
||||
missing = [item for item in required if item not in text]
|
||||
assert not missing, missing
|
||||
|
||||
|
||||
def test_the_nexus_genome_captures_current_runtime_contract() -> None:
|
||||
text = read_genome()
|
||||
required = [
|
||||
"server.py",
|
||||
"app.js",
|
||||
"index.html",
|
||||
"portals.json",
|
||||
"vision.json",
|
||||
"BROWSER_CONTRACT.md",
|
||||
"tests/test_browser_smoke.py",
|
||||
"tests/test_repo_truth.py",
|
||||
"nexus/morrowind_harness.py",
|
||||
"nexus/bannerlord_harness.py",
|
||||
"mempalace/tunnel_sync.py",
|
||||
"mcp_servers/desktop_control_server.py",
|
||||
"public/nexus/",
|
||||
]
|
||||
missing = [item for item in required if item not in text]
|
||||
assert not missing, missing
|
||||
|
||||
|
||||
def test_the_nexus_genome_explains_docs_runtime_drift() -> None:
|
||||
text = read_genome()
|
||||
assert "README.md says current `main` does not ship a browser 3D world" in text
|
||||
assert "CLAUDE.md declares root `app.js` and `index.html` as canonical frontend paths" in text
|
||||
assert "tests and browser contract now assume the root frontend exists" in text
|
||||
assert len(text) >= 5000
|
||||
Reference in New Issue
Block a user