rhodawk-ai-devops-engine / SYSTEM_ANALYSIS_BOOK.md
Rhodawk Bot
feat(openclaude): vendor OpenClaude as headless gRPC daemon, eliminate aider
39e315a
|
Raw History Blame Contribute Delete
79.7 kB

Rhodawk AI β€” System Analysis Book

Complete End-to-End Mechanics, Logic, and Operational Reference

Companion to FOUNDER_PLAYBOOK.md β€” written from the live source tree


Purpose of this document. The existing FOUNDER_PLAYBOOK.md is the canonical investor-facing narrative of what Rhodawk does and why it matters. It remains the source of truth for mission, business model, and high-level architecture and is not modified.

This book sits beside it and answers a different question: how does every piece actually work, end-to-end, in the code as it stands today? It is written for engineers who must run, debug, extend, or migrate the system, and it intentionally crosses every layer β€” from Dockerfile, through provider routing, through each Python module, into the MCP servers, into the test suite, and out to the data on disk.

Where the playbook says "the system has a 5-layer safety pipeline," this book says "process_failing_test in app.py calls sast_gate.run_sast, which forks bandit and semgrep, parses their JSON, returns a SastVerdict dataclass, and on BLOCK raises an early-exit that verification_loop converts into a retry prompt with the SAST critique inlined."

Read the playbook for what and why. Read this book for how.


Table of Contents

  1. Recent Change Log β€” The Last Mile of Fixes
  2. Provider Routing β€” DO Primary, OpenRouter Fallback
  3. Top-Level Topology
  4. Container & Build β€” Dockerfile and Requirements
  5. Process Map at Runtime
  6. Master Orchestrator β€” app.py
  7. Hermes Six-Phase Pipeline β€” hermes_orchestrator.py
  8. Safety Gate Modules
  9. Memory, Learning, and Data Flywheel
  10. Autonomous Operation β€” Harvester, Worker Pool, Job Queue
  11. GitHub Surface β€” github_app.py, webhook_server.py, commit_watcher.py
  12. Red Team & Offense Modules
  13. Notification, Audit, Disclosure, Bounty
  14. Architect Subsystem β€” Tier Routing, Sandbox, Skills, Night Mode
  15. Mythos Subsystem β€” Multi-Agent + RL + 17 MCP Servers
  16. MCP Suite β€” Every Server, Every Domain
  17. Test Suite β€” What Each Test Asserts
  18. Data on Disk β€” Files, SQLite Schemas, Audit Chain
  19. Complete Environment Variable Reference (Updated)
  20. Failure Modes and Recovery Procedures
  21. Security Model β€” Trust Boundaries and Threat Mitigation
  22. Migration Playbook β€” HF Space β†’ Paid Server
  23. Glossary of Internal Names

1. Recent Change Log β€” The Last Mile of Fixes

The Space went through five iterative dependency-and-build fixes after the original FOUNDER_PLAYBOOK.md was written at commit 8a23fcf. These changes do not appear in the playbook because they post-date it. They are critical to understand because they affect both runtime behaviour (provider selection) and build behaviour (how the container is assembled).

Order Commit What changed Why
1 504dde2 Added DigitalOcean Serverless Inference as primary, OpenRouter as fallback, in app.py::run_aider and hermes_orchestrator.py::_hermes_llm_call. Added env vars DO_INFERENCE_API_KEY, DO_INFERENCE_BASE_URL, DO_INFERENCE_MODEL, HERMES_DO_MODEL. Move the hot path off the OpenRouter free tier (rate-limit-prone) onto DigitalOcean's paid llama3.3-70b-instruct. Keep OpenRouter as resilience.
2 1e909b0 Bumped aider-chat to 0.87.0 to fix the module 'litellm' has no attribute 'APIConnectionError' crash. The aider 0.86.x series hard-pinned litellm==1.75.0, whose top-level module was missing public symbols at runtime. This bump failed because aider 0.87.0 was never published to PyPI.
3 da5ce03 Reverted to aider-chat==0.86.2 and added a Dockerfile post-step: pip install --no-cache-dir --upgrade --no-deps "litellm==1.78.5". aider only consumes litellm via getattr and a small public surface; replacing the broken pin with a known-good newer release restores APIConnectionError, _logging, encode, token_counter.
4 ad06d84 Added gitpython==3.1.46 to requirements.txt. aider 0.86.2 hard-pins gitpython; pip's resolver was bouncing between our floor (>=3.1.40) and aider's pin. Pinning explicitly removes the resolver thrash.
5 a913714 Switched the Space SDK from gradio to docker in README.md front-matter and bumped gradio>=5.49.0,<6 in requirements.txt. HF was auto-injecting gradio[oauth,mcp]==5.29.0 because the Space was registered as sdk: gradio. That injection conflicted with aider's pillow==12.1.1 pin. sdk: docker tells HF to use the existing Dockerfile verbatim, with no auto-injection.
6 dd4ccce Removed aider-chat from requirements.txt entirely. The Dockerfile now installs it with --no-deps plus a curated runtime-deps list. Even with sdk: docker, aider's pillow==12.1.1 pin still conflicted with gradio's pillow<12 constraint at the resolver level. --no-deps lets gradio's pillow 11 win, and the curated dep list provides everything aider actually imports at runtime.
7 current Aider eliminated entirely. Vendored OpenClaude headless gRPC daemon now drives every code-generation turn. Two daemons (:50051 DigitalOcean primary, :50052 OpenRouter fallback) launched from entrypoint.sh. New Python bridge openclaude_grpc/ exposes run_openclaude(...) with the legacy (combined_output, exit_code) return contract. run_aider is now a thin alias. The --no-deps + litellm 1.78.5 + curated 27-package list workaround was a fragile patchwork; any aider/gradio/pillow upstream bump could re-break the build. OpenClaude is a single Bun-built bundle with no Python dependency surface and a stable gRPC contract, so the Dockerfile loses ~30 lines of dependency hacks.

Net effect today. The Space SDK is docker. The build runs the Dockerfile end-to-end in three stages: (1) Bun compiles vendor/openclaude/ to dist/cli.mjs; (2) Python 3.12-slim with system tooling, uv, Node and Bun is provisioned; (3) the runtime image generates Python protobuf stubs from vendor/openclaude/src/proto/openclaude.proto into openclaude_grpc/. requirements.txt no longer mentions aider-chat, litellm, configargparse, or any of the other 27 curated aider runtime imports β€” they have all been deleted. entrypoint.sh boots the OpenClaude DO daemon on :50051 and (when an OpenRouter key is present) the OpenClaude OR daemon on :50052, then execs app.py.

Provider behaviour today. When DO_INFERENCE_API_KEY is present the hot path uses DigitalOcean Serverless Inference at https://inference.do-ai.run/v1 with model llama3.3-70b-instruct. OpenRouter is the configured fallback for any non-zero exit, 429, or 5xx. When DO is absent the system silently runs OpenRouter-only.


2. Provider Routing β€” DigitalOcean Primary, OpenRouter Fallback

Two independent code paths need an LLM: OpenClaude (the patch generator, replaces aider) and Hermes (the multi-phase research orchestrator + adversarial reviewer). Both are wired to the same provider chain β€” DigitalOcean Inference primary, OpenRouter fallback.

2.1 OpenClaude path β€” app.py::run_openclaude (alias run_aider)

entrypoint.sh boots two OpenClaude headless gRPC daemons:
  β”Œβ”€ DO_INFERENCE_API_KEY  β†’ :50051  (PRIMARY,  llama3.3-70b-instruct)
  └─ OPENROUTER_API_KEY    β†’ :50052  (FALLBACK, qwen-2.5-coder-32b)

run_openclaude(mcp_config_path, prompt, context_files):
  β”‚
  β”œβ”€β–Ί writes /tmp/mcp_runtime.json (the daemon hot-reloads it per chat)
  β”œβ”€β–Ί forwards prompt + valid context-file list to the bridge
  β”‚
  └─► openclaude_grpc.run_openclaude builds the chain [primary, fallback]:
        for each (port, label, model) in chain:
          client = OpenClaudeClient(host=127.0.0.1, port=port)
          if not client.wait_ready(15s): record + continue
          result = client.chat(message, working_directory=REPO_DIR, model=model)
              β”œβ”€β”€ streams text_chunk β†’ result.stdout
              β”œβ”€β”€ streams tool_start  β†’ result.tool_calls + stdout marker
              β”œβ”€β”€ streams tool_result β†’ result.stdout / .stderr
              β”œβ”€β”€ auto-replies "y" to any action_required prompt
              └── on done event       β†’ exit_code 0
          if exit_code == 0: return (combined_output, 0)
        return (last_output, last_code)

There is no litellm, no --openai-api-base shell argument, no per-model prefix munging. Each daemon is launched with OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL set in its own process environment, so the gRPC client just speaks to whichever port matches the desired provider. The legacy run_aider symbol is preserved as an alias for backwards compatibility with the Hermes/SAST/red-team callers.

2.2 Hermes path β€” hermes_orchestrator.py::_hermes_llm_call

build provider list:
  if DO_INFERENCE_API_KEY:
      providers.append( ("DigitalOcean", DO_INFERENCE_BASE, DO_KEY, HERMES_DO_MODEL, {}) )
  if OPENROUTER_API_KEY:
      providers.append( ("OpenRouter", OPENROUTER_BASE, OR_KEY, HERMES_OR_MODEL, {HTTP-Referer: ...}) )

for (name, base, key, model, extra_headers) in providers:
    POST {base}/chat/completions  with Bearer key, body {model, messages, ...}
    on HTTP 429:
        sleep exponential(attempt) and retry up to N times
    on other 5xx or network error:
        record reason, continue to next provider
    on 200:
        return {"content": choice.message.content, "provider": name, "model": model}

