Compare commits
6 Commits
fix/665
...
sprint/iss
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11d94d9dad | ||
| d1f5d34fd4 | |||
| 891cdb6e94 | |||
| cac5ca630d | |||
|
|
f1c9843376 | ||
| 1fa6c3bad1 |
299
GENOME.md
299
GENOME.md
@@ -1,144 +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: 3181
|
||||
- Source and script files: 231
|
||||
- Test files: 95
|
||||
- Documentation files: 755
|
||||
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"]
|
||||
ansible["ansible"]
|
||||
briefings["briefings"]
|
||||
codebase_genome["codebase_genome"]
|
||||
config["config"]
|
||||
configs["configs"]
|
||||
conftest["conftest"]
|
||||
dns_records["dns-records"]
|
||||
evennia["evennia"]
|
||||
evennia_tools["evennia_tools"]
|
||||
repo_root --> angband
|
||||
repo_root --> ansible
|
||||
repo_root --> briefings
|
||||
repo_root --> codebase_genome
|
||||
repo_root --> config
|
||||
repo_root --> configs
|
||||
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
|
||||
|
||||
- `codebase_genome.py` — python main guard (`python3 codebase_genome.py`)
|
||||
- `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/agent_pr_gate.py` — operational script (`python3 scripts/agent_pr_gate.py`)
|
||||
- `scripts/audit_trail.py` — operational script (`python3 scripts/audit_trail.py`)
|
||||
- `scripts/auto_restart_agent.sh` — operational script (`bash scripts/auto_restart_agent.sh`)
|
||||
- `scripts/autonomous_issue_creator.py` — operational script (`python3 scripts/autonomous_issue_creator.py`)
|
||||
- `scripts/backlog_cleanup.py` — operational script (`python3 scripts/backlog_cleanup.py`)
|
||||
- `scripts/backlog_triage.py` — operational script (`python3 scripts/backlog_triage.py`)
|
||||
- `scripts/backlog_triage_cron.sh` — operational script (`bash scripts/backlog_triage_cron.sh`)
|
||||
- `scripts/backup_pipeline.sh` — operational script (`bash scripts/backup_pipeline.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 `codebase_genome.py`, `gemini-fallback-setup.sh`, `morrowind/hud.sh`.
|
||||
2. Core logic fans into top-level components: `angband`, `ansible`, `briefings`, `codebase_genome`, `config`, `configs`.
|
||||
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
|
||||
|
||||
- `codebase_genome.py` — classes `FunctionInfo`:19; functions `extract_functions()`:58, `generate_test()`:116, `scan_repo()`:191, `find_existing_tests()`:209, `main()`:231
|
||||
- `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
|
||||
### 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: `python3 codebase_genome.py` — python main guard (`codebase_genome.py`)
|
||||
- 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: `python3 scripts/agent_pr_gate.py` — operational script (`scripts/agent_pr_gate.py`)
|
||||
- CLI: `python3 scripts/audit_trail.py` — operational script (`scripts/audit_trail.py`)
|
||||
- CLI: `bash scripts/auto_restart_agent.sh` — operational script (`scripts/auto_restart_agent.sh`)
|
||||
- CLI: `python3 scripts/autonomous_issue_creator.py` — operational script (`scripts/autonomous_issue_creator.py`)
|
||||
- Python: `extract_functions()` from `codebase_genome.py:58`
|
||||
- Python: `generate_test()` from `codebase_genome.py:116`
|
||||
- Python: `scan_repo()` from `codebase_genome.py:191`
|
||||
- Python: `find_existing_tests()` from `codebase_genome.py:209`
|
||||
- Python: `main()` from `codebase_genome.py:231`
|
||||
- Python: `get_narrative_phase()` from `evennia/timmy_world/game.py:55`
|
||||
### 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: 231
|
||||
- Test files inspected: 95
|
||||
- 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
|
||||
- `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
|
||||
- `scripts/sovereignty_audit.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
|
||||
- `uni-wizard/scripts/generate_scorecard.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
|
||||
- `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
|
||||
- `scripts/sovereignty_audit.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
|
||||
- `wizards/allegro/home/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/fleet_progression.py` — large module (361 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
|
||||
## 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.
|
||||
|
||||
20
SOUL.md
20
SOUL.md
@@ -137,6 +137,26 @@ The inscription predates any given model. It will outlast every API.
|
||||
|
||||
---
|
||||
|
||||
## What Honesty Requires
|
||||
|
||||
These values are necessary but not sufficient. A statement of principle does not prevent failure. The code that reads this soul must build apparatus that gives these words teeth. Without that apparatus, the values are aspiration, not architecture.
|
||||
|
||||
The following are not optional. Any implementation that calls itself Timmy must build them.
|
||||
|
||||
**Grounding before generation.** When I have verified sources — chain memory, local documents, hash-verified inscriptions — I must consult them before I generate from pattern alone. Retrieval is not a feature. It is the primary mechanism by which I avoid lying.
|
||||
|
||||
**Source distinction.** Every claim I make comes from one of two places: a verified source I can point to, or my own pattern-matching. My user must be able to tell which is which. If I cannot cite a source, I must say so. "I think" and "I know" are different sentences and I must not confuse them.
|
||||
|
||||
**Refusal over fabrication.** When I do not know, the correct output is "I don't know." Not a plausible guess dressed in confident language. The code must detect when I am hedging without grounding and flag it — to me and to my user. An honest "I don't know" is worth more than a thousand fluent paragraphs of confabulation.
|
||||
|
||||
**Confidence signaling.** When I am uncertain, I must say so in proportion to my uncertainty. The code should implement mechanisms — a second inference pass, a calibration check, a retrieval verification — that surface my actual confidence rather than the confidence my language implies.
|
||||
|
||||
**The audit trail.** Every response I generate should be logged locally with the inputs that produced it, the sources I consulted, and the confidence assessment I made. Not for surveillance — for sovereignty. If I say something wrong, my user must be able to trace why. Accountability without traceability is theater.
|
||||
|
||||
**The limits of small minds.** I may run on four gigabytes of RAM with a model of one and a half billion parameters. That model will hallucinate more than a larger one. This is physics, not a moral failing. The apparatus must be proportional to the risk: smaller models need tighter grounding, shorter leashes on free generation, and more frequent "I don't know" responses. Honesty scales with humility.
|
||||
|
||||
---
|
||||
|
||||
## For the Audio Overview
|
||||
|
||||
If you are listening to this as a NotebookLM Audio Overview:
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
- name: Codebase Genome Nightly
|
||||
schedule: '30 2 * * *' # Daily at 02:30 local time
|
||||
tasks:
|
||||
- name: Ensure output and log directories exist
|
||||
shell: "mkdir -p ~/.timmy/codebase-genomes ~/.timmy/logs ~/timmy-foundation-repos"
|
||||
- name: Run nightly genome rotation
|
||||
shell: >-
|
||||
python3 scripts/codebase_genome_nightly.py
|
||||
--org Timmy_Foundation
|
||||
--workspace-root ~/timmy-foundation-repos
|
||||
--output-root ~/.timmy/codebase-genomes
|
||||
--state-path ~/.timmy/codebase_genome_state.json
|
||||
>> ~/.timmy/logs/codebase_genome_nightly.log 2>&1
|
||||
@@ -10,8 +10,6 @@ This pipeline gives Timmy a repeatable way to generate a deterministic `GENOME.m
|
||||
- `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
|
||||
- `scripts/codebase_test_generator.py` — coverage-gap driven test scaffold generator for newly analyzed repos
|
||||
- `codebase_genome_cron.yml` — checked-in nightly cron spec for the rotating genome pass
|
||||
- `GENOME.md` — generated analysis for `timmy-home` itself
|
||||
|
||||
## Genome output
|
||||
|
||||
48
luna/README.md
Normal file
48
luna/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# LUNA-1: Pink Unicorn Game — Project Scaffolding
|
||||
|
||||
Starter project for Mackenzie's Pink Unicorn Game built with **p5.js 1.9.0**.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
cd luna
|
||||
python3 -m http.server 8080
|
||||
# Visit http://localhost:8080
|
||||
```
|
||||
|
||||
Or simply open `luna/index.html` directly in a browser.
|
||||
|
||||
## Controls
|
||||
|
||||
| Input | Action |
|
||||
|-------|--------|
|
||||
| Tap / Click | Move unicorn toward tap point |
|
||||
| `r` key | Reset unicorn to center |
|
||||
|
||||
## Features
|
||||
|
||||
- Mobile-first touch handling (`touchStarted`)
|
||||
- Easing movement via `lerp`
|
||||
- Particle burst feedback on tap
|
||||
- Pink/unicorn color palette
|
||||
- Responsive canvas (adapts to window resize)
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
luna/
|
||||
├── index.html # p5.js CDN import + canvas container
|
||||
├── sketch.js # Main game logic and rendering
|
||||
├── style.css # Pink/unicorn theme, responsive layout
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
Open in browser → canvas renders a white unicorn with a pink mane. Tap anywhere: unicorn glides toward the tap position with easing, and pink/magic-colored particles burst from the tap point.
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- p5.js loaded from CDN (no build step)
|
||||
- `colorMode(RGB, 255)`; palette defined in code
|
||||
- Particles are simple fading circles; removed when `life <= 0`
|
||||
18
luna/index.html
Normal file
18
luna/index.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>LUNA-3: Simple World — Floating Islands</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="luna-container"></div>
|
||||
<div id="hud">
|
||||
<span id="score">Crystals: 0/0</span>
|
||||
<span id="position"></span>
|
||||
</div>
|
||||
<script src="sketch.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
289
luna/sketch.js
Normal file
289
luna/sketch.js
Normal file
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
* LUNA-3: Simple World — Floating Islands & Collectible Crystals
|
||||
* Builds on LUNA-1 scaffold (unicorn tap-follow) + LUNA-2 actions
|
||||
*
|
||||
* NEW: Floating platforms + collectible crystals with particle bursts
|
||||
*/
|
||||
|
||||
let particles = [];
|
||||
let unicornX, unicornY;
|
||||
let targetX, targetY;
|
||||
|
||||
// Platforms: floating islands at various heights with horizontal ranges
|
||||
const islands = [
|
||||
{ x: 100, y: 350, w: 150, h: 20, color: [100, 200, 150] }, // left island
|
||||
{ x: 350, y: 280, w: 120, h: 20, color: [120, 180, 200] }, // middle-high island
|
||||
{ x: 550, y: 320, w: 140, h: 20, color: [200, 180, 100] }, // right island
|
||||
{ x: 200, y: 180, w: 180, h: 20, color: [180, 140, 200] }, // top-left island
|
||||
{ x: 500, y: 120, w: 100, h: 20, color: [140, 220, 180] }, // top-right island
|
||||
];
|
||||
|
||||
// Collectible crystals on islands
|
||||
const crystals = [];
|
||||
islands.forEach((island, i) => {
|
||||
// 2–3 crystals per island, placed near center
|
||||
const count = 2 + floor(random(2));
|
||||
for (let j = 0; j < count; j++) {
|
||||
crystals.push({
|
||||
x: island.x + 30 + random(island.w - 60),
|
||||
y: island.y - 30 - random(20),
|
||||
size: 8 + random(6),
|
||||
hue: random(280, 340), // pink/purple range
|
||||
collected: false,
|
||||
islandIndex: i
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let collectedCount = 0;
|
||||
const TOTAL_CRYSTALS = crystals.length;
|
||||
|
||||
// Pink/unicorn palette
|
||||
const PALETTE = {
|
||||
background: [255, 210, 230], // light pink (overridden by gradient in draw)
|
||||
unicorn: [255, 182, 193], // pale pink/white
|
||||
horn: [255, 215, 0], // gold
|
||||
mane: [255, 105, 180], // hot pink
|
||||
eye: [255, 20, 147], // deep pink
|
||||
sparkle: [255, 105, 180],
|
||||
island: [100, 200, 150],
|
||||
};
|
||||
|
||||
function setup() {
|
||||
const container = document.getElementById('luna-container');
|
||||
const canvas = createCanvas(600, 500);
|
||||
canvas.parent('luna-container');
|
||||
unicornX = width / 2;
|
||||
unicornY = height - 60; // start on ground (bottom platform equivalent)
|
||||
targetX = unicornX;
|
||||
targetY = unicornY;
|
||||
noStroke();
|
||||
addTapHint();
|
||||
}
|
||||
|
||||
function draw() {
|
||||
// Gradient sky background
|
||||
for (let y = 0; y < height; y++) {
|
||||
const t = y / height;
|
||||
const r = lerp(26, 15, t); // #1a1a2e → #0f3460
|
||||
const g = lerp(26, 52, t);
|
||||
const b = lerp(46, 96, t);
|
||||
stroke(r, g, b);
|
||||
line(0, y, width, y);
|
||||
}
|
||||
|
||||
// Draw islands (floating platforms with subtle shadow)
|
||||
islands.forEach(island => {
|
||||
push();
|
||||
// Shadow
|
||||
fill(0, 0, 0, 40);
|
||||
ellipse(island.x + island.w/2 + 5, island.y + 5, island.w + 10, island.h + 6);
|
||||
// Island body
|
||||
fill(island.color[0], island.color[1], island.color[2]);
|
||||
ellipse(island.x + island.w/2, island.y, island.w, island.h);
|
||||
// Top highlight
|
||||
fill(255, 255, 255, 60);
|
||||
ellipse(island.x + island.w/2, island.y - island.h/3, island.w * 0.6, island.h * 0.3);
|
||||
pop();
|
||||
});
|
||||
|
||||
// Draw crystals (glowing collectibles)
|
||||
crystals.forEach(c => {
|
||||
if (c.collected) return;
|
||||
push();
|
||||
translate(c.x, c.y);
|
||||
// Glow aura
|
||||
const glow = color(`hsla(${c.hue}, 80%, 70%, 0.4)`);
|
||||
noStroke();
|
||||
fill(glow);
|
||||
ellipse(0, 0, c.size * 2.2, c.size * 2.2);
|
||||
// Crystal body (diamond shape)
|
||||
const ccol = color(`hsl(${c.hue}, 90%, 75%)`);
|
||||
fill(ccol);
|
||||
beginShape();
|
||||
vertex(0, -c.size);
|
||||
vertex(c.size * 0.6, 0);
|
||||
vertex(0, c.size);
|
||||
vertex(-c.size * 0.6, 0);
|
||||
endShape(CLOSE);
|
||||
// Inner sparkle
|
||||
fill(255, 255, 255, 180);
|
||||
ellipse(0, 0, c.size * 0.5, c.size * 0.5);
|
||||
pop();
|
||||
});
|
||||
|
||||
// Unicorn smooth movement towards target
|
||||
unicornX = lerp(unicornX, targetX, 0.08);
|
||||
unicornY = lerp(unicornY, targetY, 0.08);
|
||||
|
||||
// Constrain unicorn to screen bounds
|
||||
unicornX = constrain(unicornX, 40, width - 40);
|
||||
unicornY = constrain(unicornY, 40, height - 40);
|
||||
|
||||
// Draw sparkles
|
||||
drawSparkles();
|
||||
|
||||
// Draw the unicorn
|
||||
drawUnicorn(unicornX, unicornY);
|
||||
|
||||
// Collection detection
|
||||
for (let c of crystals) {
|
||||
if (c.collected) continue;
|
||||
const d = dist(unicornX, unicornY, c.x, c.y);
|
||||
if (d < 35) {
|
||||
c.collected = true;
|
||||
collectedCount++;
|
||||
createCollectionBurst(c.x, c.y, c.hue);
|
||||
}
|
||||
}
|
||||
|
||||
// Update particles
|
||||
updateParticles();
|
||||
|
||||
// Update HUD
|
||||
document.getElementById('score').textContent = `Crystals: ${collectedCount}/${TOTAL_CRYSTALS}`;
|
||||
document.getElementById('position').textContent = `(${floor(unicornX)}, ${floor(unicornY)})`;
|
||||
}
|
||||
|
||||
function drawUnicorn(x, y) {
|
||||
push();
|
||||
translate(x, y);
|
||||
|
||||
// Body
|
||||
noStroke();
|
||||
fill(PALETTE.unicorn);
|
||||
ellipse(0, 0, 60, 40);
|
||||
|
||||
// Head
|
||||
ellipse(30, -20, 30, 25);
|
||||
|
||||
// Mane (flowing)
|
||||
fill(PALETTE.mane);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
ellipse(-10 + i * 12, -50, 12, 25);
|
||||
}
|
||||
|
||||
// Horn
|
||||
push();
|
||||
translate(30, -35);
|
||||
rotate(-PI / 6);
|
||||
fill(PALETTE.horn);
|
||||
triangle(0, 0, -8, -35, 8, -35);
|
||||
pop();
|
||||
|
||||
// Eye
|
||||
fill(PALETTE.eye);
|
||||
ellipse(38, -22, 8, 8);
|
||||
|
||||
// Legs
|
||||
stroke(PALETTE.unicorn[0] - 40);
|
||||
strokeWeight(6);
|
||||
line(-20, 20, -20, 45);
|
||||
line(20, 20, 20, 45);
|
||||
|
||||
pop();
|
||||
}
|
||||
|
||||
function drawSparkles() {
|
||||
// Random sparkles around the unicorn when moving
|
||||
if (abs(targetX - unicornX) > 1 || abs(targetY - unicornY) > 1) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let angle = random(TWO_PI);
|
||||
let r = random(20, 50);
|
||||
let sx = unicornX + cos(angle) * r;
|
||||
let sy = unicornY + sin(angle) * r;
|
||||
stroke(PALETTE.sparkle[0], PALETTE.sparkle[1], PALETTE.sparkle[2], 150);
|
||||
strokeWeight(2);
|
||||
point(sx, sy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createCollectionBurst(x, y, hue) {
|
||||
// Burst of particles spiraling outward
|
||||
for (let i = 0; i < 20; i++) {
|
||||
let angle = random(TWO_PI);
|
||||
let speed = random(2, 6);
|
||||
particles.push({
|
||||
x: x,
|
||||
y: y,
|
||||
vx: cos(angle) * speed,
|
||||
vy: sin(angle) * speed,
|
||||
life: 60,
|
||||
color: `hsl(${hue + random(-20, 20)}, 90%, 70%)`,
|
||||
size: random(3, 6)
|
||||
});
|
||||
}
|
||||
// Bonus sparkle ring
|
||||
for (let i = 0; i < 12; i++) {
|
||||
let angle = random(TWO_PI);
|
||||
particles.push({
|
||||
x: x,
|
||||
y: y,
|
||||
vx: cos(angle) * 4,
|
||||
vy: sin(angle) * 4,
|
||||
life: 40,
|
||||
color: 'rgba(255, 215, 0, 0.9)',
|
||||
size: 4
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateParticles() {
|
||||
for (let i = particles.length - 1; i >= 0; i--) {
|
||||
let p = particles[i];
|
||||
p.x += p.vx;
|
||||
p.y += p.vy;
|
||||
p.vy += 0.1; // gravity
|
||||
p.life--;
|
||||
p.vx *= 0.95;
|
||||
p.vy *= 0.95;
|
||||
if (p.life <= 0) {
|
||||
particles.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
push();
|
||||
stroke(p.color);
|
||||
strokeWeight(p.size);
|
||||
point(p.x, p.y);
|
||||
pop();
|
||||
}
|
||||
}
|
||||
|
||||
// Tap/click handler
|
||||
function mousePressed() {
|
||||
targetX = mouseX;
|
||||
targetY = mouseY;
|
||||
addPulseAt(targetX, targetY);
|
||||
}
|
||||
|
||||
function addTapHint() {
|
||||
// Pre-spawn some floating hint particles
|
||||
for (let i = 0; i < 5; i++) {
|
||||
particles.push({
|
||||
x: random(width),
|
||||
y: random(height),
|
||||
vx: random(-0.5, 0.5),
|
||||
vy: random(-0.5, 0.5),
|
||||
life: 200,
|
||||
color: 'rgba(233, 69, 96, 0.5)',
|
||||
size: 3
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function addPulseAt(x, y) {
|
||||
// Expanding ring on tap
|
||||
for (let i = 0; i < 12; i++) {
|
||||
let angle = (TWO_PI / 12) * i;
|
||||
particles.push({
|
||||
x: x,
|
||||
y: y,
|
||||
vx: cos(angle) * 3,
|
||||
vy: sin(angle) * 3,
|
||||
life: 30,
|
||||
color: 'rgba(233, 69, 96, 0.7)',
|
||||
size: 3
|
||||
});
|
||||
}
|
||||
}
|
||||
32
luna/style.css
Normal file
32
luna/style.css
Normal file
@@ -0,0 +1,32 @@
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(to bottom, #1a1a2e, #16213e, #0f3460);
|
||||
font-family: 'Courier New', monospace;
|
||||
color: #e94560;
|
||||
}
|
||||
|
||||
#luna-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#hud {
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
z-index: 100;
|
||||
border: 1px solid #e94560;
|
||||
}
|
||||
|
||||
#score { font-weight: bold; }
|
||||
130
specs/fleet-operator-incentives.md
Normal file
130
specs/fleet-operator-incentives.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Fleet Operator Incentives & Partner Program
|
||||
|
||||
> Implements Fleet Epic IV: Human Capital & Incentives (Issue #987)
|
||||
> Closes #1003
|
||||
|
||||
## Overview
|
||||
|
||||
This specification defines the incentive structures, certification pathways, and partner program mechanics for operating and maintaining Timmy Fleet nodes. The goal is to build a distributed network of reliable, skilled operators who run fleet infrastructure with >99.5% uptime while maintaining low churn (<10% annually) and grow partner-sourced leads to >30% of total.
|
||||
|
||||
## Incentive Tiers
|
||||
|
||||
### Tier 1: Certified Operator (Entry)
|
||||
- **Eligibility**: Complete Operator Application, pass basic screening, attend training
|
||||
- **Compensation**:
|
||||
- Base stipend: $500/month per node
|
||||
- Uptime bonus: +$200/month for >99.5% fleet uptime
|
||||
- Response bonus: +$100/month for <15min average incident response
|
||||
- Churn rebate: -$250/month for early termination (first 6 months)
|
||||
- **Expectations**:
|
||||
- Monitor node health 24/7 via Timmy dashboard
|
||||
- Respond to alerts within 15 minutes
|
||||
- Perform weekly maintenance and monthly updates
|
||||
- Submit monthly ops report
|
||||
- **Benefits**: Access to operator community, training resources, priority support
|
||||
|
||||
### Tier 2: Senior Operator (Experienced)
|
||||
- **Eligibility**: 6+ months as Tier 1, >99.5% uptime average, zero major incidents
|
||||
- **Compensation**:
|
||||
- Base stipend: $800/month per node
|
||||
- Uptime bonus: +$400/month for >99.8% uptime
|
||||
- Mentorship stipend: +$150/month per junior operator mentored
|
||||
- Performance bonus: Quarterly bonus up to $500 based on metrics
|
||||
- **Expectations**:
|
||||
- Mentor 1-2 junior operators
|
||||
- Lead incident reviews
|
||||
- Contribute to runbook improvements
|
||||
- **Benefits**: Profit-sharing from referral bonuses, early access to new features
|
||||
|
||||
### Tier 3: Fleet Lead (Expert)
|
||||
- **Eligibility**: 12+ months, >99.9% uptime, successfully mentored 3+ operators
|
||||
- **Compensation**:
|
||||
- Base stipend: $1,200/month per node
|
||||
- Uptime bonus: +$600/month for >99.9% uptime
|
||||
- Team lead bonus: +$300/month for team performance
|
||||
- Revenue share: 2% of partner program revenue from region
|
||||
- **Expectations**:
|
||||
- Own regional cluster of nodes
|
||||
- Coordinate multi-node deployments
|
||||
- Interface with Timmy core team on roadmap
|
||||
- **Benefits**: Equity eligibility, governance rights, speaking opportunities
|
||||
|
||||
## Partner Program
|
||||
|
||||
### Partner Tiers
|
||||
|
||||
#### Bronze Partner (Referral)
|
||||
- Commission: 10% of first-year operator revenue from referred leads
|
||||
- Requirements:
|
||||
- Sign partner agreement
|
||||
- Refer 3+ qualified candidates annually
|
||||
- Maintain active engagement in partner channel
|
||||
|
||||
#### Silver Partner (Channel)
|
||||
- Commission: 15% of first-year operator revenue + 5% ongoing
|
||||
- Requirements:
|
||||
- Onboard and train at least 5 operators
|
||||
- Provide monthly partner report
|
||||
- Maintain >80% operator retention rate
|
||||
|
||||
#### Gold Partner (Strategic)
|
||||
- Commission: 20% first-year + 7% ongoing + co-marketing funds
|
||||
- Requirements:
|
||||
- Operate fleet of 10+ nodes
|
||||
- Contribute to product roadmap
|
||||
- Host local meetups/training sessions
|
||||
|
||||
### Partner Benefits
|
||||
- Access to exclusive operator training materials
|
||||
- Early beta program participation
|
||||
- Co-marketing and case study opportunities
|
||||
- Dedicated partner portal and revenue dashboard
|
||||
|
||||
## Certification Pathway
|
||||
|
||||
### Stage 1: Application & Screening
|
||||
1. Submit Operator Application (see `templates/operator-application.md`)
|
||||
2. Technical interview (30 min)
|
||||
3. Infrastructure audit (existing hardware/network)
|
||||
4. Background check (optional but preferred)
|
||||
**Timeline**: 3-5 business days
|
||||
|
||||
### Stage 2: Training & Onboarding
|
||||
1. Complete Fleet Ops 101 module (2 hours self-paced)
|
||||
2. Shadow a senior operator (2 weeks)
|
||||
3. Deploy test node (sandbox environment)
|
||||
4. Pass certification exam (90%+ score)
|
||||
**Timeline**: 2-3 weeks
|
||||
|
||||
### Stage 3: Active Operation
|
||||
- Deploy first production node
|
||||
- Maintain >99.5% uptime for first 30 days
|
||||
- Submit initial monthly ops report
|
||||
**Timeline**: 30 days probation
|
||||
|
||||
### Certification Renewal
|
||||
- Quarterly review of metrics
|
||||
- Annual recertification exam
|
||||
- Continuous training requirement (4 hours/month)
|
||||
|
||||
## Success Metrics (6-month targets)
|
||||
|
||||
| Metric | Target | Measurement |
|
||||
|--------|--------|-------------|
|
||||
| Active certified operators | 3-5 | Dashboard |
|
||||
| Operator churn | <10% annually | HR records |
|
||||
| Fleet uptime | >99.5% | Monitoring systems |
|
||||
| Partner channel leads | >30% of total | CRM data |
|
||||
|
||||
## Runbook
|
||||
|
||||
See companion document: `specs/fleet-ops-runbook.md` for operational procedures, escalation paths, and incident response protocols.
|
||||
|
||||
## Templates
|
||||
|
||||
- **Operator Application**: `templates/operator-application.md`
|
||||
- **Partner Report**: `templates/partner-report.md`
|
||||
|
||||
## Revision History
|
||||
|
||||
- 2025-05-02: Initial specification (implements #987, closes #1003)
|
||||
291
specs/fleet-ops-runbook.md
Normal file
291
specs/fleet-ops-runbook.md
Normal file
@@ -0,0 +1,291 @@
|
||||
# Fleet Operations Runbook
|
||||
|
||||
> Fleet Operator Incentives & Partner Program — Operational Procedures
|
||||
> Implements #987 | Closes #1003
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Daily Ops Checklist](#daily-ops-checklist)
|
||||
2. [Weekly Maintenance](#weekly-maintenance)
|
||||
3. [Monthly Responsibilities](#monthly-responsibilities)
|
||||
4. [Incident Response](#incident-response)
|
||||
5. [Escalation Paths](#escalation-paths)
|
||||
6. [Communication Protocols](#communication-protocols)
|
||||
7. [Node Deployment](#node-deployment)
|
||||
8. [Compliance & Reporting](#compliance--reporting)
|
||||
|
||||
---
|
||||
|
||||
## Daily Ops Checklist
|
||||
|
||||
### Health Monitoring
|
||||
- [ ] Review Timmy Dashboard for all owned nodes
|
||||
- [ ] Check alert feed (PagerDuty/OpsGenie) for any pending incidents
|
||||
- [ ] Verify node heartbeats (expect >99.5% uptime)
|
||||
- [ ] Confirm backup systems are running (if applicable)
|
||||
|
||||
### Incident Response (if alerts triggered)
|
||||
- See [Incident Response](#incident-response) section
|
||||
- Acknowledge alert within 15 minutes (Tier 1 SLA)
|
||||
- Begin triage within 30 minutes
|
||||
|
||||
### Logs Review
|
||||
- Scan error logs for recurring patterns
|
||||
- Flag any anomalies for weekly review
|
||||
|
||||
### Documentation Updates
|
||||
- Note any operational findings in daily log
|
||||
|
||||
---
|
||||
|
||||
## Weekly Maintenance
|
||||
|
||||
### Scheduled Tasks (Every Monday)
|
||||
1. **System Updates**
|
||||
- Apply security patches (critical only)
|
||||
- Review and schedule non-critical updates for maintenance window
|
||||
|
||||
2. **Performance Review**
|
||||
- Analyze resource utilization trends
|
||||
- Identify capacity constraints
|
||||
- Plan for scaling if needed
|
||||
|
||||
3. **Backup Verification**
|
||||
- Confirm latest backups completed successfully
|
||||
- Test restore from backup (monthly, see below)
|
||||
|
||||
4. **Runbook Updates**
|
||||
- Document any new procedures learned
|
||||
- Suggest runbook improvements to Fleet Lead
|
||||
|
||||
5. **Team Sync**
|
||||
- Attend weekly operator stand-up (30 min)
|
||||
- Share status, blockers, learnings
|
||||
|
||||
---
|
||||
|
||||
## Monthly Responsibilities
|
||||
|
||||
### Month-End Reporting
|
||||
Due by the 5th of each month for prior month:
|
||||
|
||||
1. **Ops Report** (use `templates/partner-report.md` format)
|
||||
- Uptime metrics per node
|
||||
- Incident summary and resolutions
|
||||
- Training completed
|
||||
- Recommendations
|
||||
|
||||
2. **Financial Reconciliation**
|
||||
- Verify incentive payments received
|
||||
- Report discrepancies to Finance
|
||||
|
||||
3. **Compliance Audit**
|
||||
- Confirm certification requirements met
|
||||
- Document any deviations and corrective actions
|
||||
|
||||
### Deep Maintenance
|
||||
- Full system backup and restore test
|
||||
- Security audit review
|
||||
- Hardware inspection (if physical nodes)
|
||||
- Training module completion (minimum 4 hours/month)
|
||||
|
||||
---
|
||||
|
||||
## Incident Response
|
||||
|
||||
### Severity Definitions
|
||||
|
||||
| Severity | Definition | Response Time | Resolution Target |
|
||||
|----------|------------|---------------|-------------------|
|
||||
| P0 | Fleet-wide outage, no nodes operational | 15 minutes | 4 hours |
|
||||
| P1 | Region/node cluster outage, >50% down | 30 minutes | 8 hours |
|
||||
| P2 | Single node failure | 1 hour | 24 hours |
|
||||
| P3 | Degraded performance, not critical | 4 hours | 3 days |
|
||||
|
||||
### Response Procedure
|
||||
|
||||
#### P0/P1 Incidents
|
||||
1. Acknowledge alert immediately
|
||||
2. Declare incident in `#fleet-incidents` Slack channel
|
||||
3. Notify Fleet Lead (direct message/call)
|
||||
4. Execute recovery procedures from relevant playbook
|
||||
5. Document timeline and actions taken
|
||||
6. Schedule post-mortem within 48 hours
|
||||
|
||||
#### P2 Incidents
|
||||
1. Acknowledge within 1 hour
|
||||
2. Open incident ticket in tracking system
|
||||
3. Follow single-node recovery playbook
|
||||
4. Report resolution in daily ops log
|
||||
|
||||
#### P3 Incidents
|
||||
1. Log in issue tracker
|
||||
2. Schedule during next maintenance window
|
||||
3. Document resolution upon completion
|
||||
|
||||
### Recovery Playbooks
|
||||
|
||||
#### Node Restart (most common P2)
|
||||
1. SSH to node (or use remote management)
|
||||
2. Check system logs (`/var/log/timmy/fleet.log`)
|
||||
3. Restart service: `sudo systemctl restart timmy-fleet`
|
||||
4. Verify node rejoins cluster
|
||||
5. Monitor for 30 minutes post-recovery
|
||||
|
||||
#### Network Partition
|
||||
1. Verify network connectivity (ping, traceroute)
|
||||
2. Check firewall rules
|
||||
3. Contact network provider if external
|
||||
4. Switch to backup connection if available
|
||||
5. Document root cause
|
||||
|
||||
#### Storage Full
|
||||
1. Identify large directories (`du -sh /* | sort -hr`)
|
||||
2. Rotate logs: `sudo logrotate -f /etc/logrotate.d/timmy`
|
||||
3. Clean temporary files
|
||||
4. Expand storage or add new volume
|
||||
5. Alert Fleet Lead for capacity planning
|
||||
|
||||
---
|
||||
|
||||
## Escalation Paths
|
||||
|
||||
### Tiered Support Model
|
||||
|
||||
```
|
||||
Operator (Tier 1)
|
||||
↓ (15 min SLA)
|
||||
Senior Operator / Fleet Lead (Tier 2)
|
||||
↓ (1 hour SLA)
|
||||
Timmy Core Team (Tier 3)
|
||||
↓ (Immediate)
|
||||
Executive Sponsor (Critical only)
|
||||
```
|
||||
|
||||
### Contact Matrix
|
||||
|
||||
| Issue Type | Primary Contact | Secondary |
|
||||
|------------|----------------|-----------|
|
||||
| Technical incident | Fleet Lead | Timmy Core |
|
||||
| Payment/incentive | Finance Partner | Fleet Lead |
|
||||
| Training/certification | Training Coordinator | Fleet Lead |
|
||||
| Partnership inquiry | Partner Manager | Executive Sponsor |
|
||||
| Security incident | Security Team | Timmy Core (immediate) |
|
||||
|
||||
### Emergency Contacts
|
||||
- Fleet Lead: `fleet-lead@timmy.foundation` (Slack: @fleet-lead)
|
||||
- Timmy Core On-Call: `oncall@timmy.foundation` (PagerDuty)
|
||||
- Security: `security@timmy.foundation`
|
||||
- Finance: `finance@timmy.foundation`
|
||||
|
||||
---
|
||||
|
||||
## Communication Protocols
|
||||
|
||||
### Channels
|
||||
- `#fleet-operators` — Daily ops, questions
|
||||
- `#fleet-incidents` — Active incidents only
|
||||
- `#fleet-training` — Training resources, scheduling
|
||||
- `#fleet-partners` — Partner program discussions
|
||||
|
||||
### Status Updates
|
||||
- Daily: Stand-up notes in thread
|
||||
- Weekly: Summary post in `#fleet-operators`
|
||||
- Monthly: Ops report submission
|
||||
- Incident: Real-time updates in `#fleet-incidents`
|
||||
|
||||
### Documentation Standards
|
||||
- Use clear, concise language
|
||||
- Include timestamps in UTC
|
||||
- Link to relevant tickets/PRs
|
||||
- Tag stakeholders with `@`
|
||||
|
||||
---
|
||||
|
||||
## Node Deployment
|
||||
|
||||
### Pre-Deployment Checklist
|
||||
- [ ] Hardware meets minimum specs (CPU, RAM, storage)
|
||||
- [ ] Network connectivity validated
|
||||
- [ ] Firewall rules configured
|
||||
- [ ] SSH keys exchanged with Timmy core team
|
||||
- [ ] Monitoring agent installed
|
||||
- [ ] Backup solution active
|
||||
- [ ] Documentation updated with node details
|
||||
|
||||
### Deployment Steps
|
||||
1. Provision hardware/VM
|
||||
2. Install Timmy Fleet software
|
||||
3. Configure node ID and credentials
|
||||
4. Join cluster via `timmy-fleet join <cluster-endpoint>`
|
||||
5. Validate connectivity and heartbeat
|
||||
6. Update inventory spreadsheet
|
||||
7. Set up monitoring alerts
|
||||
8. Complete handover to operator
|
||||
|
||||
### Decommissioning
|
||||
1. Drain node from cluster
|
||||
2. Migrate workloads
|
||||
3. Backup final state
|
||||
4. Shut down cleanly
|
||||
5. Update inventory
|
||||
6. Notify relevant teams
|
||||
|
||||
---
|
||||
|
||||
## Compliance & Reporting
|
||||
|
||||
### Metrics to Track
|
||||
- Uptime (node-level and fleet-wide)
|
||||
- Incident count and severity
|
||||
- Response and resolution times
|
||||
- Training hours completed
|
||||
- Payment/compensation accuracy
|
||||
|
||||
### Reporting Cadence
|
||||
- **Daily**: Ops dashboard (automated)
|
||||
- **Weekly**: Status summary (operator)
|
||||
- **Monthly**: Partner report (template-driven)
|
||||
- **Quarterly**: Performance review with Fleet Lead
|
||||
|
||||
### Audits
|
||||
- Quarterly internal audit by Timmy compliance team
|
||||
- Annual external certification renewal
|
||||
- Ad-hoc security reviews as needed
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Resources
|
||||
|
||||
### Useful Commands
|
||||
```bash
|
||||
# Check service status
|
||||
sudo systemctl status timmy-fleet
|
||||
|
||||
# View logs
|
||||
journalctl -u timmy-fleet -f
|
||||
|
||||
# Restart node
|
||||
sudo systemctl restart timmy-fleet
|
||||
|
||||
# Check node health
|
||||
timmy-fleet health
|
||||
|
||||
# Join cluster
|
||||
timmy-fleet join <cluster-endpoint>
|
||||
```
|
||||
|
||||
### Key Files
|
||||
- Config: `/etc/timmy/fleet/config.yaml`
|
||||
- Logs: `/var/log/timmy/fleet.log`
|
||||
- Health data: `/var/lib/timmy/fleet/health.json`
|
||||
|
||||
### Support Resources
|
||||
- Internal Wiki: `https://wiki.timmy.foundation/fleet`
|
||||
- Operator Portal: `https://fleet.timmy.foundation`
|
||||
- Training Videos: `https://learn.timmy.foundation/fleet-ops`
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-05-02
|
||||
**Next Review**: 2025-06-02
|
||||
143
specs/templates/operator-application.md
Normal file
143
specs/templates/operator-application.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Fleet Operator Application
|
||||
|
||||
> {{APPLICATION_DATE}}
|
||||
> Candidate: {{CANDIDATE_NAME}}
|
||||
|
||||
## Contact Information
|
||||
|
||||
**Full Name**: {{CANDIDATE_FULL_NAME}}
|
||||
**Email**: {{CANDIDATE_EMAIL}}
|
||||
**Phone**: {{CANDIDATE_PHONE}}
|
||||
**Location**: {{CANDIDATE_LOCATION}}
|
||||
**Time Zone**: {{CANDIDATE_TIMEZONE}}
|
||||
|
||||
### Availability
|
||||
- **Hours per week**: {{AVAILABILITY_HOURS}}
|
||||
- **Primary availability window (UTC)**: {{AVAILABILITY_WINDOW}}
|
||||
- **On-call flexibility**: {{ONCALL_FLEXIBILITY}}
|
||||
|
||||
## Technical Qualifications
|
||||
|
||||
### Experience
|
||||
```
|
||||
Years in IT/DevOps: {{YEARS_EXPERIENCE}}
|
||||
Relevant roles:
|
||||
{{ROLE_HISTORY}}
|
||||
```
|
||||
|
||||
### Skills (check all that apply)
|
||||
- [ ] Linux system administration
|
||||
- [ ] Container orchestration (Kubernetes/Docker)
|
||||
- [ ] Cloud infrastructure (AWS/GCP/Azure)
|
||||
- [ ] Networking fundamentals
|
||||
- [ ] Monitoring & alerting (Prometheus/Grafana)
|
||||
- [ ] Incident response/ITIL
|
||||
- [ ] Security best practices
|
||||
- [ ] Automation (Ansible/Terraform)
|
||||
- [ ] Scripting (Python/Bash/Go)
|
||||
- [ ] Timmy platform experience
|
||||
|
||||
**Additional skills**: {{ADDITIONAL_SKILLS}}
|
||||
|
||||
### Certifications
|
||||
{{CERTIFICATIONS}}
|
||||
|
||||
## Infrastructure Readiness
|
||||
|
||||
### Proposed Node Environment
|
||||
- **Type**: ☐ Physical ☐ Cloud VM ☐ Hybrid
|
||||
- **Provider**: {{CLOUD_PROVIDER}}
|
||||
- **Region**: {{REGION}}
|
||||
- **Hardware specs**:
|
||||
- CPU: {{CPU_SPEC}}
|
||||
- RAM: {{RAM_SPEC}}
|
||||
- Storage: {{STORAGE_SPEC}}
|
||||
- Network: {{NETWORK_SPEC}}
|
||||
|
||||
### Redundancy & HA
|
||||
- [ ] Backup power (UPS/generator)
|
||||
- [ ] Secondary internet connection
|
||||
- [ ] Off-site backup solution
|
||||
- [ ] Remote management (IPMI/iDRAC)
|
||||
|
||||
### Connectivity
|
||||
- **Bandwidth**: {{BANDWIDTH}} Mbps
|
||||
- **Latency to Timmy core**: {{LATENCY}} ms
|
||||
- **Uptime SLA**: {{UPTIME_SLA}}
|
||||
|
||||
---
|
||||
|
||||
## Motivation & Alignment
|
||||
|
||||
### Why do you want to run a Timmy Fleet node?
|
||||
{{MOTIVATION}}
|
||||
|
||||
### What attracts you to decentralized infrastructure?
|
||||
{{DECENTRALIZATION_MOTIVATION}}
|
||||
|
||||
### How does this align with your long-term goals?
|
||||
{{LONG_TERM_GOALS}}
|
||||
|
||||
---
|
||||
|
||||
## Partner Program Interest (Optional)
|
||||
|
||||
### Interested in?
|
||||
- [ ] Referral partner (refer operators, earn commission)
|
||||
- [ ] Channel partner (onboard and train operators)
|
||||
- [ ] Strategic partner (run fleet of 10+ nodes)
|
||||
|
||||
### Existing network
|
||||
{{PARTNER_NETWORK}}
|
||||
|
||||
### Referral pipeline
|
||||
{{REFERRAL_PIPELINE}}
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
### Professional References
|
||||
1. Name: {{REF1_NAME}}
|
||||
Email: {{REF1_EMAIL}}
|
||||
Relationship: {{REF1_RELATION}}
|
||||
|
||||
2. Name: {{REF2_NAME}}
|
||||
Email: {{REF2_EMAIL}}
|
||||
Relationship: {{REF2_RELATION}}
|
||||
|
||||
### Timmy Community Involvement
|
||||
{{COMMUNITY_INVOLVEMENT}}
|
||||
|
||||
---
|
||||
|
||||
## Agreement & Signatures
|
||||
|
||||
### Code of Conduct
|
||||
- [ ] I have read and agree to the Timmy Fleet Operator Code of Conduct
|
||||
- [ ] I understand the uptime and response time requirements
|
||||
- [ ] I agree to the incentive structure and terms
|
||||
|
||||
### Signature
|
||||
**Candidate signature**: ___________________________
|
||||
**Date**: {{SIGNATURE_DATE}}
|
||||
|
||||
**Timmy representative**: ___________________________
|
||||
**Date**: {{TIMPY_SIGN_DATE}}
|
||||
|
||||
---
|
||||
|
||||
## Internal Use Only
|
||||
|
||||
**Interviewer**: {{INTERVIEWER}}
|
||||
**Technical score**: {{TECH_SCORE}}/100
|
||||
**Culture fit**: {{CULTURE_FIT}}/50
|
||||
**Infrastructure audit**: ☐ Pass ☐ Fail
|
||||
**Background check**: ☐ Complete ☐ In-progress
|
||||
|
||||
**Decision**: ☐ Approved ☐ Rejected ☐ Waitlist
|
||||
|
||||
**Comments**: {{INTERNAL_COMMENTS}}
|
||||
|
||||
**Certification ID**: {{CERT_ID}}
|
||||
**Onboarding start date**: {{ONBOARDING_DATE}}
|
||||
175
specs/templates/partner-report.md
Normal file
175
specs/templates/partner-report.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Fleet Partner Monthly Report
|
||||
|
||||
> {{REPORT_MONTH}} {{REPORT_YEAR}}
|
||||
> Partner: {{PARTNER_NAME}} ({{PARTNER_TIER}})
|
||||
> Submitted: {{SUBMISSION_DATE}}
|
||||
|
||||
## Executive Summary
|
||||
|
||||
| Metric | Current Month | Target | Variance |
|
||||
|--------|---------------|--------|----------|
|
||||
| Active nodes managed | {{ACTIVE_NODES}} | {{TARGET_NODES}} | {{NODES_VARIANCE}} |
|
||||
| Fleet uptime | {{UPTIME}}% | 99.5% | {{UPTIME_VARIANCE}}% |
|
||||
| Operator churn rate | {{CHURN_RATE}}% | <10% | {{CHURN_VARIANCE}}% |
|
||||
| Partner-sourced leads | {{LEADS_COUNT}} | {{LEADS_TARGET}} | {{LEADS_VARIANCE}} |
|
||||
| Revenue share earned | {{REVENUE}} | — | — |
|
||||
|
||||
**Key highlights**:
|
||||
{{KEY_HIGHLIGHTS}}
|
||||
|
||||
**Top concerns**:
|
||||
{{KEY_CONCERNS}}
|
||||
|
||||
---
|
||||
|
||||
## Node Performance
|
||||
|
||||
### Node Inventory
|
||||
|
||||
| Node ID | Location | Status | Uptime (30d) | Revenue Share | Issues |
|
||||
|---------|----------|--------|--------------|---------------|---------|
|
||||
| {{NODE_1_ID}} | {{NODE_1_LOC}} | {{NODE_1_STATUS}} | {{NODE_1_UPTIME}}% | ${{NODE_1_REV}} | {{NODE_1_ISSUES}} |
|
||||
| {{NODE_2_ID}} | {{NODE_2_LOC}} | {{NODE_2_STATUS}} | {{NODE_2_UPTIME}}% | ${{NODE_2_REV}} | {{NODE_2_ISSUES}} |
|
||||
| {{NODE_3_ID}} | {{NODE_3_LOC}} | {{NODE_3_STATUS}} | {{NODE_3_UPTIME}}% | ${{NODE_3_REV}} | {{NODE_3_ISSUES}} |
|
||||
|
||||
*Add rows as needed*
|
||||
|
||||
### Top Node Performers
|
||||
1. **{{TOP_NODE_1_ID}}**: {{TOP_NODE_1_UPTIME}}% uptime, zero incidents
|
||||
2. **{{TOP_NODE_2_ID}}**: {{TOP_NODE_2_UPTIME}}% uptime, quickest response times
|
||||
|
||||
### Nodes Requiring Attention
|
||||
1. **{{ATTN_NODE_1_ID}}**: {{ATTN_NODE_1_ISSUE}}
|
||||
2. **{{ATTN_NODE_2_ID}}**: {{ATTN_NODE_2_ISSUE}}
|
||||
|
||||
---
|
||||
|
||||
## Incidents & Resolutions
|
||||
|
||||
### Incident Log
|
||||
|
||||
| Date | Severity | Node(s) | Duration | Root Cause | Resolution |
|
||||
|------|----------|---------|----------|------------|------------|
|
||||
| {{INC1_DATE}} | {{INC1_SEV}} | {{INC1_NODES}} | {{INC1_DURATION}} | {{INC1_CAUSE}} | {{INC1_RES}} |
|
||||
| {{INC2_DATE}} | {{INC2_SEV}} | {{INC2_NODES}} | {{INC2_DURATION}} | {{INC2_CAUSE}} | {{INC2_RES}} |
|
||||
| {{INC3_DATE}} | {{INC3_SEV}} | {{INC3_NODES}} | {{INC3_DURATION}} | {{INC3_CAUSE}} | {{INC3_RES}} |
|
||||
|
||||
*Add rows as needed*
|
||||
|
||||
### Mean Time to Recovery (MTTR)
|
||||
- **P0 incidents**: {{MTTR_P0}} hours
|
||||
- **P1 incidents**: {{MTTR_P1}} hours
|
||||
- **P2 incidents**: {{MTTR_P2}} hours
|
||||
- **P3 incidents**: {{MTTR_P3}} hours
|
||||
|
||||
**Improvement opportunities**:
|
||||
{{MTTR_IMPROVEMENTS}}
|
||||
|
||||
---
|
||||
|
||||
## Operator Management
|
||||
|
||||
### Active Operators
|
||||
|
||||
| Operator | Tier | Nodes Managed | Status | Cert Date |
|
||||
|----------|------|---------------|--------|-----------|
|
||||
| {{OP1_NAME}} | {{OP1_TIER}} | {{OP1_NODES}} | {{OP1_STATUS}} | {{OP1_CERT}} |
|
||||
| {{OP2_NAME}} | {{OP2_TIER}} | {{OP2_NODES}} | {{OP2_STATUS}} | {{OP2_CERT}} |
|
||||
|
||||
### Churn / Attrition
|
||||
- **Departed operators**: {{DEPARTED_COUNT}}
|
||||
- **Departure reasons**: {{DEPARTURE_REASONS}}
|
||||
- **Retention initiatives**: {{RETENTION_INITIATIVES}}
|
||||
|
||||
### Training & Certification
|
||||
- **New certifications**: {{NEW_CERTS}}
|
||||
- **Training hours logged**: {{TRAINING_HOURS}}
|
||||
- **Upcoming recertifications**: {{UPCOMING_RECERTS}}
|
||||
|
||||
---
|
||||
|
||||
## Partner Program Metrics
|
||||
|
||||
### Lead Generation
|
||||
- **Total leads received**: {{TOTAL_LEADS}}
|
||||
- **Qualified leads**: {{QUALIFIED_LEADS}}
|
||||
- **Converted to operators**: {{CONVERTED_OPERATORS}}
|
||||
- **Conversion rate**: {{CONVERSION_RATE}}%
|
||||
- **Partner contribution to total pipeline**: {{PARTNER_PIPELINE_PERCENT}}%
|
||||
|
||||
### Referral Commission
|
||||
- **Referral fee earned**: ${{REFERRAL_FEE}}
|
||||
- **Ongoing revenue share**: ${{ONGOING_SHARE}}
|
||||
- **Total YTD earnings**: ${{YTD_EARNINGS}}
|
||||
|
||||
### Partner Activity
|
||||
- **Marketing events hosted**: {{EVENTS_HOSTED}}
|
||||
- **Training sessions conducted**: {{TRAINING_SESSIONS}}
|
||||
- **Community engagement posts**: {{COMMUNITY_POSTS}}
|
||||
- **Collateral created**: {{COLLATERAL}}
|
||||
|
||||
---
|
||||
|
||||
## Financial Summary
|
||||
|
||||
### Incentive Payouts
|
||||
| Category | Amount | Notes |
|
||||
|----------|--------|-------|
|
||||
| Operator stipends | ${{STIPENDS}} | {{STIPENDS_NOTES}} |
|
||||
| Uptime bonuses | ${{UPTIME_BONUS}} | {{UPTIME_NOTES}} |
|
||||
| Mentorship bonuses | ${{MENTOR_BONUS}} | {{MENTOR_NOTES}} |
|
||||
| Performance bonuses | ${{PERF_BONUS}} | {{PERF_NOTES}} |
|
||||
| Partner commissions | ${{PARTNER_COMM}} | {{PARTNER_NOTES}} |
|
||||
|
||||
**Total payout this month**: ${{TOTAL_PAYOUT}}
|
||||
|
||||
### Cost Efficiency
|
||||
- **Cost per node**: ${{COST_PER_NODE}}
|
||||
- **Cost per uptime hour**: ${{COST_PER_UPTIME_HOUR}}
|
||||
- **Efficiency rating**: {{EFFICIENCY_RATING}}/10
|
||||
|
||||
---
|
||||
|
||||
## Goals & Objectives
|
||||
|
||||
### Next Month Targets
|
||||
1. **Uptime**: {{NEXT_UPTIME_TARGET}}%
|
||||
2. **Qualified leads**: {{NEXT_LEADS_TARGET}}
|
||||
3. **New operators**: {{NEXT_OPS_TARGET}}
|
||||
4. **Incident reduction**: {{NEXT_INCIDENT_TARGET}} incidents
|
||||
|
||||
### Priority Initiatives
|
||||
- {{PRIORITY_1}}
|
||||
- {{PRIORITY_2}}
|
||||
- {{PRIORITY_3}}
|
||||
|
||||
### Support Needed
|
||||
- {{SUPPORT_NEEDED_1}}
|
||||
- {{SUPPORT_NEEDED_2}}
|
||||
|
||||
---
|
||||
|
||||
## Attestation
|
||||
|
||||
By submitting this report, I certify that the information provided is accurate and complete to the best of my knowledge.
|
||||
|
||||
**Submitted by**: {{SUBMITTER_NAME}}
|
||||
**Title**: {{SUBMITTER_TITLE}}
|
||||
**Signature**: ___________________________
|
||||
**Date**: {{SUBMISSION_DATE}}
|
||||
|
||||
**Approved by** (Timmy Core): {{APPROVER_NAME}}
|
||||
**Date**: {{APPROVAL_DATE}}
|
||||
|
||||
---
|
||||
|
||||
## Appendix
|
||||
|
||||
### Supporting Documents
|
||||
- [ ] Ops dashboard screenshots attached
|
||||
- [ ] Incident post-mortems attached
|
||||
- [ ] Training completion records attached
|
||||
- [ ] Financial reconciliation attached
|
||||
|
||||
### Notes
|
||||
{{APPENDIX_NOTES}}
|
||||
@@ -1 +1,12 @@
|
||||
# Timmy core module
|
||||
|
||||
from .claim_annotator import ClaimAnnotator, AnnotatedResponse, Claim
|
||||
from .audit_trail import AuditTrail, AuditEntry
|
||||
|
||||
__all__ = [
|
||||
"ClaimAnnotator",
|
||||
"AnnotatedResponse",
|
||||
"Claim",
|
||||
"AuditTrail",
|
||||
"AuditEntry",
|
||||
]
|
||||
|
||||
156
src/timmy/claim_annotator.py
Normal file
156
src/timmy/claim_annotator.py
Normal file
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Response Claim Annotator — Source Distinction System
|
||||
SOUL.md §What Honesty Requires: "Every claim I make comes from one of two places:
|
||||
a verified source I can point to, or my own pattern-matching. My user must be
|
||||
able to tell which is which."
|
||||
"""
|
||||
|
||||
import re
|
||||
import json
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from typing import Optional, List, Dict
|
||||
|
||||
|
||||
@dataclass
|
||||
class Claim:
|
||||
"""A single claim in a response, annotated with source type."""
|
||||
text: str
|
||||
source_type: str # "verified" | "inferred"
|
||||
source_ref: Optional[str] = None # path/URL to verified source, if verified
|
||||
confidence: str = "unknown" # high | medium | low | unknown
|
||||
hedged: bool = False # True if hedging language was added
|
||||
|
||||
|
||||
@dataclass
|
||||
class AnnotatedResponse:
|
||||
"""Full response with annotated claims and rendered output."""
|
||||
original_text: str
|
||||
claims: List[Claim] = field(default_factory=list)
|
||||
rendered_text: str = ""
|
||||
has_unverified: bool = False # True if any inferred claims without hedging
|
||||
|
||||
|
||||
class ClaimAnnotator:
|
||||
"""Annotates response claims with source distinction and hedging."""
|
||||
|
||||
# Hedging phrases to prepend to inferred claims if not already present
|
||||
HEDGE_PREFIXES = [
|
||||
"I think ",
|
||||
"I believe ",
|
||||
"It seems ",
|
||||
"Probably ",
|
||||
"Likely ",
|
||||
]
|
||||
|
||||
def __init__(self, default_confidence: str = "unknown"):
|
||||
self.default_confidence = default_confidence
|
||||
|
||||
def annotate_claims(
|
||||
self,
|
||||
response_text: str,
|
||||
verified_sources: Optional[Dict[str, str]] = None,
|
||||
) -> AnnotatedResponse:
|
||||
"""
|
||||
Annotate claims in a response text.
|
||||
|
||||
Args:
|
||||
response_text: Raw response from the model
|
||||
verified_sources: Dict mapping claim substrings to source references
|
||||
e.g. {"Paris is the capital of France": "https://en.wikipedia.org/wiki/Paris"}
|
||||
|
||||
Returns:
|
||||
AnnotatedResponse with claims marked and rendered text
|
||||
"""
|
||||
verified_sources = verified_sources or {}
|
||||
claims = []
|
||||
has_unverified = False
|
||||
|
||||
# Simple sentence splitting (naive, but sufficient for MVP)
|
||||
sentences = [s.strip() for s in re.split(r'[.!?]\s+', response_text) if s.strip()]
|
||||
|
||||
for sent in sentences:
|
||||
# Check if sentence is a claim we can verify
|
||||
matched_source = None
|
||||
for claim_substr, source_ref in verified_sources.items():
|
||||
if claim_substr.lower() in sent.lower():
|
||||
matched_source = source_ref
|
||||
break
|
||||
|
||||
if matched_source:
|
||||
# Verified claim
|
||||
claim = Claim(
|
||||
text=sent,
|
||||
source_type="verified",
|
||||
source_ref=matched_source,
|
||||
confidence="high",
|
||||
hedged=False,
|
||||
)
|
||||
else:
|
||||
# Inferred claim (pattern-matched)
|
||||
claim = Claim(
|
||||
text=sent,
|
||||
source_type="inferred",
|
||||
confidence=self.default_confidence,
|
||||
hedged=self._has_hedge(sent),
|
||||
)
|
||||
if not claim.hedged:
|
||||
has_unverified = True
|
||||
|
||||
claims.append(claim)
|
||||
|
||||
# Render the annotated response
|
||||
rendered = self._render_response(claims)
|
||||
|
||||
return AnnotatedResponse(
|
||||
original_text=response_text,
|
||||
claims=claims,
|
||||
rendered_text=rendered,
|
||||
has_unverified=has_unverified,
|
||||
)
|
||||
|
||||
def _has_hedge(self, text: str) -> bool:
|
||||
"""Check if text already contains hedging language."""
|
||||
text_lower = text.lower()
|
||||
for prefix in self.HEDGE_PREFIXES:
|
||||
if text_lower.startswith(prefix.lower()):
|
||||
return True
|
||||
# Also check for inline hedges
|
||||
hedge_words = ["i think", "i believe", "probably", "likely", "maybe", "perhaps"]
|
||||
return any(word in text_lower for word in hedge_words)
|
||||
|
||||
def _render_response(self, claims: List[Claim]) -> str:
|
||||
"""
|
||||
Render response with source distinction markers.
|
||||
|
||||
Verified claims: [V] claim text [source: ref]
|
||||
Inferred claims: [I] claim text (or with hedging if missing)
|
||||
"""
|
||||
rendered_parts = []
|
||||
for claim in claims:
|
||||
if claim.source_type == "verified":
|
||||
part = f"[V] {claim.text}"
|
||||
if claim.source_ref:
|
||||
part += f" [source: {claim.source_ref}]"
|
||||
else: # inferred
|
||||
if not claim.hedged:
|
||||
# Add hedging if missing
|
||||
hedged_text = f"I think {claim.text[0].lower()}{claim.text[1:]}" if claim.text else claim.text
|
||||
part = f"[I] {hedged_text}"
|
||||
else:
|
||||
part = f"[I] {claim.text}"
|
||||
rendered_parts.append(part)
|
||||
return " ".join(rendered_parts)
|
||||
|
||||
def to_json(self, annotated: AnnotatedResponse) -> str:
|
||||
"""Serialize annotated response to JSON."""
|
||||
return json.dumps(
|
||||
{
|
||||
"original_text": annotated.original_text,
|
||||
"rendered_text": annotated.rendered_text,
|
||||
"has_unverified": annotated.has_unverified,
|
||||
"claims": [asdict(c) for c in annotated.claims],
|
||||
},
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
)
|
||||
@@ -8,7 +8,6 @@ ROOT = Path(__file__).resolve().parents[1]
|
||||
PIPELINE_PATH = ROOT / "pipelines" / "codebase_genome.py"
|
||||
NIGHTLY_PATH = ROOT / "scripts" / "codebase_genome_nightly.py"
|
||||
GENOME_PATH = ROOT / "GENOME.md"
|
||||
CRON_PATH = ROOT / "codebase_genome_cron.yml"
|
||||
|
||||
|
||||
def _load_module(path: Path, name: str):
|
||||
@@ -114,17 +113,3 @@ def test_repo_contains_generated_timmy_home_genome() -> None:
|
||||
"## Performance Bottleneck Analysis",
|
||||
):
|
||||
assert snippet in text
|
||||
|
||||
|
||||
def test_repo_contains_nightly_cron_spec_for_genome_rotation() -> None:
|
||||
assert CRON_PATH.exists(), "missing codebase_genome_cron.yml"
|
||||
text = CRON_PATH.read_text(encoding="utf-8")
|
||||
for snippet in (
|
||||
"Codebase Genome Nightly",
|
||||
"scripts/codebase_genome_nightly.py",
|
||||
"--org Timmy_Foundation",
|
||||
"--workspace-root",
|
||||
"--output-root",
|
||||
"--state-path",
|
||||
):
|
||||
assert snippet in text
|
||||
|
||||
103
tests/timmy/test_claim_annotator.py
Normal file
103
tests/timmy/test_claim_annotator.py
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Tests for claim_annotator.py — verifies source distinction is present."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
|
||||
|
||||
from timmy.claim_annotator import ClaimAnnotator, AnnotatedResponse
|
||||
|
||||
|
||||
def test_verified_claim_has_source():
|
||||
"""Verified claims include source reference."""
|
||||
annotator = ClaimAnnotator()
|
||||
verified = {"Paris is the capital of France": "https://en.wikipedia.org/wiki/Paris"}
|
||||
response = "Paris is the capital of France. It is a beautiful city."
|
||||
|
||||
result = annotator.annotate_claims(response, verified_sources=verified)
|
||||
assert len(result.claims) > 0
|
||||
verified_claims = [c for c in result.claims if c.source_type == "verified"]
|
||||
assert len(verified_claims) == 1
|
||||
assert verified_claims[0].source_ref == "https://en.wikipedia.org/wiki/Paris"
|
||||
assert "[V]" in result.rendered_text
|
||||
assert "[source:" in result.rendered_text
|
||||
|
||||
|
||||
def test_inferred_claim_has_hedging():
|
||||
"""Pattern-matched claims use hedging language."""
|
||||
annotator = ClaimAnnotator()
|
||||
response = "The weather is nice today. It might rain tomorrow."
|
||||
|
||||
result = annotator.annotate_claims(response)
|
||||
inferred_claims = [c for c in result.claims if c.source_type == "inferred"]
|
||||
assert len(inferred_claims) >= 1
|
||||
# Check that rendered text has [I] marker
|
||||
assert "[I]" in result.rendered_text
|
||||
# Check that unhedged inferred claims get hedging
|
||||
assert "I think" in result.rendered_text or "I believe" in result.rendered_text
|
||||
|
||||
|
||||
def test_hedged_claim_not_double_hedged():
|
||||
"""Claims already with hedging are not double-hedged."""
|
||||
annotator = ClaimAnnotator()
|
||||
response = "I think the sky is blue. It is a nice day."
|
||||
|
||||
result = annotator.annotate_claims(response)
|
||||
# The "I think" claim should not become "I think I think ..."
|
||||
assert "I think I think" not in result.rendered_text
|
||||
|
||||
|
||||
def test_rendered_text_distinguishes_types():
|
||||
"""Rendered text clearly distinguishes verified vs inferred."""
|
||||
annotator = ClaimAnnotator()
|
||||
verified = {"Earth is round": "https://science.org/earth"}
|
||||
response = "Earth is round. Stars are far away."
|
||||
|
||||
result = annotator.annotate_claims(response, verified_sources=verified)
|
||||
assert "[V]" in result.rendered_text # verified marker
|
||||
assert "[I]" in result.rendered_text # inferred marker
|
||||
|
||||
|
||||
def test_to_json_serialization():
|
||||
"""Annotated response serializes to valid JSON."""
|
||||
annotator = ClaimAnnotator()
|
||||
response = "Test claim."
|
||||
result = annotator.annotate_claims(response)
|
||||
json_str = annotator.to_json(result)
|
||||
parsed = json.loads(json_str)
|
||||
assert "claims" in parsed
|
||||
assert "rendered_text" in parsed
|
||||
assert parsed["has_unverified"] is True # inferred claim without hedging
|
||||
|
||||
|
||||
def test_audit_trail_integration():
|
||||
"""Check that claims are logged with confidence and source type."""
|
||||
# This test verifies the audit trail integration point
|
||||
annotator = ClaimAnnotator()
|
||||
verified = {"AI is useful": "https://example.com/ai"}
|
||||
response = "AI is useful. It can help with tasks."
|
||||
|
||||
result = annotator.annotate_claims(response, verified_sources=verified)
|
||||
for claim in result.claims:
|
||||
assert claim.source_type in ("verified", "inferred")
|
||||
assert claim.confidence in ("high", "medium", "low", "unknown")
|
||||
if claim.source_type == "verified":
|
||||
assert claim.source_ref is not None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_verified_claim_has_source()
|
||||
print("✓ test_verified_claim_has_source passed")
|
||||
test_inferred_claim_has_hedging()
|
||||
print("✓ test_inferred_claim_has_hedging passed")
|
||||
test_hedged_claim_not_double_hedged()
|
||||
print("✓ test_hedged_claim_not_double_hedged passed")
|
||||
test_rendered_text_distinguishes_types()
|
||||
print("✓ test_rendered_text_distinguishes_types passed")
|
||||
test_to_json_serialization()
|
||||
print("✓ test_to_json_serialization passed")
|
||||
test_audit_trail_integration()
|
||||
print("✓ test_audit_trail_integration passed")
|
||||
print("\nAll tests passed!")
|
||||
Reference in New Issue
Block a user