if all providers exhausted:
    return {"error": "all providers failed", "details": [...]}

This is implemented in the helpers _post_chat_completion (raw HTTP + retry), _strip_provider_prefix (litellm-style prefix removal so the DigitalOcean endpoint sees a clean model name), and _hermes_llm_call (orchestrates the chain). The same chain is used by adversarial reviewer calls because they delegate through _hermes_llm_call.

2.3 Why DO first

DigitalOcean's Serverless Inference is paid, predictable, and sized for the hot path. OpenRouter's free tier exists, but rate limits and 429s during adversarial bursts (3 concurrent reviewer models) make it unreliable as a primary. Keeping OpenRouter as a fallback preserves resilience without making the burst case the steady state.

2.4 Required env vars

Var Purpose Default
DO_INFERENCE_API_KEY DigitalOcean Serverless Inference key none β€” if unset, DO path is skipped
DO_INFERENCE_BASE_URL Endpoint base https://inference.do-ai.run/v1
DO_INFERENCE_MODEL Aider's primary model name on DO llama3.3-70b-instruct
HERMES_DO_MODEL Hermes' primary model name on DO (may differ) falls back to DO_INFERENCE_MODEL
OPENROUTER_API_KEY OpenRouter key for fallback + adversarial models none β€” if unset, OR path is skipped
HERMES_OR_MODEL Hermes' OpenRouter fallback model qwen/qwen-2.5-coder-32b-instruct:free

If neither DO nor OpenRouter is configured the system logs a single explicit error per audit. There is no silent degradation β€” by design.


3. Top-Level Topology

The Space is a single Docker container that runs:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Container (port 7860 exposed, 7861 + 7862 internal)                    β”‚
β”‚                                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”‚
β”‚  β”‚ Gradio dashboard     β”‚    β”‚ Webhook server       β”‚                  β”‚
β”‚  β”‚ app.py:demo          β”‚    β”‚ webhook_server.py    β”‚                  β”‚
β”‚  β”‚ port 7860            β”‚    β”‚ port 7861            β”‚                  β”‚
β”‚  β”‚ 10 tabs + chat inbox β”‚    β”‚ /webhook/github      β”‚                  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β”‚
β”‚             β”‚                            β”‚                              β”‚
β”‚             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                              β”‚
β”‚                       β–Ό                                                  β”‚
β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                    β”‚
β”‚           β”‚ enterprise_audit_loop  β”‚  ← background threads dispatched   β”‚
β”‚           β”‚ (app.py)               β”‚     for each repo audit            β”‚
β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                    β”‚
β”‚                     β”‚                                                    β”‚
β”‚                     β–Ό                                                    β”‚
β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                    β”‚
β”‚           β”‚ Worker Pool            β”‚  ← ThreadPoolExecutor, optionally  β”‚
β”‚           β”‚ worker_pool.py         β”‚    process-isolated per job        β”‚
β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                    β”‚
β”‚                     β”‚                                                    β”‚
β”‚                     β–Ό                                                    β”‚
β”‚           process_failing_test() … 15-step healing loop                 β”‚
β”‚                                                                          β”‚
β”‚  Background daemons (started conditionally):                             β”‚
β”‚  β€’ repo_harvester.py  (autonomous target selection, every 6h)           β”‚
β”‚  β€’ commit_watcher.py  (silent-patch detection)                          β”‚
β”‚  β€’ lora_scheduler.py  (training-data export)                            β”‚
β”‚  β€’ red_team_fuzzer.py (when all tests are green)                        β”‚
β”‚  β€’ mythos.api.fastapi_server (optional, port 7863)                      β”‚
β”‚  β€’ public_leaderboard.py (optional, port 7862)                          β”‚
β”‚                                                                          β”‚
β”‚  Persistent storage (mounted at /data):                                  β”‚
β”‚  β€’ job_queue.sqlite                                                      β”‚
β”‚  β€’ training_store.sqlite                                                 β”‚
β”‚  β€’ embedding_index.sqlite (or Qdrant remote)                             β”‚
β”‚  β€’ audit_trail.jsonl                                                     β”‚
β”‚  β€’ harvester_feed.json                                                   β”‚
β”‚  β€’ lora_exports/*.jsonl                                                  β”‚
β”‚  β€’ disclosure_vault/                                                     β”‚
β”‚  β€’ repo/  (cloned target repositories, ephemeral)                        β”‚
β”‚                                                                          β”‚
β”‚  External calls:                                                         β”‚
β”‚  β€’ GitHub API (clone, PR, fork, check_run, merge)                       β”‚
β”‚  β€’ DigitalOcean Inference (primary)                                      β”‚
β”‚  β€’ OpenRouter (fallback + adversarial models)                            β”‚
β”‚  β€’ OpenRouter for adversarial trio (Qwen/Gemma/Mistral)                 β”‚
β”‚  β€’ Telegram & Slack (notifications)                                      β”‚
β”‚  β€’ HackerOne / Bugcrowd (bounty submissions, optional)                  β”‚
β”‚  β€’ NVD / OSV / Snyk (CVE intelligence)                                   β”‚
β”‚  β€’ Shodan, Wayback, crt.sh (recon, optional)                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

4. Container & Build β€” Dockerfile and Requirements

4.1 README.md front-matter (the HF Space manifest)

title: Rhodawk AI DevSecOps Engine
sdk: docker
app_port: 7860
license: apache-2.0

sdk: docker is the critical line. With sdk: gradio, HF Spaces injects gradio[oauth,mcp]==<sdk_version> plus uvicorn, websockets, spaces, and mcp into the build's pip command β€” overriding our explicit pins and breaking the resolver. With sdk: docker, HF runs the Dockerfile verbatim and exposes only app_port to the public preview iframe.

4.2 Dockerfile (logical structure)

FROM python:3.12-slim AS base
# system deps for: git (clone), build-essential (some wheels),
# libpq-dev (psycopg2), libssl/libffi (cryptography), curl, jq, nodejs (MCP servers)
RUN apt-get update && apt-get install -y --no-install-recommends \
        git build-essential libpq-dev libssl-dev libffi-dev curl jq \
        nodejs npm && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY requirements.txt /app/requirements.txt

# Stage A: install everything pip can solve cleanly
RUN pip install --no-cache-dir -r requirements.txt mcp-server-fetch && \
    # Stage B: install aider WITHOUT its strict pins (pillow==12.1.1, litellm==1.75.0)
    pip install --no-cache-dir --no-deps "aider-chat==0.86.2" && \
    # Stage C: replace aider's broken litellm pin with a working release
    pip install --no-cache-dir --upgrade --no-deps "litellm==1.78.5" && \
    # Stage D: provide aider's actual runtime imports (subset of its setup.py)
    pip install --no-cache-dir \
        configargparse jsonschema rich prompt_toolkit pyyaml \
        packaging pathspec diskcache networkx scipy \
        beautifulsoup4 pypandoc flake8 importlib_resources \
        pyperclip pexpect json5 psutil watchfiles socksio \
        mixpanel posthog tree-sitter grep_ast oslex \
        tokenizers google-generativeai openai diff-match-patch \
        soundfile sounddevice

COPY . /app
EXPOSE 7860 7861
CMD ["python", "app.py"]

Why this layered install pattern works. The pip resolver cannot satisfy pillow<12 (gradio) and pillow==12.1.1 (aider) simultaneously. By installing aider with --no-deps we let gradio's pillow 11 win. Aider only imports a small fraction of its declared deps at runtime, and those that matter are installed explicitly in Stage D. The litellm replacement is necessary because the version aider pins (1.75.0) ships a broken module surface β€” litellm.APIConnectionError, litellm._logging, litellm.encode, and litellm.token_counter are all referenced by aider but not exported by 1.75.0. 1.78.5 restores them.

4.3 requirements.txt (resolved set)

The file declares: requests, pytest, uv>=0.7.0, gitpython==3.1.46, gradio>=5.49.0,<6, jinja2==3.1.6, ruff, tenacity, bandit[toml], pip-audit, radon, hypothesis[cli]>=6.100.0, semgrep>=1.45.0, sentence-transformers>=2.7.0, sqlite-vec>=0.1.1, pygithub>=2.3.0, PyJWT>=2.8.0, datasets>=2.19.0, numpy>=1.26.0, psycopg2-binary>=2.9.9, rapidfuzz>=3.0.0, z3-solver>=4.12.0, qdrant-client>=1.9.0, transformers>=4.40.0, torch>=2.2.0, starlette, plus optional FastAPI deps used by the Mythos API server.

aider-chat is intentionally absent β€” see Stage B above.


5. Process Map at Runtime

Process / Thread Started by Lifetime Listens on Purpose
Main Python process python app.py container lifetime β€” imports modules, starts threads, hosts Gradio
Gradio Uvicorn worker Gradio's demo.launch() container lifetime 7860 serves the dashboard UI
Webhook Uvicorn worker webhook_server.start() thread container lifetime 7861 receives GitHub & CI webhooks
Audit threads submit_repo_audit() per request per audit β€” runs enterprise_audit_loop for one repo
Worker pool threads worker_pool.run() inside an audit per audit β€” parallel test repair
Worker subprocesses optional, when RHODAWK_PROCESS_ISOLATE=true per job β€” per-job blast radius isolation
Aider subprocess subprocess.Popen per fix attempt per attempt β€” LLM patch generation
MCP server processes npx/uvx spawned by aider per attempt stdio tools (fetch, github, filesystem, etc.)
Adversarial review threads concurrent.futures in adversarial_reviewer per gate β€” 3-model parallel review
Harvester daemon repo_harvester.start_daemon() if enabled container lifetime β€” autonomous target search
Commit watcher commit_watcher.start_daemon() if enabled container lifetime β€” silent-patch correlation
LoRA scheduler lora_scheduler.start_daemon() if enabled container lifetime β€” training data export trigger
Mythos FastAPI optional container lifetime 7863 external programmatic API
Leaderboard optional container lifetime 7862 public stats Gradio

All daemons are gated by their respective RHODAWK_*_ENABLED env vars and are off by default to keep the cold-start container minimal.


6. Master Orchestrator β€” app.py

app.py is 2,704 lines. It is the wiring file. Conceptually it has six sections.

6.1 Module imports & global config

Lines ~1–200. Imports every other module in the project. Reads ~50 environment variables into module-level constants (DEFAULT_MODEL, MAX_RETRIES, WORKERS, OPENROUTER_API_KEY, DO_INFERENCE_API_KEY, DO_INFERENCE_BASE_URL, DO_INFERENCE_MODEL, FALLBACK_MODELS, RHODAWK_TENANT_ID, audit/disclosure/training paths, adversarial config, conviction thresholds, harvester config, etc.).

6.2 MCP runtime config writer

Lines ~200–470. Reads mcp_config.json (the template), substitutes __INJECTED_BY_APP_AT_RUNTIME__ placeholders with real values from env, and writes the materialized config to /tmp/mcp_runtime.json. Aider is launched with --mcp-config /tmp/mcp_runtime.json so that all MCP tools (fetch-docs, github-manager, filesystem-research, semgrep-sast, …) are available during patch generation.

6.3 run_aider(prompt, repo_dir, model=None) β€” provider chain

Lines ~600–700. The function described in Β§2.1. Chooses the provider list based on which API keys are set, runs aider as a subprocess with the right env and CLI flags, captures stdout/stderr, parses the diff, and returns (stdout, stderr, exit_code, model_used). On non-zero exit it moves to the next provider.

6.4 process_failing_test(...) β€” the 15-step healing loop

The single most important function in the project.

1.  Memory retrieval β€” embedding_memory.retrieve_similar_fixes_v2(failure_text)
2.  Build prompt    β€” verification_loop.build_initial_prompt(test_path, failure, similar)
3.  Aider call      β€” run_aider(prompt, repo_dir)              (provider chain)
4.  Re-run test     β€” runtime.run_tests(test_path)
5.  If still FAIL   β€” append failure delta, build_retry_prompt, GOTO 3 (up to MAX_RETRIES)
6.  SAST gate       β€” sast_gate.run_sast(repo_dir, diff)
7.  If BLOCK        β€” append SAST critique, GOTO 3
8.  Supply chain    β€” supply_chain.run_supply_chain(diff, language)
9.  If BLOCK        β€” append supply-chain critique, GOTO 3
10. Z3 verify       β€” formal_verifier.verify(diff)             (if enabled)
11. If UNSAFE       β€” append Z3 critique, GOTO 3
12. Adversarial     β€” adversarial_reviewer.review_concurrent(diff, failure, repo)
13. If REJECT       β€” append adversarial critique, GOTO 3 (with extended budget)
14. Persist         β€” training_store.record_attempt(...)
15. Return verdict  β€” VerificationResult(success, attempts, verdicts...)

The retry budget is normally MAX_RETRIES (default 5) but is multiplied by ADVERSARIAL_REJECTION_MULTIPLIER when the retry was triggered by an adversarial reject β€” to give the model more chances when the gate is the strict adversarial trio rather than a hard test failure.

6.5 process_audit_test(...) β€” wraps healing with PR + conviction

Calls process_failing_test, then on success:

  • github_app.open_pr_for_repo(repo, branch, title, body) β†’ URL
  • conviction_engine.evaluate(verification_result, adversarial_result, memory_match) β†’ Conviction
  • If Conviction.met and RHODAWK_AUTO_MERGE=true: github_app.merge_pr(url)
  • audit_logger.append({event: PR_OPENED, ...})
  • notifier.notify_pr_opened(repo, url)

6.6 enterprise_audit_loop(repo) β€” the per-audit driver

  • Clones the repo into /data/repo/<sanitized-owner>__<repo>
  • RuntimeFactory.for_repo(repo_dir) returns the right LanguageRuntime
  • runtime.setup_env() (creates venv, installs deps)
  • runtime.discover_tests() returns a list of test file paths
  • Runs each test once to find the failing set
  • Submits each failing test to the worker pool, which calls process_audit_test
  • On completion: red_team_fuzzer.start(repo_dir) if all tests are now green
  • Logs a final AUDIT_COMPLETE event

6.7 Gradio UI

The demo block defines 10 tabs:

  1. Chat Inbox β€” submit owner/repo to start an audit
  2. Live Agent Log β€” real-time tail of the audit log with auto-refresh (3 s)
  3. Audit Trail β€” paginated view of audit_trail.jsonl with filters
  4. Memory Browser β€” search the embedding memory by failure text
  5. Training Store β€” stats and JSONL export trigger
  6. Harvester β€” refresh feed, view ranked candidates, dispatch manually
  7. Findings β€” vulnerability findings from Hermes / red team
  8. Hermes Sessions β€” list of research sessions with phases & VES scores
  9. System Status β€” env-var presence, daemon status, queue depth
  10. Settings β€” read-only display of effective configuration

The Live Agent Log uses a gr.Timer that fires every 3 seconds to repaint the latest 200 lines of the in-memory log buffer.


7. Hermes Six-Phase Pipeline β€” hermes_orchestrator.py

The Hermes orchestrator is a research-and-disclosure pipeline parallel to the test-healing loop. It runs against a target codebase or live host and produces structured VulnerabilityFinding records.

7.1 Phases

# Enum value Module(s) called Output
1 RECON repo_harvester, mythos.mcp.reconnaissance_mcp, subdomain_enum_mcp, httpx_probe_mcp, wayback_mcp, shodan_mcp target inventory + tech fingerprint
2 STATIC taint_analyzer, semantic_extractor, mythos.static.{treesitter_cpg, joern_bridge, codeql_bridge, semgrep_bridge} candidate sinks + CWE hits
3 DYNAMIC fuzzing_engine, harness_factory, mythos.dynamic.{aflpp_runner, klee_runner, qemu_harness, frida_instr, gdb_automation} crashes, traces, coverage
4 EXPLOIT exploit_primitives, mythos.exploit.{pwntools_synth, rop_chain, heap_exploit, privesc_kb} working PoC artifacts
5 CONSENSUS adversarial_reviewer, _run_acts_consensus() model-quorum verdict + ACTS score
6 DISCLOSURE disclosure_vault, bounty_gateway, notifier encrypted writeup + optional submission

7.2 Tool dispatch

Each phase exposes a small set of HermesTool subclasses (ReconTool, TaintTool, SymbolicTool, FuzzTool, ExploitTool, CVETool, CommitWatchTool, SSECTool, ChainAnalyzerTool). The _dispatch_tool(tool_name, args, session) function looks up the class by name and runs it with the session context. Tool output is appended to session.findings and persisted via persist_hermes_session(session).

7.3 Scoring

  • compute_ves(...) β€” Vulnerability Evidence Score: weighted combination of reproducibility, exploitability, impact, and code-confidence signals.
  • compute_acts(model_verdicts) β€” Adversarial Consensus Trust Score: measures inter-model agreement on the diff/exploit, used as an additional gate before disclosure.

7.4 LLM call surface

Every Hermes-triggered LLM call goes through _hermes_llm_call, which implements the DO-primary / OpenRouter-fallback chain described in Β§2.2. This means even adversarial review and disclosure-prose generation benefit from the same provider resilience.

7.5 Session persistence

HermesSession is a dataclass (session_id, target, phase, findings, tool_invocations, started_at, finished_at, provider_history, ves, acts). persist_hermes_session(session) writes a JSON artifact under /data/hermes_sessions/<session_id>.json and appends an audit-trail event. The Gradio "Hermes Sessions" tab reads from this directory.

7.6 TVG β€” Threat-Vector Graph

build_tvg(repo_dir, findings) produces a directed graph of (source β†’ sink, primitive, finding_id) edges suitable for downstream visualization or LLM-driven exploit-chain reasoning. Used by mythos/reasoning/attack_graph.py to compute reachable attack chains.


8. Safety Gate Modules

8.1 sast_gate.py

Runs bandit on Python diffs, semgrep with language-appropriate rule sets on every diff, and a hand-rolled 16-pattern secret scanner over diff additions only. Patterns include: AWS access keys (AKIA[0-9A-Z]{16}), generic API keys (api[_-]?key.*[=:].{20,}), JWTs (eyJ[\w-]+\.[\w-]+\.[\w-]+), private key headers (-----BEGIN (RSA|EC|OPENSSH|PGP) PRIVATE KEY-----), .env-style assignments, OAuth tokens, SSH host keys, hardcoded passwords in connection strings, etc. Returns SastVerdict(level, findings, raw) where level ∈ {PASS, BLOCK}. A single CRITICAL or HIGH finding flips to BLOCK; MEDIUM/LOW are surfaced but advisory.

8.2 supply_chain.py

Two passes per diff:

  1. Known CVEs. Extract added packages from requirements.txt, package.json, pom.xml, go.mod, Cargo.toml, Gemfile. Run the matching CVE scanner: pip-audit, npm audit --json, OWASP dependency-check, govulncheck, cargo audit, bundler-audit.
  2. Typosquatting. For each new package name, compute Levenshtein distance against a 40+ entry list of canonical popular package names. Anything within distance 1 of a popular name (and not equal to it) is flagged as a likely typosquat.

8.3 formal_verifier.py

Three Z3-backed checks over diff additions:

  • Div-by-zero. Pattern-extract expr / divisor and expr % divisor, parse divisor as a Z3 expr, query solver.check(divisor == 0).
  • Negative literal index. Find arr[k] where k is an integer literal, query satisfiability of k < 0.
  • Always-false assert. For each assert expr, walk the surrounding scope for name = literal constants, substitute, query solver.check(Not(expr)). Returns FormalVerdict(SAFE | UNSAFE | SKIP, witnesses). Disabled by default (RHODAWK_Z3_ENABLED=false) because Z3 is a heavy import.

8.4 adversarial_reviewer.py

Sends the diff + failure + repo identity to three reviewer models in parallel via concurrent.futures.ThreadPoolExecutor(max_workers=3). Each model receives an instruction template that demands a strict JSON envelope: {verdict, confidence, critical_issues[], warnings[], retry_guidance}. The reviewer parses each envelope, computes:

  • consensus_votes = Counter(verdicts)
  • consensus_fraction = max(votes.values()) / 3
  • final verdict = majority (β‰₯RHODAWK_CONSENSUS_THRESHOLD of 0.67)
  • critical_issues = union(per-model critical lists)

Sequential mode (RHODAWK_ADVERSARY_SEQUENTIAL=true) runs the same models serially. Used as a fallback when concurrent calls hit OpenRouter's per-key concurrency limits.

8.5 conviction_engine.py

Seven boolean criteria, all of which must be true to allow autonomous merge:

  1. adversarial.verdict == APPROVE (not just CONDITIONAL)
  2. adversarial.confidence β‰₯ RHODAWK_CONVICTION_CONFIDENCE (default 0.92)
  3. adversarial.consensus_fraction β‰₯ RHODAWK_CONVICTION_CONSENSUS (0.85)
  4. verification.attempts == 1 (fixed on first try)
  5. sast.findings == [] (zero SAST findings)
  6. supply_chain.added_packages == [] (no new deps)
  7. memory.best_match.similarity β‰₯ RHODAWK_CONVICTION_MEMORY_SIM AND memory.best_match.merged_by_human == True

Returns Conviction(met: bool, missing_criteria: list, score: float). The score is a weighted combination useful for analytics even when met is False.

8.6 taint_analyzer.py

Lightweight per-language source/sink dataflow analyzer used during the Hermes STATIC phase (not in the patch healing loop). Tracks tainted variables from common sources (HTTP request data, file reads, env vars, CLI args) to dangerous sinks (eval, subprocess, raw SQL, pickle.loads, yaml.load, etree.fromstring).

8.7 symbolic_engine.py

Wraps Z3 for richer symbolic execution beyond the single-statement checks in formal_verifier.py. Used by Hermes SymbolicTool.

8.8 vuln_classifier.py

Maps raw findings (from SAST tools, taint, fuzzers) to CWE IDs and estimated CVSS using a rule table. Output feeds disclosure_vault and bounty_gateway.


9. Memory, Learning, and Data Flywheel

9.1 embedding_memory.py

Two interchangeable backends:

SQLite + MiniLM (default). sentence-transformers/all-MiniLM-L6-v2 for encoding. Embeddings stored in a SQLite table (id, failure_norm, embedding BLOB, fix_diff, outcome, repo, ts) and queried by cosine similarity using sqlite-vec. Lightweight, runs entirely in-process, no external service.

Qdrant + CodeBERT (optional). microsoft/codebert-base for code-aware encoding. Vectors pushed to a Qdrant collection (HNSW index) β€” local or remote. Switched on via RHODAWK_EMBEDDING_BACKEND=qdrant.

Public API used by the rest of the system:

  • retrieve_similar_fixes_v2(failure_text, top_k=5) β†’ list of past fixes
  • record_fix(failure_text, diff, outcome, repo) β†’ persists for future retrieval
  • rebuild_embedding_index() β†’ re-encode entire training_store on demand

Failure normalization strips file paths, line numbers, addresses, and hex IDs so that semantically identical failures across different repos collide in embedding space.

9.2 memory_engine.py

Legacy v1 store. Exact-key lookup by normalized failure signature. Kept for cold-start scenarios where the embedding index has zero entries.

9.3 training_store.py

SQLite database (/data/training_store.sqlite) with two tables:

  • fix_attempts(id, ts, repo, test_path, failure, diff, model, attempt, success)
  • fix_patterns(signature, success_count, attempt_count, last_seen)

Entry points:

  • record_attempt(...) β€” every fix attempt, success or failure
  • export_training_data(jsonl_path) β€” writes {"messages": [{"role": "system", ...}, {"role": "user", ...}, {"role": "assistant", "content": diff}]} β€” directly compatible with HuggingFace TRL/PEFT SFT trainers.
  • get_statistics() β€” counts for the dashboard

9.4 lora_scheduler.py

Background daemon. Polls the training store. When either RHODAWK_LORA_MIN_SAMPLES (default 50) new successful fix pairs accumulate or RHODAWK_LORA_MAX_AGE_HOURS (default 168 = 1 week) elapse since the last export, it calls training_store.export_training_data() to a new JSONL file under /data/lora_exports/lora_<timestamp>.jsonl.

9.5 knowledge_rag.py

Retrieval-augmented generation helper for Hermes. Indexes long-form security documentation (the architect/skills/*.md library plus optionally fetched CVE writeups) and exposes a retrieve(query, top_k) helper that the research planner can call to ground exploit reasoning in vetted prior art.


10. Autonomous Operation β€” Harvester, Worker Pool, Job Queue

10.1 repo_harvester.py

  • Background daemon, gated by RHODAWK_HARVESTER_ENABLED=true.
  • Cycle period: RHODAWK_HARVESTER_POLL_SECONDS (default 21600 = 6 h).
  • Per cycle: GitHub Search API for repos in 7 supported languages (language:python, language:javascript, …) with at least RHODAWK_HARVESTER_MIN_STARS (default 100) and recent activity.
  • Cross-references each candidate's check-runs API to find currently failing CI.
  • Scoring: 0.35*log(stars+1)/log(MAX_STARS+1) + 0.40*recency_score + 0.25*failing_check_count_score.
  • Persists ranked feed to /data/harvester_feed.json.
  • Dispatches the top RHODAWK_HARVESTER_MAX_REPOS (default 20) targets into the audit loop via submit_repo_audit().

10.2 worker_pool.py

  • ThreadPoolExecutor(max_workers=RHODAWK_WORKERS) (default 8).
  • When RHODAWK_PROCESS_ISOLATE=true: each job runs in multiprocessing.get_context("fork").Process with a result Queue and a hard timeout of RHODAWK_ISOLATE_TIMEOUT seconds (default 600).
  • On timeout: process is terminate()d then kill()ed if still alive, job is marked FAILED, audit-trail event recorded.
  • Falls back gracefully to in-process execution if fork is not available (e.g., Windows host β€” irrelevant to HF but matters for self-hosters).

10.3 job_queue.py

  • SQLite-backed (/data/job_queue.sqlite).
  • Schema: (tenant_id, repo, test_path) UNIQUE β†’ (status, pr_url, model_version, started_at, updated_at, attempts, last_error).
  • States: PENDING, RUNNING, DONE, FAILED, SAST_BLOCKED, ADVERSARIAL_REJECTED, CONVICTION_NOT_MET.
  • Idempotency: a DONE row is skipped on resubmission. A RUNNING row older than 1 hour (stale, from a crashed previous container) is reset to PENDING after a branch-cleanup pass.
  • prune_done_jobs(older_than_hours=72) keeps the table from growing unbounded.

11. GitHub Surface β€” github_app.py, webhook_server.py, commit_watcher.py

11.1 github_app.py

  • PAT mode (default). Uses GITHUB_TOKEN directly via PyGithub.
  • GitHub App mode. Uses RHODAWK_APP_ID + RHODAWK_APP_PRIVATE_KEY to issue a 10-minute JWT, exchange it for a 1-hour installation token, and refresh on each call. Enterprise-grade auth.
  • open_pr_for_repo(repo, branch, title, body) β€” chooses standard or fork mode based on RHODAWK_FORK_MODE.
  • Standard mode. Push branch to upstream, open PR upstreamβ†’upstream.
  • Fork mode. fork_repo(repo) (waits for GitHub's async fork to complete by polling), push branch to fork, open cross-repo PR forkβ†’upstream. This is what enables fixing repos you don't own.
  • merge_pr(url) β€” used by the conviction engine when criteria are met.

11.2 webhook_server.py

HTTP server on port 7861. Endpoints:

  • POST /webhook/github β€” validates X-Hub-Signature-256 HMAC against RHODAWK_WEBHOOK_SECRET. Handles push and check_run events.
  • POST /webhook/ci β€” generic CI failure trigger (token in header).
  • POST /webhook/trigger β€” manual trigger (admin token).
  • GET /webhook/health β€” liveness.
  • GET /webhook/queue β€” current queue depth + last 20 events. Per-IP token bucket rate limiter (default 30 req/min per IP).

11.3 commit_watcher.py

Daemon for silent-patch detection. Polls a configured set of high-value upstream repos for new commits. Heuristics flag commits whose message says "fix" / "security" / "CVE" but which have no associated public advisory β€” a known pattern for CAD (Coordinated Asynchronous Disclosure) or under-the-radar security fixes. Findings are routed to disclosure_vault for downstream attribution.

11.4 chain_analyzer.py

Walks PR commit chains and groups related commits into "fix series" so that the training store records the full fix, not just the first commit in a multi-commit fix. Important for accurate (failure β†’ fix) pair generation.


12. Red Team & Offense Modules

12.1 red_team_fuzzer.py

1,561 lines. The Blue Team-to-Red Team transition. When process_audit_test finishes and all tests are green, this module:

  • Generates property-based tests using Hypothesis strategies inferred from function signatures.
  • Runs them with pytest --hypothesis-show-statistics.
  • Captures shrunken counterexamples.
  • Feeds the counterexamples into a CEGIS loop: each refuted property becomes the spec for the next attack synthesis round.
  • Zero-day candidates are written as JSON artifacts under /data/findings/ and handed back to the Blue Team healing loop so the bug becomes a fix.

12.2 fuzzing_engine.py

Lower-level fuzzing primitives consumed by both red_team_fuzzer.py and the Hermes DYNAMIC phase. Bridges to mythos/dynamic/aflpp_runner.py, klee_runner.py, and qemu_harness.py when those are available.

12.3 harness_factory.py

Generates fuzz harnesses from function signatures: type inference, seed corpus extraction from existing tests, AFL++/libFuzzer wrapper emission. Used by red_team_fuzzer.py and Hermes.

12.4 exploit_primitives.py

Catalogs reusable exploitation primitives: arbitrary read/write, function-pointer overwrite, format-string leak, integer-overflow ladder, heap-grooming templates. Each primitive has a match(finding) β†’ bool predicate and an apply(finding) β†’ ExploitArtifact synthesizer.

12.5 cve_intel.py

NVD/OSV/Snyk lookup for prior-art correlation. Given a finding, returns the closest known CVE and similarity score so the disclosure isn't a duplicate.


13. Notification, Audit, Disclosure, Bounty

13.1 notifier.py

  • Telegram via Bot API (TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID).
  • Slack via incoming webhook (SLACK_WEBHOOK_URL).
  • All sends are non-blocking (background threads with bounded queue).
  • Templates for: AUDIT_START, TEST_FAIL, PR_CREATED, PATCH_FAIL, SAST_BLOCK, AUDIT_COMPLETE, ZERO_DAY_FOUND, DISCLOSURE_SUBMITTED.

13.2 audit_logger.py

Append-only JSONL at /data/audit_trail.jsonl. Each entry:

{
  "ts": "2026-04-22T12:34:56Z",
  "event": "ADVERSARIAL_REVIEW",
  "tenant": "acme",
  "repo": "owner/name",
  "payload": {...},
  "prev_hash": "sha256:...",
  "hash": "sha256:..."
}

prev_hash is the hash of the previous entry; hash is the SHA-256 of the current entry (excluding the hash field itself). The genesis entry has prev_hash = "0"*64.

verify_chain_integrity() walks the file from genesis, recomputes each hash, and asserts equality. Any tamper anywhere breaks the chain at the tampered point and every subsequent entry. SOC 2 / ISO 27001 evidence artifact.

13.3 disclosure_vault.py

Encrypted at-rest storage for vulnerability writeups. Uses Fernet with a key derived from DISCLOSURE_VAULT_PASSPHRASE. Each entry: finding metadata + full PoC + suggested fix + CVE correlation. Read API requires the same passphrase. Used by Hermes DISCLOSURE phase before any public submission.

13.4 bounty_gateway.py

Programmatic submission to HackerOne, Bugcrowd, Intigriti, YesWeHack via their REST APIs. Submission requires:

  • Finding has passed adversarial CONSENSUS phase
  • VES β‰₯ configured floor
  • Manual approval flag (default: required) OR RHODAWK_BOUNTY_AUTO_SUBMIT=true (off by default β€” kept off in production)

13.5 oss_guardian.py

Stewardship layer for fixes pushed to OSS repos. Tracks PR status, maintainer responses, and time-to-merge. Feeds analytics for the public leaderboard and for the conviction engine's "merged by human" signal.

13.6 oss_target_scorer.py

Scoring helper used by both the harvester and the public leaderboard to rank repos by community impact (stars, dependents, ecosystem centrality).

13.7 public_leaderboard.py

Standalone Gradio interface (port 7862) showing PRs submitted, PRs merged, repos touched, patterns learned, zero-days reported. All numbers read directly from audit_trail.jsonl and training_store.sqlite β€” no synthetic metrics.

13.8 swebench_harness.py

Runs the Rhodawk healing loop against SWE-bench Verified instances. Reports pass@1. Same pipeline as production β€” no special-cased logic. Provides reproducible benchmarks for investor/customer claims.


14. Architect Subsystem β€” Tier Routing, Sandbox, Skills, Night Mode

The architect/ package is the higher-order control layer that sits above the per-test healing loop and decides which model, which skill, and which sandbox each task should use.

14.1 architect/model_router.py

Five-tier model router. Each task is classified by complexity and routed to the cheapest tier that can satisfy it:

  • Tier 1 β€” Ultra. DeepSeek 3.2, MiniMax 2.5. Used for global strategy and multi-repo planning.
  • Tier 2 β€” Strong. Qwen 2.5 Coder 32B. Default patch generator.
  • Tier 3 β€” Balanced. Llama 3.3 70B (DigitalOcean), DeepSeek V3, Gemma 2 27B. Adversarial reviewers.
  • Tier 4 β€” Lite. Mistral 7B, Gemma 2 9B. Cheap second-opinion calls.
  • Tier 5 β€” Local. Embedded MiniLM/CodeBERT for embeddings β€” no LLM call.

The router consumes (task_type, code_size_tokens, security_sensitivity, required_capabilities) and returns a routing decision with provider, model, and expected_cost_usd.

14.2 architect/sandbox.py

SandboxManager β€” abstraction over (a) plain subprocess, (b) bwrap (bubblewrap) namespace isolation, (c) Firecracker microVM (planned). Currently used in subprocess + bwrap modes for any tool execution that must not touch the host filesystem outside /tmp/sandbox/<id>/.

14.3 architect/skill_registry.py

Registers the 28 skill markdown files under architect/skills/ as discoverable knowledge units. Each skill file declares: domain (api-security, container-escape, smart-contract-audit, …), required tools, suggested model tier, and reference references. The registry exposes find_skills(query) β†’ list[Skill] for the planner.

14.4 architect/skills/

28 long-form security playbooks covering: api-security, ai-ml-security, automotive-security, aviation-aerospace, binary-analysis, browser-engine security, ci-cd-pipeline-attack, cloud-security, container-escape, cryptographic-implementation, cryptography-attacks, firmware-analysis, hardware-protocols, ics-scada, linux-kernel-exploitation, llm-system- prompt-injection, memory-safety, mobile-android, mobile-ios, network- protocol, reverse-engineering, rf-radio-security, satellite-comms, smart-contract-audit, supply-chain, vibe-coded-app-hunter, web-security advanced, zero-day-research, plus bb-methodology-claude.md and bug-bounty-reference-index.md.

14.5 architect/nightmode.py

The autonomous "night mode" loop. When enabled, between human-driven audits the system pulls in scope from connected bug-bounty platforms (via mythos.mcp.scope_parser_mcp), enumerates targets, and runs Hermes pipelines against authorized scope only β€” submitting findings through bounty_gateway. Hard-gated by ARCHITECT_NIGHTMODE_ENABLED=true and a per-platform scope-acceptance check.

14.6 architect/godmode_consensus.py

A heavier-weight consensus protocol used by night mode that runs the adversarial trio AND a Tier 1 model, requiring unanimous agreement before any external submission. Higher false-negative rate, near-zero false-positive rate β€” appropriate when the action is irreversible.

14.7 architect/master_redteam_prompt.py

Centralizes the master prompt used by the red-team modules. Externalizing the prompt makes it tunable without code changes and auditable for prompt-injection resistance.

14.8 architect/parseltongue.py

Internal DSL for declaring multi-step research plans. Compiles to a sequence of HermesTool invocations. Used by the Mythos planner agent.

14.9 architect/embodied_bridge.py

Bridge to the EmbodiedOS / OpenClaw / Hermes Agent runtime when present externally. Stubs gracefully when EmbodiedOS is not reachable.

14.10 architect/rl_feedback_loop.py

RL feedback collector. After each fix, an outcome reward is computed (merge=+1, rejected=-0.5, never-reviewed-after-30-days=-0.1) and the plan-level statistics are updated for the planner's policy table.


15. Mythos Subsystem β€” Multi-Agent + RL + 17 MCP Servers

mythos/ is the deepest research layer β€” designed to close the gap between Rhodawk's deterministic 6-phase pipeline and a Mythos-class autonomous research agent.

15.1 mythos/MYTHOS_PLAN.md

Living blueprint document mapping Rhodawk's gaps to concrete Mythos modules. Read this first to understand the design intent.

15.2 mythos/agents/

  • base.py β€” abstract Agent class with observe, plan, act.
  • planner.py β€” generates research plans from a target description. Uses the Tier 1 model + RL policy table.
  • explorer.py β€” enumeration agent for recon and surface mapping.
  • executor.py β€” runs concrete tools (calls into mythos/static, mythos/dynamic, mythos/exploit).
  • orchestrator.py β€” top-level coordinator that wires planner β†’ explorer β†’ executor β†’ consensus and persists the trace.

15.3 mythos/static/

  • treesitter_cpg.py β€” Tree-sitter–based Code Property Graph builder.
  • joern_bridge.py β€” Joern CPG queries for taint chains.
  • codeql_bridge.py β€” CodeQL pack runner with predefined query sets.
  • semgrep_bridge.py β€” Semgrep with curated security rule packs.

15.4 mythos/dynamic/

  • aflpp_runner.py β€” AFL++ harness execution.
  • klee_runner.py β€” KLEE symbolic execution wrapper.
  • qemu_harness.py β€” full-system QEMU with snapshot/restore.
  • frida_instr.py β€” Frida runtime instrumentation sessions.
  • gdb_automation.py β€” scripted GDB triage of crashes.

15.5 mythos/exploit/

  • pwntools_synth.py β€” pwntools-based PoC synthesis.
  • rop_chain.py β€” ROP gadget search + chain assembly via ROPGadget.
  • heap_exploit.py β€” heap exploitation primitives (tcache, fastbin, unsafe-unlink).
  • privesc_kb.py β€” privilege escalation knowledge base + matcher.

15.6 mythos/learning/

  • rl_planner.py β€” RL planner using the reward signal from architect/rl_feedback_loop.py.
  • curriculum.py β€” curriculum learning over progressively harder vulnerability classes.
  • episodic_memory.py β€” episodic store of full (target, plan, action, observation, reward) trajectories.
  • mlflow_tracker.py β€” MLflow run tracking for training experiments.
  • lora_adapters.py β€” LoRA adapter loader; lets the system swap in domain-specific adapters per task.

15.7 mythos/reasoning/

  • probabilistic.py β€” probabilistic attack-vector reasoning.
  • attack_graph.py β€” attack-graph construction over (asset, action, result) triples; computes minimum-cost reachable goal paths.

15.8 mythos/api/

  • fastapi_server.py β€” optional FastAPI server (port 7863) exposing /audit, /research, /findings, /leaderboard JSON APIs.
  • auth.py β€” bearer-token auth middleware.
  • schemas.py β€” Pydantic request/response models.
  • webhooks.py β€” webhook delivery on async events.

15.9 mythos/skills/

  • registry.py β€” runtime skill discovery and ranking. Bridges to architect/skill_registry.py to expose skills via MCP.

15.10 mythos/integration.py

Top-level wiring. Initializes the Mythos subsystem from app.py's startup. If Mythos modules fail to import (optional dependencies missing), it logs a warning and lets the system continue without the Mythos features.

15.11 mythos/diagnostics.py

Self-test CLI. python -m mythos.diagnostics prints which agents, MCP servers, and external tools are reachable, and exits non-zero if any required component is broken. Used by the mythos.__main__ entry point and by container health checks.

15.12 mythos/__main__.py

Allows python -m mythos to launch the Mythos subsystem standalone.


16. MCP Suite β€” Every Server, Every Domain

The mcp_config.json template declares 34 MCP server entries (with some duplicates β€” see note below). Aider is launched with the rendered /tmp/mcp_runtime.json so all of these tools become callable during patch generation. Hermes also calls them directly.

16.1 Generic / shared servers

Server Command Purpose
fetch-docs uvx mcp-server-fetch HTTP fetch with SSRF allow-list (60+ domains)
github-manager npx @modelcontextprotocol/server-github full GitHub API
filesystem-research npx @modelcontextprotocol/server-filesystem RO access to /data/repo, /tmp/research, /tmp/findings
memory-store npx @modelcontextprotocol/server-memory persistent KG of exploit chains
sequential-thinking npx @modelcontextprotocol/server-sequential-thinking structured CoT
web-search npx @modelcontextprotocol/server-brave-search Brave search API
git-forensics npx @modelcontextprotocol/server-git deep git-history analysis
postgres-intelligence npx @modelcontextprotocol/server-postgres findings DB queries
sqlite-findings npx @modelcontextprotocol/server-sqlite local findings DB

16.2 Security tooling shells (mcp-server-shell allow-list)

Server Allowed binaries Purpose
nuclei-scanner nuclei,nuclei-templates DAST + CVE templates
semgrep-sast semgrep taint + CWE + secrets
trufflehog-secrets trufflehog git-history secret scan
bandit-sast bandit Python AST SAST
pip-audit-sca pip-audit,pip OSV-backed Python SCA
osv-scanner osv-scanner multi-ecosystem SCA
z3-formal-verifier python3 Z3 verification scripts
hypothesis-fuzzer python3,pytest,hypothesis property-based testing
atheris-fuzzer python3,atheris coverage-guided fuzzing
angr-symbolic python3 binary symbolic execution
radon-complexity radon complexity / attack surface
ruff-linter ruff anti-pattern detection
aider-patcher aider patch synthesis (recursive β€” careful)

16.3 Intelligence + bounty

Server Purpose
cve-intelligence NVD / CVE.org / OSV fetch
bounty-platform HackerOne/Bugcrowd/Intigriti/YesWeHack APIs
supply-chain-monitor PyPI/npm/crates typosquatting + dep-confusion

16.4 Mythos-native MCP servers (Python modules)

Server Module Purpose
reconnaissance-mcp mythos.mcp.reconnaissance_mcp language/framework/dep fingerprinting + attack surface
static-analysis-mcp mythos.mcp.static_analysis_mcp Tree-sitter CPG + Joern + CodeQL + Semgrep
dynamic-analysis-mcp mythos.mcp.dynamic_analysis_mcp AFL++ + KLEE + QEMU + Frida + GDB
exploit-generation-mcp mythos.mcp.exploit_generation_mcp Pwntools + ROP + heap + privesc
vulnerability-database-mcp mythos.mcp.vulnerability_database_mcp NVD/OSV/Exploit-DB lookup
web-security-mcp mythos.mcp.web_security_mcp OWASP ZAP + nuclei + sqlmap orchestration
browser-agent-mcp mythos.mcp.browser_agent_mcp Playwright live browser
scope-parser-mcp mythos.mcp.scope_parser_mcp bug-bounty scope ingestion
subdomain-enum-mcp mythos.mcp.subdomain_enum_mcp subfinder + amass + dnsx + crt.sh
httpx-probe-mcp mythos.mcp.httpx_probe_mcp concurrent HTTP probing + tech fingerprint
shodan-mcp mythos.mcp.shodan_mcp Shodan REST passive recon
wayback-mcp mythos.mcp.wayback_mcp Wayback / CommonCrawl historical URL recall
frida-runtime-mcp mythos.mcp.frida_runtime_mcp live Frida instrumentation
ghidra-bridge-mcp mythos.mcp.ghidra_bridge_mcp headless Ghidra / radare2 bridge
can-bus-mcp mythos.mcp.can_bus_mcp automotive CAN-bus + UDS (ISO 14229)
sdr-analysis-mcp mythos.mcp.sdr_analysis_mcp GNU Radio / rtl_sdr RF capture

Duplicate-key note. mcp_config.json currently declares scope-parser-mcp, subdomain-enum-mcp, wayback-mcp, httpx-probe-mcp, and shodan-mcp twice. JSON parse semantics use the last value, so the ARCHITECT-flavored variants (with env injections for HackerOne/Shodan tokens) are what wins at runtime. The earlier entries are dead weight and could be removed in a future cleanup commit.

16.5 Runtime materialization

On startup, app.py reads mcp_config.json, recursively replaces every __INJECTED_BY_APP_AT_RUNTIME__ placeholder with the corresponding env var value (OPENROUTER_API_KEY, BRAVE_API_KEY, DATABASE_URL, HACKERONE_API_TOKEN, BUGCROWD_API_TOKEN, INTIGRITI_API_TOKEN, SHODAN_API_KEY, NVD_API_KEY, NUCLEI_API_KEY, SEMGREP_APP_TOKEN, GITHUB_PERSONAL_ACCESS_TOKEN), drops any server whose required secret is missing, and writes the result to /tmp/mcp_runtime.json. Aider launches with --mcp-config /tmp/mcp_runtime.json. Secrets are never committed.


17. Test Suite β€” What Each Test Asserts

tests/ contains 9 test modules and one conftest.py.

Test file What it asserts
test_audit_chain.py The SHA-256 audit chain in audit_logger.py rejects tampering. Writes synthetic events, mutates one entry, expects verify_chain_integrity() to flag the break point.
test_job_queue.py Idempotency guarantees: identical (tenant, repo, test_path) submissions don't duplicate. Stale RUNNING rows older than 1h reset to PENDING. Status transitions are valid.
test_mcp_servers_load.py The MCP runtime config materializes correctly: all __INJECTED__ placeholders are resolved or the server is dropped. No secrets leak into the rendered file.
test_model_router.py The 5-tier router produces deterministic routing for the same input. Tier promotions happen on capability misses. Cost estimates are monotonic with tier.
test_mythos_diagnostics.py mythos.diagnostics.run_diagnostics() exits 0 in healthy state and non-zero when any required Mythos module is missing.
test_nightmode_smoke.py Architect night mode initializes without external services and refuses to act when no scope source is configured.
test_scope_parser.py The HackerOne / Bugcrowd / Intigriti scope parsers correctly partition assets into IN_SCOPE / OUT_OF_SCOPE buckets with edge cases (wildcards, port specs, regex policies).
test_skill_registry.py The 28 skill files in architect/skills/ are all parseable, declare required metadata, and are discoverable by find_skills(query).
test_webhook_hmac.py webhook_server.py rejects requests with invalid HMAC signatures and accepts valid ones. Constant-time comparison is used (no timing side channel).

conftest.py defines fixtures for: temporary /data overrides, mock GitHub API, mock OpenRouter API, in-memory SQLite for the job queue and training store, and a synthetic failing-test repo factory.


18. Data on Disk β€” Files, SQLite Schemas, Audit Chain

/data/
β”œβ”€β”€ job_queue.sqlite                 # job_queue.py
β”œβ”€β”€ training_store.sqlite            # training_store.py (fix_attempts, fix_patterns)
β”œβ”€β”€ embedding_index.sqlite           # embedding_memory.py SQLite backend
β”œβ”€β”€ memory_engine.sqlite             # legacy v1 pattern memory
β”œβ”€β”€ rhodawk_findings.db              # MCP sqlite-findings server
β”œβ”€β”€ audit_trail.jsonl                # SHA-256 chained event log
β”œβ”€β”€ harvester_feed.json              # ranked candidate repos
β”œβ”€β”€ disclosure_vault/
β”‚   └── <finding_id>.fernet          # encrypted writeups
β”œβ”€β”€ lora_exports/
β”‚   └── lora_<timestamp>.jsonl       # SFT-ready training data
β”œβ”€β”€ hermes_sessions/
β”‚   └── <session_id>.json            # persisted Hermes research sessions
β”œβ”€β”€ findings/
β”‚   └── <finding_id>.json            # raw findings from red team / Mythos
β”œβ”€β”€ repo/
β”‚   └── <owner>__<name>/             # cloned target repos (ephemeral)
β”œβ”€β”€ nuclei-templates/                # nuclei DAST templates cache
└── research/                        # MCP filesystem-research scratch

/tmp/:

/tmp/
β”œβ”€β”€ mcp_runtime.json                 # rendered MCP config (with secrets)
β”œβ”€β”€ sandbox/<id>/                    # bwrap sandbox roots
└── findings/                        # MCP filesystem-research output

18.1 SQLite schemas (effective)

-- training_store.sqlite
CREATE TABLE fix_attempts (
  id INTEGER PRIMARY KEY,
  ts TEXT NOT NULL,
  repo TEXT NOT NULL,
  test_path TEXT NOT NULL,
  failure TEXT NOT NULL,
  diff TEXT,
  model TEXT,
  attempt INTEGER,
  success INTEGER NOT NULL
);
CREATE INDEX ix_fix_attempts_repo ON fix_attempts(repo);
CREATE INDEX ix_fix_attempts_success ON fix_attempts(success);

CREATE TABLE fix_patterns (
  signature TEXT PRIMARY KEY,
  success_count INTEGER NOT NULL DEFAULT 0,
  attempt_count INTEGER NOT NULL DEFAULT 0,
  last_seen TEXT NOT NULL
);

-- job_queue.sqlite
CREATE TABLE jobs (
  tenant_id TEXT NOT NULL,
  repo TEXT NOT NULL,
  test_path TEXT NOT NULL,
  status TEXT NOT NULL,
  pr_url TEXT,
  model_version TEXT,
  started_at TEXT,
  updated_at TEXT NOT NULL,
  attempts INTEGER NOT NULL DEFAULT 0,
  last_error TEXT,
  PRIMARY KEY (tenant_id, repo, test_path)
);

-- embedding_index.sqlite (sqlite-vec)
CREATE TABLE embeddings (
  id INTEGER PRIMARY KEY,
  failure_norm TEXT,
  embedding BLOB,           -- vector serialized via sqlite-vec
  fix_diff TEXT,
  outcome TEXT,
  repo TEXT,
  ts TEXT
);
CREATE VIRTUAL TABLE embedding_index USING vec0(
  embedding float[384]
);

18.2 Audit chain entry shape

{
  "ts":  "2026-04-22T13:14:15.123Z",
  "event": "ADVERSARIAL_REVIEW",
  "tenant": "default",
  "repo": "owner/name",
  "test_path": "tests/test_x.py",
  "payload": {
    "verdict": "APPROVE",
    "confidence": 0.93,
    "consensus_fraction": 1.0,
    "models": ["qwen-2.5-7b", "gemma-2-9b", "mistral-7b"],
    "critical_issues": [],
    "warnings": ["minor style nit"]
  },
  "prev_hash": "sha256:f3a1...c0",
  "hash": "sha256:9b22...ee"
}

19. Complete Environment Variable Reference (Updated)

This table supersedes the playbook's reference for everything related to inference providers and the build-changed paths.

19.1 Required for any meaningful run

Var Purpose
GITHUB_TOKEN PAT with repo scope (or use App mode below)
OPENROUTER_API_KEY needed for fallback + adversarial trio
DO_INFERENCE_API_KEY strongly recommended β€” enables paid DO primary

19.2 Inference providers (new since playbook)

Var Default Description
DO_INFERENCE_API_KEY β€” DigitalOcean Serverless Inference key
DO_INFERENCE_BASE_URL https://inference.do-ai.run/v1 DO endpoint
DO_INFERENCE_MODEL llama3.3-70b-instruct Aider's primary model on DO
HERMES_DO_MODEL ${DO_INFERENCE_MODEL} Hermes' primary model on DO
HERMES_OR_MODEL qwen/qwen-2.5-coder-32b-instruct:free Hermes' OpenRouter fallback
OPENROUTER_API_KEY β€” Fallback + adversarial models

19.3 Models, retries, consensus

Var Default Description
RHODAWK_MODEL (computed: DO if available else OR free) Aider primary model
RHODAWK_ADVERSARY_MODEL openrouter/qwen/qwen-2.5-7b-instruct:free lead reviewer
RHODAWK_CONSENSUS_THRESHOLD 0.67 majority fraction
RHODAWK_ADVERSARY_SEQUENTIAL false serial vs concurrent reviewers
MAX_RETRIES 5 healing-loop retry budget
ADVERSARIAL_REJECTION_MULTIPLIER 2 extra retries when reject reason is adversarial

19.4 Conviction (auto-merge)

Var Default Description
RHODAWK_AUTO_MERGE false enable autonomous merge
RHODAWK_CONVICTION_CONFIDENCE 0.92 min adversarial confidence
RHODAWK_CONVICTION_CONSENSUS 0.85 min consensus fraction
RHODAWK_CONVICTION_MEMORY_SIM 0.85 min memory similarity

19.5 Memory backend

Var Default Description
RHODAWK_EMBEDDING_BACKEND sqlite sqlite or qdrant
RHODAWK_EMBEDDING_MODEL all-MiniLM-L6-v2 SQLite backend encoder
RHODAWK_CODEBERT_MODEL microsoft/codebert-base Qdrant backend encoder
QDRANT_URL β€” Qdrant remote URL when not local
QDRANT_API_KEY β€” Qdrant cloud auth

19.6 LoRA scheduler

Var Default Description
RHODAWK_LORA_ENABLED false enable scheduler
RHODAWK_LORA_MIN_SAMPLES 50 min new fixes per export
RHODAWK_LORA_MAX_AGE_HOURS 168 max time between exports
RHODAWK_LORA_OUTPUT_DIR /data/lora_exports JSONL destination

19.7 Harvester

Var Default Description
RHODAWK_HARVESTER_ENABLED false start daemon
RHODAWK_HARVESTER_POLL_SECONDS 21600 cycle interval
RHODAWK_HARVESTER_MIN_STARS 100 min stars to consider
RHODAWK_HARVESTER_MAX_REPOS 20 targets per cycle

19.8 Worker pool & isolation

Var Default Description
RHODAWK_WORKERS 8 parallel workers
RHODAWK_PROCESS_ISOLATE false per-job subprocess isolation
RHODAWK_ISOLATE_TIMEOUT 600 per-job timeout (seconds)

19.9 GitHub

Var Default Description
GITHUB_TOKEN β€” PAT auth
RHODAWK_FORK_MODE false enable fork-and-PR for any public repo
RHODAWK_FORK_OWNER (authenticated user) org to fork into
RHODAWK_APP_ID β€” GitHub App ID
RHODAWK_APP_PRIVATE_KEY β€” GitHub App PEM
RHODAWK_WEBHOOK_SECRET β€” HMAC for /webhook/github

19.10 Adversarial / red team / formal

Var Default Description
RHODAWK_RED_TEAM_ENABLED true enable CEGIS fuzzer when all tests green
RHODAWK_Z3_ENABLED false enable Z3 formal verification gate

19.11 Architect / Mythos / night mode

Var Default Description
ARCHITECT_NIGHTMODE_ENABLED false enable autonomous night mode
ARCHITECT_GODMODE_REQUIRED true require unanimous consensus before external action
MYTHOS_API_ENABLED false start FastAPI on 7863
MYTHOS_API_TOKEN β€” bearer token for the FastAPI
DISCLOSURE_VAULT_PASSPHRASE β€” Fernet key derivation passphrase
RHODAWK_BOUNTY_AUTO_SUBMIT false auto-submit to bounty platforms

19.12 External intelligence

Var Description
BRAVE_API_KEY Brave Search MCP
SHODAN_API_KEY Shodan recon MCP
NVD_API_KEY NVD CVE intelligence MCP
NUCLEI_API_KEY Nuclei templates premium feed
SEMGREP_APP_TOKEN Semgrep Cloud rules
HACKERONE_USERNAME, HACKERONE_API_TOKEN, HACKERONE_API_KEY HackerOne
BUGCROWD_API_TOKEN Bugcrowd
INTIGRITI_API_TOKEN Intigriti

19.13 Notifications

Var Description
TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID Telegram alerts
SLACK_WEBHOOK_URL Slack alerts

19.14 Multitenancy

Var Default Description
RHODAWK_TENANT_ID default namespace prefix for jobs, audits, exports

20. Failure Modes and Recovery Procedures

Symptom Most likely cause Recovery
Build fails on pillow resolver conflict requirements.txt re-lists aider-chat Remove it; aider must be --no-deps only in Dockerfile
Build fails with gradio[oauth,mcp]==5.29.0 injection Space SDK reverted to gradio Confirm sdk: docker in README.md front-matter
Aider crashes litellm has no attribute APIConnectionError litellm 1.75.0 reinstalled by transitive dep Re-run the pip install --no-deps litellm==1.78.5 step or pin in Dockerfile
All LLM calls fail with 429 OpenRouter rate-limited and DO not configured Set DO_INFERENCE_API_KEY; calls will route to DO first
All LLM calls fail with No inference provider configured Both DO_INFERENCE_API_KEY and OPENROUTER_API_KEY missing Set at least one; restart container
Webhook 401 from GitHub RHODAWK_WEBHOOK_SECRET mismatch Re-set the secret in the GitHub repo's webhook config to match
Audit hangs forever on a single test Aider subprocess wedged Set RHODAWK_PROCESS_ISOLATE=true and RHODAWK_ISOLATE_TIMEOUT=600
embedding_index.sqlite corrupted Hard kill mid-write Delete the file; rebuild_embedding_index() will reconstruct from training_store.sqlite
Audit chain integrity fails Manual edit of audit_trail.jsonl The chain is correctly rejecting tamper. To start a new chain, archive and remove the file; a new genesis entry will be written.
Conviction never fires Memory has zero matches at threshold β‰₯0.85 Expected on cold start; lower RHODAWK_CONVICTION_MEMORY_SIM to 0.75 in early life if you want auto-merge sooner β€” but be honest with yourself about what you're trading.
MCP server fails to spawn npx/uvx missing or required env var unset Check container has nodejs+npm and uvx (uv); confirm injected env var is present at startup
Harvester feed empty Token lacks search scope or rate limited Confirm GITHUB_TOKEN has public_repo; raise RHODAWK_HARVESTER_MIN_STARS
Mythos FastAPI 401 Wrong bearer token Confirm MYTHOS_API_TOKEN matches client header

21. Security Model β€” Trust Boundaries and Threat Mitigation

21.1 Trust boundaries

  1. Container ↔ host. Container runs as root in the Docker image but touches only /data (mounted) and /tmp (ephemeral). No host paths leak.
  2. Container ↔ target repo. Cloned repos live in /data/repo/<id>/. They are treated as untrusted: scripts in target repos are never python <target_script>'d directly β€” only the runtime's allowed commands (pytest, npm test, go test, …) are invoked.
  3. Container ↔ LLM provider. Code snippets and failure traces are sent over the wire to DigitalOcean Inference and OpenRouter. This is the primary data-leakage surface β€” controlled by deployment mode (HF Spaces is multi-tenant; self-hosted is single-tenant).
  4. MCP fetch ↔ internet. fetch-docs and similar fetch MCPs use FETCH_ALLOWED_DOMAINS allow-lists to prevent SSRF against internal services.
  5. Webhook ↔ public internet. All webhook endpoints validate HMAC signatures with constant-time comparison. Per-IP rate limiting in front. No untrusted JSON is unpickled.

21.2 Threat mitigation by attack

Threat Mitigation
Prompt injection in target source Multi-model adversarial review catches divergent reactions; SAST/supply-chain catch the resulting bad diffs
LLM-introduced typosquat (reqeusts) supply_chain.py Levenshtein typosquatting check
LLM-introduced backdoor SAST + adversarial trio + zero-package-introduction conviction criterion
Tampered audit trail SHA-256 chain detects any post-hoc edit
Webhook spoofing HMAC-SHA256 with constant-time compare
Secret leakage via logs Secret scanner runs over diffs; mcp_runtime.json is in /tmp not the repo
Subprocess sandbox escape Runtime command allow-lists; optional bwrap; planned Firecracker
Bug-bounty submission of duplicate finding cve_intel.py correlation + manual approval default
Auto-merge of an unsafe diff 7 conviction criteria; default OFF; passes only the cleanest fixes
Provider compromise (e.g., OpenRouter MITM) TLS verification; provider chain falls back rather than blindly trusting bad responses

21.3 Secret hygiene

  • mcp_config.json is a template with __INJECTED_BY_APP_AT_RUNTIME__ placeholders. The realized config goes to /tmp/mcp_runtime.json which is not committed and is recreated on each startup.
  • .env-style files are never read; everything goes through os.getenv. HF Spaces / Docker -e are the only injection paths.
  • The disclosure vault uses Fernet with key derived from DISCLOSURE_VAULT_PASSPHRASE. Lose that passphrase, lose the vault β€” by design.

22. Migration Playbook β€” HF Space β†’ Paid Server

The Space is a great PoC environment but has hard limits: ephemeral storage on free tier, single-container topology, and shared GPU resources. The paid-server migration target is a single Linux box (DigitalOcean Droplet, Hetzner CCX, or AWS EC2) running the same Docker image.

22.1 Pre-migration checklist

  • All env vars from Β§19 documented and stored in a secrets manager
  • /data directory size on Space measured (du -sh /data) and provisioned on the new host (recommend β‰₯50 GB to start)
  • DigitalOcean Inference key budgeted for the expected request volume
  • Webhook secret rotated for the new endpoint URL
  • DNS or reverse-proxy plan in place if you want HTTPS in front of ports 7860/7861/7862/7863
  • Decision made on Qdrant: keep SQLite/MiniLM (simpler) or stand up a Qdrant container alongside (better recall on large corpora)

22.2 Migration steps

  1. Snapshot data. On the Space:
    tar czf /tmp/rhodawk-data.tgz /data
    
    Download via the HF Spaces file browser or via git LFS.
  2. Provision the new host. Install Docker + Docker Compose. Mount a block volume at /var/lib/rhodawk-data.
  3. Restore data.
    sudo mkdir -p /var/lib/rhodawk-data
    sudo tar xzf rhodawk-data.tgz -C /var/lib/rhodawk-data --strip-components=1
    
  4. Build the image (or pull from a private registry if you've pushed one):
    git clone https://huggingface.co/spaces/Architect8999/rhodawk-ai-devops-engine
    cd rhodawk-ai-devops-engine
    docker build -t rhodawk:latest .
    
  5. Run with all env vars + persistent volume.
    docker run -d --name rhodawk \
      -p 7860:7860 -p 7861:7861 \
      -v /var/lib/rhodawk-data:/data \
      -e DO_INFERENCE_API_KEY=... \
      -e OPENROUTER_API_KEY=... \
      -e GITHUB_TOKEN=... \
      -e RHODAWK_WEBHOOK_SECRET=... \
      -e RHODAWK_TENANT_ID=acme \
      -e RHODAWK_AUTO_MERGE=false \
      -e RHODAWK_HARVESTER_ENABLED=true \
      rhodawk:latest
    
  6. Update GitHub webhook payload URL to the new host.
  7. Verify the audit chain integrity on the new host:
    docker exec rhodawk python -c \
      "from audit_logger import verify_chain_integrity; verify_chain_integrity()"
    
  8. Run a known-failing-test repo through the chat inbox or a webhook to confirm end-to-end.

22.3 Recommended additions on paid host

  • Reverse proxy (Caddy or Traefik) terminating TLS, fronting 7860/7861.
  • Docker Compose file checking the container into a restart-policy.
  • cron or systemd timer that runs docker exec rhodawk python -m mythos.diagnostics every 5 minutes and pages on non-zero exit.
  • Off-host backup of /var/lib/rhodawk-data nightly. The training store is the proprietary asset β€” losing it loses the moat.
  • Optional Qdrant container (qdrant/qdrant:latest) on a private network, with RHODAWK_EMBEDDING_BACKEND=qdrant + QDRANT_URL=http://qdrant:6333.

22.4 What changes at scale (later)

  • Move job_queue from SQLite to PostgreSQL (psycopg2-binary already installed, see mcp_config.json postgres-intelligence server).
  • Move audit trail to S3 with versioning (the SHA-256 chain remains; only the storage backend changes).
  • Replace single-host worker pool with a queue + worker fleet (Redis/RQ or Celery).
  • Replace Gradio dashboard with a Next.js front-end calling the mythos.api.fastapi_server JSON API.

23. Glossary of Internal Names

Name Meaning
Aider Open-source AI pair-programming CLI, used as the patch generator
APIConnectionError Symbol that aider expects in litellm; missing in 1.75.0 β€” fixed by upgrading to 1.78.5
ACTS Adversarial Consensus Trust Score (Hermes)
Audit chain The SHA-256-chained JSONL log in audit_logger.py
Architect Higher-order control package (architect/) β€” tier router, sandbox, skills, night mode
CEGIS Counterexample-Guided Inductive Synthesis (red team loop)
Conviction The 7-criteria gate that allows autonomous merge
DO DigitalOcean Serverless Inference (the new primary inference provider)
EmbodiedOS External persistent runtime that hosts OpenClaw + Hermes Agent (optional bridge)
Fork mode Forking any public repo and PR'ing back β€” enables fixing repos you don't own
Godmode consensus Stricter consensus (adversarial trio + Tier 1) used by night mode
Harvester Daemon that finds its own targets on GitHub
Hermes The 6-phase research orchestrator (hermes_orchestrator.py)
LoRA scheduler Daemon that exports successful (failure, fix) pairs as SFT JSONL
MCP Model Context Protocol β€” Anthropic's tool-server protocol
Mythos The deepest research package (mythos/) β€” multi-agent + RL + 17 native MCP servers
Mythos-level Aspirational target capability class β€” autonomous frontier vulnerability research
Night mode Autonomous bug-bounty loop running between human-driven audits
OpenClaw Local-gateway component of EmbodiedOS
OR OpenRouter (the new fallback inference provider)
PoC Proof of Concept (exploit)
Provider chain The ordered list [DO_primary, OpenRouter_fallback] consulted on every LLM call
Sandbox bwrap (or planned Firecracker) isolation for tool execution
SAST gate Static analysis security gate (bandit + semgrep + secret patterns)
Supply chain gate CVE + typosquatting check on newly added packages
Tier 1–5 Five-tier model router classification
Training store SQLite DB of every fix attempt β€” the proprietary data asset
TVG Threat-Vector Graph
VES Vulnerability Evidence Score (Hermes)
Z3 gate Optional formal-verification gate using the Z3 SMT solver

Rhodawk AI β€” System Analysis Book Companion to FOUNDER_PLAYBOOK.md v4.0 (which remains the canonical investor narrative) Generated from the live source tree; last updated to reflect the DigitalOcean primary / OpenRouter fallback inference chain, the --no-deps aider install pattern, and the Docker-SDK Space configuration.